Direct almost all chr saving through CharacterSaver

Client#disconnectInternal remains.
Had to remove some configurable save points to keep it simple.
This commit is contained in:
P0nk
2023-08-04 16:05:10 +02:00
parent e52f646558
commit 4e39142fb3
18 changed files with 122 additions and 152 deletions

View File

@@ -242,7 +242,6 @@ 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_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
USE_ENFORCE_ADMIN_ACCOUNT: false #Forces accounts having GM characters to be treated as a "GM account" by the client (localhost). Some of the GM account perks is the ability to FLY, but unable to TRADE.
@@ -254,7 +253,6 @@ server:
USE_ENFORCE_ITEM_SUGGESTION: false #Forces the Owl of Minerva and the Cash Shop to always display the defined item array instead of those featured by the players.
USE_ENFORCE_UNMERCHABLE_CASH: true #Forces players to not sell CASH items via merchants, drops of it disappears.
USE_ENFORCE_UNMERCHABLE_PET: true #Forces players to not sell pets via merchants, drops of it disappears. (since non-named pets gets dirty name and other possible DB-related issues)
USE_ENFORCE_MERCHANT_SAVE: true #Forces automatic DB save on merchant owners, at every item movement on shop.
USE_ENFORCE_MDOOR_POSITION: false #Forces mystic door to be spawned near spawnpoints.
USE_SPAWN_CLEAN_MDOOR: false #Makes mystic doors to be spawned without deploy animation. This clears disconnecting issues that may happen when trying to cancel doors a couple seconds after deployment.
USE_SPAWN_LOOT_ON_ANIMATION: false #Makes loot appear some time after the mob has been killed (following the mob death animation, instead of instantly).
@@ -371,7 +369,6 @@ server:
USE_FULL_HOLY_SYMBOL: false #Holy symbol doesn't require EXP sharers to work in full.
#Character Configuration
USE_ADD_SLOTS_BY_LEVEL: false #Slots are added each 20 levels.
USE_ADD_RATES_BY_LEVEL: false #Rates are added each 20 levels.
USE_STACK_COUPON_RATES: false #Multiple coupons effects builds up together.
USE_PERFECT_PITCH: false #For lvl 30 or above, each lvlup grants player 1 perfect pitch.

View File

