Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03802666ef | ||
|
|
ecd155f2bb | ||
|
|
d6147d5191 | ||
|
|
7ef471f1e2 | ||
|
|
c3404d296a | ||
|
|
c145a53688 | ||
|
|
c744935dd0 | ||
|
|
90b44c3a8b | ||
|
|
60a44252ea |
@@ -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_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_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_SERVER_AUTOASSIGNER: false #HeavenMS-builtin autoassigner, uses algorithm based on distributing AP accordingly with required secondary stat on equipments.
|
||||
USE_REFRESH_RANK_MOVE: true
|
||||
|
||||
@@ -21484,6 +21484,17 @@ CREATE TABLE IF NOT EXISTS `worldtransfers` (
|
||||
INDEX (characterid)
|
||||
) 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`
|
||||
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.item.ItemScriptManager;
|
||||
import server.*;
|
||||
import server.ExpLogger.ExpLogRecord;
|
||||
import server.ItemInformationProvider.ScriptedItem;
|
||||
import server.events.Events;
|
||||
import server.events.RescueGaga;
|
||||
@@ -150,6 +151,7 @@ public class Character extends AbstractCharacterObject {
|
||||
private final AtomicInteger gachaexp = new AtomicInteger();
|
||||
private final AtomicInteger meso = new AtomicInteger();
|
||||
private final AtomicInteger chair = new AtomicInteger(-1);
|
||||
private long totalExpGained = 0;
|
||||
private int merchantmeso;
|
||||
private BuddyList buddylist;
|
||||
private EventInstanceManager eventInstance = null;
|
||||
@@ -3092,6 +3094,7 @@ public class Character extends AbstractCharacterObject {
|
||||
leftover = nextExp - Integer.MAX_VALUE;
|
||||
}
|
||||
updateSingleStat(Stat.EXP, exp.addAndGet((int) total));
|
||||
totalExpGained += total;
|
||||
if (show) {
|
||||
announceExpGain(gain, equip, party, inChat, white);
|
||||
}
|
||||
@@ -3108,6 +3111,20 @@ public class Character extends AbstractCharacterObject {
|
||||
gainExpInternal(leftover, equip, party, false, inChat, white);
|
||||
} else {
|
||||
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_AUTOBAN;
|
||||
public boolean USE_AUTOBAN_LOG;
|
||||
public boolean USE_EXP_GAIN_LOG;
|
||||
public boolean USE_AUTOSAVE;
|
||||
public boolean USE_SERVER_AUTOASSIGNER;
|
||||
public boolean USE_REFRESH_RANK_MOVE;
|
||||
|
||||
@@ -45,6 +45,8 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
@@ -122,40 +124,12 @@ public final class MTSHandler extends AbstractPacketHandler {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
int oldmax = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||||
int oldday = calendar.get(Calendar.DAY_OF_MONTH) + 7;
|
||||
if (oldmax < oldday) {
|
||||
if (calendar.get(Calendar.MONTH) + 2 > 12) {
|
||||
year = calendar.get(Calendar.YEAR) + 1;
|
||||
month = 1;
|
||||
calendar.set(year, month, 1);
|
||||
day = oldday - oldmax;
|
||||
} else {
|
||||
month = calendar.get(Calendar.MONTH) + 2;
|
||||
year = calendar.get(Calendar.YEAR);
|
||||
calendar.set(year, month, 1);
|
||||
day = oldday - oldmax;
|
||||
}
|
||||
} else {
|
||||
day = calendar.get(Calendar.DAY_OF_MONTH) + 7;
|
||||
month = calendar.get(Calendar.MONTH);
|
||||
year = calendar.get(Calendar.YEAR);
|
||||
}
|
||||
String date = year + "-";
|
||||
if (month < 10) {
|
||||
date += "0" + month + "-";
|
||||
} else {
|
||||
date += month + "-";
|
||||
}
|
||||
if (day < 10) {
|
||||
date += "0" + day;
|
||||
} else {
|
||||
date += day + "";
|
||||
}
|
||||
|
||||
LocalDate now = LocalDate.now();
|
||||
LocalDate sellEnd = now.plusDays(7);
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
String date = sellEnd.format(formatter);
|
||||
|
||||
if (!i.getInventoryType().equals(InventoryType.EQUIP)) {
|
||||
Item item = i;
|
||||
try (PreparedStatement pse = con.prepareStatement("INSERT INTO mts_items (tab, type, itemid, quantity, expiration, giftFrom, seller, price, owner, sellername, sell_ends) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) {
|
||||
@@ -761,7 +735,7 @@ public final class MTSHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM mts_items WHERE tab = ? " + (type != 0 ? "AND type = ?" : "") + "AND transfer = 0")) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM mts_items WHERE tab = ? " + (type != 0 ? "AND type = ?" : "") + " AND transfer = 0")) {
|
||||
ps.setInt(1, tab);
|
||||
if (type != 0) {
|
||||
ps.setInt(2, type);
|
||||
|
||||
@@ -291,7 +291,7 @@ public class AbstractPlayerInteraction {
|
||||
int size = Math.min(itemids.size(), quantity.size());
|
||||
|
||||
List<List<Pair<Integer, Integer>>> invList = new ArrayList<>(6);
|
||||
for (int i = InventoryType.UNDEFINED.getType(); i < InventoryType.CASH.getType(); i++) {
|
||||
for (int i = InventoryType.UNDEFINED.getType(); i <= InventoryType.CASH.getType(); i++) {
|
||||
invList.add(new LinkedList<>());
|
||||
}
|
||||
|
||||
|
||||
93
src/main/java/server/ExpLogger.java
Normal file
93
src/main/java/server/ExpLogger.java
Normal file
@@ -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.scheduleWithFixedDelay(saveExpLoggerToDBRunnable, EXP_LOGGER_THREAD_SLEEP_DURATION_SECONDS, 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ package server;
|
||||
|
||||
import client.inventory.Item;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
@@ -38,13 +40,16 @@ public class MTSItemInfo {
|
||||
private int day = 1;
|
||||
|
||||
public MTSItemInfo(Item item, int price, int id, int cid, String seller, String date) {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
LocalDate sellEnd = LocalDate.parse(date, formatter);
|
||||
|
||||
this.item = item;
|
||||
this.price = price;
|
||||
this.seller = seller;
|
||||
this.id = id;
|
||||
this.year = Integer.parseInt(date.substring(0, 4));
|
||||
this.month = Integer.parseInt(date.substring(5, 7));
|
||||
this.day = Integer.parseInt(date.substring(8, 10));
|
||||
this.year = sellEnd.getYear();
|
||||
this.month = sellEnd.getMonthValue();
|
||||
this.day = sellEnd.getDayOfMonth();
|
||||
}
|
||||
|
||||
public Item getItem() {
|
||||
|
||||
Reference in New Issue
Block a user