added timed thread, added batch, cleaned code
changed starting value to false
This commit is contained in:
@@ -234,6 +234,7 @@ server:
|
|||||||
USE_STARTING_AP_4: false #Use early-GMS 4/4/4/4 starting stats. To overcome AP shortage, this gives 4AP/5AP at 1st/2nd job advancements.
|
USE_STARTING_AP_4: false #Use early-GMS 4/4/4/4 starting stats. To overcome AP shortage, this gives 4AP/5AP at 1st/2nd job advancements.
|
||||||
USE_AUTOBAN: false #Commands the server to detect infractors automatically.
|
USE_AUTOBAN: false #Commands the server to detect infractors automatically.
|
||||||
USE_AUTOBAN_LOG: true #Log autoban related messages. Still logs even with USE_AUTOBAN disabled.
|
USE_AUTOBAN_LOG: true #Log autoban related messages. Still logs even with USE_AUTOBAN disabled.
|
||||||
|
USE_EXP_GAIN_LOG: false #Logs characters exp gains; logs world rate & coupon exp, total gained exp, and current exp, level can be calculated from "ExpTable".
|
||||||
USE_AUTOSAVE: true #Enables server autosaving feature (saves characters to DB each 1 hour).
|
USE_AUTOSAVE: true #Enables server autosaving feature (saves characters to DB each 1 hour).
|
||||||
USE_SERVER_AUTOASSIGNER: false #HeavenMS-builtin autoassigner, uses algorithm based on distributing AP accordingly with required secondary stat on equipments.
|
USE_SERVER_AUTOASSIGNER: false #HeavenMS-builtin autoassigner, uses algorithm based on distributing AP accordingly with required secondary stat on equipments.
|
||||||
USE_REFRESH_RANK_MOVE: true
|
USE_REFRESH_RANK_MOVE: true
|
||||||
|
|||||||
@@ -21484,6 +21484,17 @@ CREATE TABLE IF NOT EXISTS `worldtransfers` (
|
|||||||
INDEX (characterid)
|
INDEX (characterid)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `characterexplogs` (
|
||||||
|
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
`world_exp_rate` INT,
|
||||||
|
`exp_coupon` INT,
|
||||||
|
`gained_exp` BIGINT,
|
||||||
|
`current_exp` INT,
|
||||||
|
`exp_gain_time` DATETIME,
|
||||||
|
`charid` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
FOREIGN KEY (`charid`) REFERENCES `characters`(`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
||||||
|
|
||||||
ALTER TABLE `dueyitems`
|
ALTER TABLE `dueyitems`
|
||||||
ADD CONSTRAINT `dueyitems_ibfk_1` FOREIGN KEY (`PackageId`) REFERENCES `dueypackages` (`PackageId`) ON DELETE CASCADE;
|
ADD CONSTRAINT `dueyitems_ibfk_1` FOREIGN KEY (`PackageId`) REFERENCES `dueypackages` (`PackageId`) ON DELETE CASCADE;
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import scripting.AbstractPlayerInteraction;
|
|||||||
import scripting.event.EventInstanceManager;
|
import scripting.event.EventInstanceManager;
|
||||||
import scripting.item.ItemScriptManager;
|
import scripting.item.ItemScriptManager;
|
||||||
import server.*;
|
import server.*;
|
||||||
|
import server.ExpLogger.ExpLogRecord;
|
||||||
import server.ItemInformationProvider.ScriptedItem;
|
import server.ItemInformationProvider.ScriptedItem;
|
||||||
import server.events.Events;
|
import server.events.Events;
|
||||||
import server.events.RescueGaga;
|
import server.events.RescueGaga;
|
||||||
@@ -150,6 +151,7 @@ public class Character extends AbstractCharacterObject {
|
|||||||
private final AtomicInteger gachaexp = new AtomicInteger();
|
private final AtomicInteger gachaexp = new AtomicInteger();
|
||||||
private final AtomicInteger meso = new AtomicInteger();
|
private final AtomicInteger meso = new AtomicInteger();
|
||||||
private final AtomicInteger chair = new AtomicInteger(-1);
|
private final AtomicInteger chair = new AtomicInteger(-1);
|
||||||
|
private long totalExpGained = 0;
|
||||||
private int merchantmeso;
|
private int merchantmeso;
|
||||||
private BuddyList buddylist;
|
private BuddyList buddylist;
|
||||||
private EventInstanceManager eventInstance = null;
|
private EventInstanceManager eventInstance = null;
|
||||||
@@ -234,7 +236,7 @@ public class Character extends AbstractCharacterObject {
|
|||||||
private final List<Integer> viptrockmaps = new ArrayList<>();
|
private final List<Integer> viptrockmaps = new ArrayList<>();
|
||||||
private Map<String, Events> events = new LinkedHashMap<>();
|
private Map<String, Events> events = new LinkedHashMap<>();
|
||||||
private PartyQuest partyQuest = null;
|
private PartyQuest partyQuest = null;
|
||||||
private final List<Pair<DelayedQuestUpdate, Object[]>> npcUpdateQuests = new LinkedList<>();
|
private final List<Pair<DelayedQuestUpdate, Object[]>> npcUpdateQuests = new LinkedList<>();
|
||||||
private Dragon dragon = null;
|
private Dragon dragon = null;
|
||||||
private Ring marriageRing;
|
private Ring marriageRing;
|
||||||
private int marriageItemid = -1;
|
private int marriageItemid = -1;
|
||||||
@@ -3092,6 +3094,7 @@ public class Character extends AbstractCharacterObject {
|
|||||||
leftover = nextExp - Integer.MAX_VALUE;
|
leftover = nextExp - Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
updateSingleStat(Stat.EXP, exp.addAndGet((int) total));
|
updateSingleStat(Stat.EXP, exp.addAndGet((int) total));
|
||||||
|
totalExpGained += total;
|
||||||
if (show) {
|
if (show) {
|
||||||
announceExpGain(gain, equip, party, inChat, white);
|
announceExpGain(gain, equip, party, inChat, white);
|
||||||
}
|
}
|
||||||
@@ -3108,6 +3111,20 @@ public class Character extends AbstractCharacterObject {
|
|||||||
gainExpInternal(leftover, equip, party, false, inChat, white);
|
gainExpInternal(leftover, equip, party, false, inChat, white);
|
||||||
} else {
|
} else {
|
||||||
lastExpGainTime = System.currentTimeMillis();
|
lastExpGainTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
if (YamlConfig.config.server.USE_EXP_GAIN_LOG) {
|
||||||
|
ExpLogRecord expLogRecord = new ExpLogger.ExpLogRecord(
|
||||||
|
getWorldServer().getExpRate(),
|
||||||
|
expCoupon,
|
||||||
|
totalExpGained,
|
||||||
|
exp.get(),
|
||||||
|
new Timestamp(lastExpGainTime),
|
||||||
|
id
|
||||||
|
);
|
||||||
|
ExpLogger.putExpLogRecord(expLogRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
totalExpGained = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ public class ServerConfig {
|
|||||||
public boolean USE_STARTING_AP_4;
|
public boolean USE_STARTING_AP_4;
|
||||||
public boolean USE_AUTOBAN;
|
public boolean USE_AUTOBAN;
|
||||||
public boolean USE_AUTOBAN_LOG;
|
public boolean USE_AUTOBAN_LOG;
|
||||||
|
public boolean USE_EXP_GAIN_LOG;
|
||||||
public boolean USE_AUTOSAVE;
|
public boolean USE_AUTOSAVE;
|
||||||
public boolean USE_SERVER_AUTOASSIGNER;
|
public boolean USE_SERVER_AUTOASSIGNER;
|
||||||
public boolean USE_REFRESH_RANK_MOVE;
|
public boolean USE_REFRESH_RANK_MOVE;
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package server;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import static java.util.concurrent.TimeUnit.*;
|
||||||
|
|
||||||
|
import config.YamlConfig;
|
||||||
|
import tools.DatabaseConnection;
|
||||||
|
|
||||||
|
public class ExpLogger {
|
||||||
|
private static final LinkedBlockingQueue<ExpLogRecord> expLoggerQueue = new LinkedBlockingQueue<>();
|
||||||
|
private static final short EXP_LOGGER_THREAD_SLEEP_DURATION_SECONDS = 60;
|
||||||
|
private static final short EXP_LOGGER_THREAD_SHUTDOWN_WAIT_DURATION_MINUTES = 5;
|
||||||
|
|
||||||
|
public record ExpLogRecord(int worldExpRate, int expCoupon, long gainedExp, int currentExp,Timestamp expGainTime, int charid) {}
|
||||||
|
|
||||||
|
public static void putExpLogRecord(ExpLogRecord expLogRecord) {
|
||||||
|
try {
|
||||||
|
expLoggerQueue.put(expLogRecord);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static private ScheduledExecutorService schdExctr = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
|
||||||
|
@Override
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private static Runnable saveExpLoggerToDBRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try (Connection con = DatabaseConnection.getConnection();
|
||||||
|
PreparedStatement ps = con.prepareStatement("INSERT INTO characterexplogs (world_exp_rate, exp_coupon, gained_exp, current_exp, exp_gain_time, charid) VALUES (?, ?, ?, ?, ?, ?)")) {
|
||||||
|
|
||||||
|
List<ExpLogRecord> drainedExpLogs = new ArrayList<>();
|
||||||
|
expLoggerQueue.drainTo(drainedExpLogs);
|
||||||
|
for (ExpLogRecord expLogRecord : drainedExpLogs) {
|
||||||
|
ps.setInt(1, expLogRecord.worldExpRate);
|
||||||
|
ps.setInt(2, expLogRecord.expCoupon);
|
||||||
|
ps.setLong(3, expLogRecord.gainedExp);
|
||||||
|
ps.setInt(4, expLogRecord.currentExp);
|
||||||
|
ps.setTimestamp(5, expLogRecord.expGainTime);
|
||||||
|
ps.setInt(6, expLogRecord.charid);
|
||||||
|
ps.addBatch();
|
||||||
|
}
|
||||||
|
ps.executeBatch();
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
sqle.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private static void startExpLogger() {
|
||||||
|
schdExctr.schedule(saveExpLoggerToDBRunnable, EXP_LOGGER_THREAD_SLEEP_DURATION_SECONDS, SECONDS);
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
|
stopExpLogger();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean stopExpLogger() {
|
||||||
|
schdExctr.shutdown();
|
||||||
|
try {
|
||||||
|
schdExctr.awaitTermination(EXP_LOGGER_THREAD_SHUTDOWN_WAIT_DURATION_MINUTES, MINUTES);
|
||||||
|
Thread runThreadBeforeShutdown = new Thread(saveExpLoggerToDBRunnable);
|
||||||
|
runThreadBeforeShutdown.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
runThreadBeforeShutdown.start();
|
||||||
|
return true;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
if (YamlConfig.config.server.USE_EXP_GAIN_LOG) {
|
||||||
|
startExpLogger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user