Compare commits

...

9 Commits

Author SHA1 Message Date
Ponk
03802666ef Merge pull request #190 from ormizj/character-exp-log #minor
added logs for character exp gain
2023-11-08 21:16:57 +01:00
Ponk
ecd155f2bb Merge pull request #201 from peamy/master #patch
BugFix: can't give CASH items to player (prepareInventoryItemList)
2023-11-08 20:50:50 +01:00
remsus
d6147d5191 Fix preparation of invList (CASH was skipped) in prepareInventoryItemList (AbstractPlayerInteraction) 2023-11-08 11:26:55 +01:00
Ponk
7ef471f1e2 Merge pull request #197 from wangxiaobao0851/fix-mts #patch
Fix MTS sql syntax error and month error
2023-11-07 17:28:16 +01:00
王小宝
c3404d296a Fix MTS sql syntax error and month error 2023-10-13 21:16:40 +08:00
ormizj
c145a53688 fixed wrong method call 2023-09-15 01:04:22 +03:00
spiderpig60
c744935dd0 changed starting server to vanilla values 2023-09-10 21:48:02 +03:00
spiderpig60
90b44c3a8b added timed thread, added batch, cleaned code
changed starting value to false
2023-09-10 21:36:52 +03:00
spiderpig60
60a44252ea added logs for character exp gain 2023-09-10 01:53:53 +03:00
8 changed files with 141 additions and 39 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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<>());
}

View 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();
}
}
}

View File

@@ -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() {