@@ -50,8 +50,6 @@ import net.server.guild.Alliance;
import net.server.guild.Guild;
import net.server.guild.GuildCharacter;
import net.server.guild.GuildPackets;
import net.server.services.task.world.CharacterSaveService;
import net.server.services.type.WorldServices;
import net.server.world.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -6449,15 +6447,6 @@ public class Character extends AbstractCharacterObject {
}
if (level % 20 == 0) {
if (YamlConfig.config.server.USE_ADD_SLOTS_BY_LEVEL == true) {
if (!isGM()) {
for (byte i = 1; i < 5; i++) {
gainSlots(i, 4, true);
}
this.yellowMessage("You reached level " + level + ". Congratulations! As a token of your success, your inventory has been expanded a little bit.");
}
}
if (YamlConfig.config.server.USE_ADD_RATES_BY_LEVEL == true) { //For the rate upgrade
revertLastPlayerRates();
setPlayerRates();
@@ -8240,20 +8229,10 @@ public class Character extends AbstractCharacterObject {
return false;
}
// TODO: all callers should use CharacterSaver instead.
// It's supposed to act as a proxy to these 2 methods (as a first step towards taking full ownership of character saving)
public void saveCharToDB() {
if (YamlConfig.config.server.USE_AUTOSAVE) {
Runnable r = new Runnable() {
@Override
public void run() {
saveCharToDB(true);
}
};
CharacterSaveService service = (CharacterSaveService) getWorldServer().getServiceAccess(WorldServices.SAVE_CHARACTER);
service.registerSaveCharacter(this.getId(), r);
} else {
saveCharToDB(true);
}
saveCharToDB(true);
}
//ItemFactory saveItems and monsterbook.saveCards are the most time consuming here.
@@ -9179,33 +9158,28 @@ public class Character extends AbstractCharacterObject {
return slots <= 96;
}
public boolean gainSlots(int type, int slots) {
return gainSlots(type, slots, true);
}
public boolean gainSlots(int type, int slots, boolean update) {
int newLimit = gainSlotsInternal(type, slots);
if (newLimit != -1) {
this.saveCharToDB();
if (update) {
sendPacket(PacketCreator.updateInventorySlotLimit(type, newLimit));
}
return true;
} else {
Integer updatedLimit = gainSlotsInternal(type, slots);
if (updatedLimit == null) {
return false;
}
if (update) {
sendPacket(PacketCreator.updateInventorySlotLimit(type, updatedLimit));
}
return true;
}
private int gainSlotsInternal(int type, int slots) {
private Integer gainSlotsInternal(int type, int slots) {
inventory[type].lockInventory();
try {
if (canGainSlots(type, slots)) {
int newLimit = inventory[type].getSlotLimit() + slots;
inventory[type].setSlotLimit(newLimit);
return newLimit;
} else {
return -1;
if (!canGainSlots(type, slots)) {
return null;
}
int newLimit = inventory[type].getSlotLimit() + slots;
inventory[type].setSlotLimit(newLimit);
return newLimit;
} finally {
inventory[type].unlockInventory();
}

View File

@@ -1,5 +1,6 @@
package client.command;
import database.character.CharacterSaver;
import database.drop.DropProvider;
import server.shop.ShopFactory;
import service.ChannelService;
@@ -8,9 +9,9 @@ import service.ChannelService;
* @author Ponk
*/
public record CommandContext(CommandsExecutor commandsExecutor, DropProvider dropProvider, ShopFactory shopFactory,
ChannelService channelService) {
CharacterSaver characterSaver, ChannelService channelService) {
public CommandContext with(CommandsExecutor ce) {
return new CommandContext(ce, this.dropProvider, this.shopFactory, this.channelService);
return new CommandContext(ce, this.dropProvider, this.shopFactory, this.characterSaver, this.channelService);
}
}

View File

@@ -41,7 +41,7 @@ public class SaveAllCommand extends Command {
Character player = c.getPlayer();
for (World world : Server.getInstance().getWorlds()) {
for (Character chr : world.getPlayerStorage().getAllCharacters()) {
chr.saveCharToDB();
ctx.characterSaver().save(chr);
}
}
String message = player.getName() + " used !saveall.";

View File

@@ -55,7 +55,7 @@ public class WarpWorldCommand extends Command {
player.getMap().removePlayer(player);//LOL FORGOT THIS ><
player.setSessionTransitionState();
player.setWorld(worldb);
player.saveCharToDB();//To set the new world :O (true because else 2 player instances are created, one in both worlds)
ctx.characterSaver().save(player);//To set the new world :O (true because else 2 player instances are created, one in both worlds)
c.sendPacket(PacketCreator.getChannelChange(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1])));
} catch (UnknownHostException | NumberFormatException ex) {
ex.printStackTrace();

View File

@@ -91,7 +91,6 @@ public class ServerConfig {
public boolean USE_STARTING_AP_4;
public boolean USE_AUTOBAN;
public boolean USE_AUTOBAN_LOG;
public boolean USE_AUTOSAVE;
public boolean USE_SERVER_AUTOASSIGNER;
public boolean USE_REFRESH_RANK_MOVE;
public boolean USE_ENFORCE_ADMIN_ACCOUNT;
@@ -103,7 +102,6 @@ public class ServerConfig {
public boolean USE_ENFORCE_ITEM_SUGGESTION;
public boolean USE_ENFORCE_UNMERCHABLE_CASH;
public boolean USE_ENFORCE_UNMERCHABLE_PET;
public boolean USE_ENFORCE_MERCHANT_SAVE;
public boolean USE_ENFORCE_MDOOR_POSITION;
public boolean USE_SPAWN_CLEAN_MDOOR;
public boolean USE_SPAWN_LOOT_ON_ANIMATION;
@@ -220,7 +218,6 @@ public class ServerConfig {
public boolean USE_FULL_HOLY_SYMBOL;
//Character Configuration
public boolean USE_ADD_SLOTS_BY_LEVEL;
public boolean USE_ADD_RATES_BY_LEVEL;
public boolean USE_STACK_COUPON_RATES;
public boolean USE_PERFECT_PITCH;

View File

@@ -0,0 +1,39 @@
package database.character;
import client.Character;
import client.Client;
import client.MonsterBook;
import database.monsterbook.MonsterCardDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.Optional;
public class CharacterLoader {
private static final Logger log = LoggerFactory.getLogger(CharacterLoader.class);
private final MonsterCardDao monsterCardDao;
public CharacterLoader(MonsterCardDao monsterCardDao) {
this.monsterCardDao = monsterCardDao;
}
public Optional<Character> loadForChannel(int chrId, Client client) {
var monsterBook = loadMonsterBook(chrId);
final Character chr;
try {
chr = Character.loadCharFromDB(chrId, client, true, monsterBook);
} catch (SQLException e) {
log.warn("Failed to load character (id {})", chrId, e);
return Optional.empty();
}
return Optional.ofNullable(chr);
}
private MonsterBook loadMonsterBook(int chrId) {
var monsterCards = monsterCardDao.load(chrId);
return new MonsterBook(monsterCards);
}
}

View File

@@ -3,6 +3,7 @@ package net;
import client.command.CommandsExecutor;
import client.processor.action.MakerProcessor;
import client.processor.npc.FredrickProcessor;
import database.character.CharacterLoader;
import database.character.CharacterSaver;
import database.drop.DropProvider;
import server.shop.ShopFactory;
@@ -15,12 +16,13 @@ import java.util.Objects;
* @author Ponk
*/
public record ChannelDependencies(
CharacterSaver characterSaver, NoteService noteService, FredrickProcessor fredrickProcessor,
MakerProcessor makerProcessor, DropProvider dropProvider, CommandsExecutor commandsExecutor,
ShopFactory shopFactory, ChannelService channelService
CharacterLoader characterLoader, CharacterSaver characterSaver, NoteService noteService,
FredrickProcessor fredrickProcessor, MakerProcessor makerProcessor, DropProvider dropProvider,
CommandsExecutor commandsExecutor, ShopFactory shopFactory, ChannelService channelService
) {
public ChannelDependencies {
Objects.requireNonNull(characterLoader);
Objects.requireNonNull(characterSaver);
Objects.requireNonNull(noteService);
Objects.requireNonNull(fredrickProcessor);

View File

@@ -152,7 +152,8 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.ITEM_SORT, new InventoryMergeHandler());
registerHandler(RecvOpcode.ITEM_MOVE, new ItemMoveHandler());
registerHandler(RecvOpcode.MESO_DROP, new MesoDropHandler());
registerHandler(RecvOpcode.PLAYER_LOGGEDIN, new PlayerLoggedinHandler(channelDeps.noteService()));
registerHandler(RecvOpcode.PLAYER_LOGGEDIN, new PlayerLoggedinHandler(channelDeps.characterLoader(),
channelDeps.noteService()));
registerHandler(RecvOpcode.CHANGE_MAP, new ChangeMapHandler());
registerHandler(RecvOpcode.MOVE_LIFE, new MoveLifeHandler());
registerHandler(RecvOpcode.CLOSE_RANGE_ATTACK, new CloseRangeDamageHandler(channelDeps.dropProvider()));
@@ -174,7 +175,7 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.USE_INNER_PORTAL, new InnerPortalHandler());
registerHandler(RecvOpcode.CANCEL_BUFF, new CancelBuffHandler());
registerHandler(RecvOpcode.CANCEL_ITEM_EFFECT, new CancelItemEffectHandler());
registerHandler(RecvOpcode.PLAYER_INTERACTION, new PlayerInteractionHandler());
registerHandler(RecvOpcode.PLAYER_INTERACTION, new PlayerInteractionHandler(channelDeps.characterSaver()));
registerHandler(RecvOpcode.RPS_ACTION, new RPSActionHandler());
registerHandler(RecvOpcode.DISTRIBUTE_AP, new DistributeAPHandler());
registerHandler(RecvOpcode.DISTRIBUTE_SP, new DistributeSPHandler());
@@ -186,8 +187,8 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.DENY_PARTY_REQUEST, new DenyPartyRequestHandler());
registerHandler(RecvOpcode.MULTI_CHAT, new MultiChatHandler());
registerHandler(RecvOpcode.USE_DOOR, new DoorHandler());
registerHandler(RecvOpcode.ENTER_MTS, new EnterMTSHandler());
registerHandler(RecvOpcode.ENTER_CASHSHOP, new EnterCashShopHandler());
registerHandler(RecvOpcode.ENTER_MTS, new EnterMTSHandler(channelDeps.characterSaver()));
registerHandler(RecvOpcode.ENTER_CASHSHOP, new EnterCashShopHandler(channelDeps.characterSaver()));
registerHandler(RecvOpcode.DAMAGE_SUMMON, new DamageSummonHandler());
registerHandler(RecvOpcode.MOVE_SUMMON, new MoveSummonHandler());
registerHandler(RecvOpcode.SUMMON_ATTACK, new SummonDamageHandler(channelDeps.dropProvider()));
@@ -277,7 +278,7 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.FREDRICK_ACTION, new FredrickHandler(channelDeps.fredrickProcessor()));
registerHandler(RecvOpcode.MONSTER_CARNIVAL, new MonsterCarnivalHandler());
registerHandler(RecvOpcode.REMOTE_STORE, new RemoteStoreHandler());
registerHandler(RecvOpcode.WEDDING_ACTION, new WeddingHandler());
registerHandler(RecvOpcode.WEDDING_ACTION, new WeddingHandler(channelDeps.characterSaver()));
registerHandler(RecvOpcode.WEDDING_TALK, new WeddingTalkHandler());
registerHandler(RecvOpcode.WEDDING_TALK_MORE, new WeddingTalkMoreHandler());
registerHandler(RecvOpcode.WATER_OF_LIFE, new UseWaterOfLifeHandler());

View File

@@ -43,6 +43,7 @@ import constants.net.OpcodeConstants;
import constants.net.ServerConstants;
import database.PgDatabaseConfig;
import database.PgDatabaseConnection;
import database.character.CharacterLoader;
import database.character.CharacterSaver;
import database.drop.DropDao;
import database.drop.DropProvider;
@@ -979,6 +980,7 @@ public class Server {
private ChannelDependencies registerChannelDependencies(PgDatabaseConnection connection) {
MonsterCardDao monsterCardDao = new MonsterCardDao(connection);
CharacterLoader characterLoader = new CharacterLoader(monsterCardDao);
CharacterSaver characterSaver = new CharacterSaver(monsterCardDao);
ChannelService channelService = new ChannelService(characterSaver);
NoteService noteService = new NoteService(new NoteDao(connection));
@@ -987,9 +989,9 @@ public class Server {
DropProvider dropProvider = new DropProvider(new DropDao(connection));
ShopFactory shopFactory = new ShopFactory(new ShopDao(connection));
CommandContext commandContext = new CommandContext(null, dropProvider, shopFactory,
channelService);
characterSaver, channelService);
CommandsExecutor commandsExecutor = new CommandsExecutor(commandContext);
ChannelDependencies channelDependencies = new ChannelDependencies(characterSaver, noteService,
ChannelDependencies channelDependencies = new ChannelDependencies(characterLoader, characterSaver, noteService,
fredrickProcessor, makerProcessor, dropProvider, commandsExecutor, shopFactory, channelService);
PacketProcessor.registerGameHandlerDependencies(channelDependencies);

View File

@@ -23,6 +23,7 @@ package net.server.channel.handlers;
import client.Character;
import client.Client;
import database.character.CharacterSaver;
import net.AbstractPacketHandler;
import net.packet.InPacket;
import net.server.Server;
@@ -33,6 +34,12 @@ import tools.PacketCreator;
* @author Flav
*/
public class EnterCashShopHandler extends AbstractPacketHandler {
private final CharacterSaver chrSaver;
public EnterCashShopHandler(CharacterSaver chrSaver) {
this.chrSaver = chrSaver;
}
@Override
public void handlePacket(InPacket p, Client c) {
try {
@@ -87,7 +94,7 @@ public class EnterCashShopHandler extends AbstractPacketHandler {
c.getChannelServer().removePlayer(mc);
mc.getMap().removePlayer(mc);
mc.getCashShop().open(true);
mc.saveCharToDB();
chrSaver.save(mc);
} catch (Exception e) {
e.printStackTrace();
}

View File

@@ -27,6 +27,7 @@ import client.inventory.Equip;
import client.inventory.Item;
import client.processor.action.BuybackProcessor;
import config.YamlConfig;
import database.character.CharacterSaver;
import net.AbstractPacketHandler;
import net.packet.InPacket;
import net.server.Server;
@@ -45,6 +46,12 @@ import java.util.List;
public final class EnterMTSHandler extends AbstractPacketHandler {
private final CharacterSaver chrSaver;
public EnterMTSHandler(CharacterSaver chrSaver) {
this.chrSaver = chrSaver;
}
@Override
public final void handlePacket(InPacket p, Client c) {
Character chr = c.getPlayer();
@@ -105,7 +112,7 @@ public final class EnterMTSHandler extends AbstractPacketHandler {
chr.forfeitExpirableQuests();
chr.cancelQuestExpirationTask();
chr.saveCharToDB();
chrSaver.save(chr);
c.getChannelServer().removePlayer(chr);
chr.getMap().removePlayer(c.getPlayer());
@@ -276,4 +283,4 @@ public final class EnterMTSHandler extends AbstractPacketHandler {
}
return items;
}
}
}

View File

@@ -33,6 +33,7 @@ import config.YamlConfig;
import constants.game.GameConstants;
import constants.id.ItemId;
import constants.inventory.ItemConstants;
import database.character.CharacterSaver;
import net.AbstractPacketHandler;
import net.packet.InPacket;
import org.slf4j.Logger;
@@ -53,6 +54,11 @@ import java.util.Arrays;
*/
public final class PlayerInteractionHandler extends AbstractPacketHandler {
private static final Logger log = LoggerFactory.getLogger(PlayerInteractionHandler.class);
private final CharacterSaver chrSaver;
public PlayerInteractionHandler(CharacterSaver chrSaver) {
this.chrSaver = chrSaver;
}
public enum Action {
CREATE(0),
@@ -644,10 +650,6 @@ public final class PlayerInteractionHandler extends AbstractPacketHandler {
c.sendPacket(PacketCreator.updateHiredMerchant(merchant, chr));
if (YamlConfig.config.server.USE_ENFORCE_MERCHANT_SAVE) {
chr.saveCharToDB(false);
}
try {
merchant.saveItems(false); // thanks Masterrulax for realizing yet another dupe with merchants/Fredrick
} catch (SQLException ex) {
@@ -771,7 +773,7 @@ public final class PlayerInteractionHandler extends AbstractPacketHandler {
return;
}
merchant.takeItemBack(slot, chr);
merchant.takeItemBack(slot, chr, chrSaver);
}
} else if (mode == Action.CLOSE_MERCHANT.getCode()) {
if (isTradeOpen(chr)) {

View File

@@ -27,6 +27,7 @@ import client.inventory.*;
import client.keybind.KeyBinding;
import config.YamlConfig;
import constants.game.GameConstants;
import database.character.CharacterLoader;
import net.AbstractPacketHandler;
import net.packet.InPacket;
import net.server.PlayerBuffValueHolder;
@@ -64,9 +65,11 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
private static final Logger log = LoggerFactory.getLogger(PlayerLoggedinHandler.class);
private static final Set<Integer> attemptingLoginAccounts = new HashSet<>();
private final CharacterLoader chrLoader;
private final NoteService noteService;
public PlayerLoggedinHandler(NoteService noteService) {
public PlayerLoggedinHandler(CharacterLoader chrLoader, NoteService noteService) {
this.chrLoader = chrLoader;
this.noteService = noteService;
}
@@ -94,7 +97,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
@Override
public final void handlePacket(InPacket p, Client c) {
final int cid = p.readInt(); // TODO: investigate if this is the "client id" supplied in PacketCreator#getServerIP()
final int chrId = p.readInt();
final Server server = Server.getInstance();
if (!c.tryacquireClient()) {
@@ -120,7 +123,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
}
}
Character player = wserv.getPlayerStorage().getCharacterById(cid);
Character player = wserv.getPlayerStorage().getCharacterById(chrId);
final Hwid hwid;
if (player == null) {
@@ -135,21 +138,18 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
c.setHwid(hwid);
if (!server.validateCharacteridInTransition(c, cid)) {
if (!server.validateCharacteridInTransition(c, chrId)) {
c.disconnect(true, false);
return;
}
boolean newcomer = false;
if (player == null) {
try {
player = Character.loadCharFromDB(cid, c, true);
Optional<Character> loadedChr = chrLoader.loadForChannel(chrId, c);
if (loadedChr.isPresent()) {
player = loadedChr.get();
newcomer = true;
} catch (SQLException e) {
e.printStackTrace();
}
if (player == null) { //If you are still getting null here then please just uninstall the game >.>, we dont need you fucking with the logs
} else {
c.disconnect(true, false);
return;
}
@@ -212,13 +212,13 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
wserv.addPlayer(player);
player.setEnteredChannelWorld();
List<PlayerBuffValueHolder> buffs = server.getPlayerBuffStorage().getBuffsFromStorage(cid);
List<PlayerBuffValueHolder> buffs = server.getPlayerBuffStorage().getBuffsFromStorage(chrId);
if (buffs != null) {
List<Pair<Long, PlayerBuffValueHolder>> timedBuffs = getLocalStartTimes(buffs);
player.silentGiveBuffs(timedBuffs);
}
Map<Disease, Pair<Long, MobSkill>> diseases = server.getPlayerBuffStorage().getDiseasesFromStorage(cid);
Map<Disease, Pair<Long, MobSkill>> diseases = server.getPlayerBuffStorage().getDiseasesFromStorage(chrId);
if (diseases != null) {
player.silentApplyDiseases(diseases);
}
@@ -415,7 +415,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
}
if (newcomer) {
EventInstanceManager eim = EventRecallCoordinator.getInstance().recallEventInstance(cid);
EventInstanceManager eim = EventRecallCoordinator.getInstance().recallEventInstance(chrId);
if (eim != null) {
eim.registerPlayer(player);
}

View File

@@ -16,6 +16,7 @@ import client.inventory.manipulator.InventoryManipulator;
import client.inventory.manipulator.KarmaManipulator;
import config.YamlConfig;
import constants.inventory.ItemConstants;
import database.character.CharacterSaver;
import net.AbstractPacketHandler;
import net.packet.InPacket;
import org.slf4j.Logger;
@@ -32,6 +33,11 @@ import java.util.List;
*/
public final class WeddingHandler extends AbstractPacketHandler {
private static final Logger log = LoggerFactory.getLogger(WeddingHandler.class);
private final CharacterSaver chrSaver;
public WeddingHandler(CharacterSaver chrSaver) {
this.chrSaver = chrSaver;
}
@Override
public void handlePacket(InPacket p, Client c) {
@@ -87,9 +93,6 @@ public final class WeddingHandler extends AbstractPacketHandler {
}
if (newItem != null) {
if (YamlConfig.config.server.USE_ENFORCE_MERCHANT_SAVE) {
chr.saveCharToDB(false);
}
marriage.saveGiftItemsToDb(c, groomWishlist, cid);
}
} else {

View File

@@ -1,49 +0,0 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server.task;
import client.Character;
import config.YamlConfig;
import net.server.PlayerStorage;
import net.server.world.World;
/**
* @author Ronan
*/
public class CharacterAutosaverTask extends BaseTask implements Runnable { // thanks Alex09 (Alex-0000) for noticing these runnable classes are tasks, "workers" runs them
@Override
public void run() {
if (!YamlConfig.config.server.USE_AUTOSAVE) {
return;
}
PlayerStorage ps = wserv.getPlayerStorage();
for (Character chr : ps.getAllCharacters()) {
if (chr != null && chr.isLoggedin()) {
chr.saveCharToDB(false);
}
}
}
public CharacterAutosaverTask(World world) {
super(world);
}
}

View File

@@ -196,7 +196,6 @@ public class World {
mountsSchedule = tman.register(new MountTirednessTask(this), MINUTES.toMillis(1), MINUTES.toMillis(1));
merchantSchedule = tman.register(new HiredMerchantTask(this), 10 * MINUTES.toMillis(1), 10 * MINUTES.toMillis(1));
timedMapObjectsSchedule = tman.register(new TimedMapObjectTask(this), MINUTES.toMillis(1), MINUTES.toMillis(1));
charactersSchedule = tman.register(new CharacterAutosaverTask(this), HOURS.toMillis(1), HOURS.toMillis(1));
marriagesSchedule = tman.register(new WeddingReservationTask(this), MINUTES.toMillis(YamlConfig.config.server.WEDDING_RESERVATION_INTERVAL), MINUTES.toMillis(YamlConfig.config.server.WEDDING_RESERVATION_INTERVAL));
mapOwnershipSchedule = tman.register(new MapOwnershipTask(this), SECONDS.toMillis(20), SECONDS.toMillis(20));
fishingSchedule = tman.register(new FishingTask(this), SECONDS.toMillis(10), SECONDS.toMillis(10));
@@ -2124,11 +2123,6 @@ public class World {
timedMapObjectsSchedule = null;
}
if (charactersSchedule != null) {
charactersSchedule.cancel(false);
charactersSchedule = null;
}
if (marriagesSchedule != null) {
marriagesSchedule.cancel(false);
marriagesSchedule = null;

View File

@@ -31,6 +31,7 @@ import client.inventory.manipulator.InventoryManipulator;
import client.inventory.manipulator.KarmaManipulator;
import client.processor.npc.FredrickProcessor;
import config.YamlConfig;
import database.character.CharacterSaver;
import net.packet.Packet;
import net.server.Server;
import server.ItemInformationProvider;
@@ -232,7 +233,7 @@ public class HiredMerchant extends AbstractMapObject {
}
}
public void takeItemBack(int slot, Character chr) {
public void takeItemBack(int slot, Character chr, CharacterSaver chrSaver) {
synchronized (items) {
PlayerShopItem shopItem = items.get(slot);
if (shopItem.isExist()) {
@@ -252,10 +253,6 @@ public class HiredMerchant extends AbstractMapObject {
removeFromSlot(slot);
chr.sendPacket(PacketCreator.updateHiredMerchant(this, chr));
}
if (YamlConfig.config.server.USE_ENFORCE_MERCHANT_SAVE) {
chr.saveCharToDB(false);
}
}
}
@@ -461,10 +458,6 @@ public class HiredMerchant extends AbstractMapObject {
}
}
if (YamlConfig.config.server.USE_ENFORCE_MERCHANT_SAVE) {
c.getPlayer().saveCharToDB(false);
}
synchronized (items) {
items.clear();
}