Add ChannelService to handle cc'ing

This commit is contained in:
P0nk
2023-08-04 14:53:20 +02:00
parent f6aa8ceba6
commit 05b7ec77c8
11 changed files with 162 additions and 86 deletions

View File

@@ -21,7 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import client.inventory.InventoryType;
import config.YamlConfig;
import constants.game.GameConstants;
import constants.id.MapId;
@@ -59,9 +58,7 @@ import server.MapleLeafLogger;
import server.ThreadManager;
import server.TimerManager;
import server.life.Monster;
import server.maps.FieldLimit;
import server.maps.MapleMap;
import server.maps.MiniDungeonInfo;
import tools.BCrypt;
import tools.DatabaseConnection;
import tools.HexTool;
@@ -69,7 +66,6 @@ import tools.PacketCreator;
import javax.script.ScriptEngine;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@@ -974,10 +970,9 @@ public class Client extends ChannelInboundHandlerAdapter {
private void disconnectInternal(boolean shutdown, boolean cashshop) {//once per Client instance
if (player != null && player.isLoggedin() && player.getClient() != null) {
final int messengerid = player.getMessenger() == null ? 0 : player.getMessenger().getId();
//final int fid = player.getFamilyId();
final BuddyList bl = player.getBuddylist();
final MessengerCharacter chrm = new MessengerCharacter(player, 0);
final GuildCharacter chrg = player.getMGC();
final MessengerCharacter messengerChr = new MessengerCharacter(player, 0);
final GuildCharacter guildChr = player.getMGC();
final Guild guild = player.getGuild();
player.cancelMagicDoor();
@@ -990,14 +985,8 @@ public class Client extends ChannelInboundHandlerAdapter {
if (!cashshop) {
if (!this.serverTransition) { // meaning not changing channels
if (messengerid > 0) {
wserv.leaveMessenger(messengerid, chrm);
wserv.leaveMessenger(messengerid, messengerChr);
}
/*
if (fid > 0) {
final Family family = worlda.getFamily(fid);
family.
}
*/
player.forfeitExpirableQuests(); //This is for those quests that you have to stay logged in for a certain amount of time
@@ -1022,8 +1011,8 @@ public class Client extends ChannelInboundHandlerAdapter {
log.error("Account stuck", e);
} finally {
if (!this.serverTransition) {
if (chrg != null) {
chrg.setCharacter(null);
if (guildChr != null) {
guildChr.setCharacter(null);
}
wserv.removePlayer(player);
//getChannelServer().removePlayer(player); already being done
@@ -1462,61 +1451,6 @@ public class Client extends ChannelInboundHandlerAdapter {
sendPacket(PacketCreator.enableActions());
}
public void changeChannel(int channel) {
Server server = Server.getInstance();
if (player.isBanned()) {
disconnect(false, false);
return;
}
if (!player.isAlive() || FieldLimit.CANNOTMIGRATE.check(player.getMap().getFieldLimit())) {
sendPacket(PacketCreator.enableActions());
return;
} else if (MiniDungeonInfo.isDungeonMap(player.getMapId())) {
sendPacket(PacketCreator.serverNotice(5, "Changing channels or entering Cash Shop or MTS are disabled when inside a Mini-Dungeon."));
sendPacket(PacketCreator.enableActions());
return;
}
String[] socket = Server.getInstance().getInetSocket(this, getWorld(), channel);
if (socket == null) {
sendPacket(PacketCreator.serverNotice(1, "Channel " + channel + " is currently disabled. Try another channel."));
sendPacket(PacketCreator.enableActions());
return;
}
player.closePlayerInteractions();
player.closePartySearchInteractions();
player.unregisterChairBuff();
server.getPlayerBuffStorage().addBuffsToStorage(player.getId(), player.getAllBuffs());
server.getPlayerBuffStorage().addDiseasesToStorage(player.getId(), player.getAllDiseases());
player.setDisconnectedFromChannelWorld();
player.notifyMapTransferToPartner(-1);
player.removeIncomingInvites();
player.cancelAllBuffs(true);
player.cancelAllDebuffs();
player.cancelBuffExpireTask();
player.cancelDiseaseExpireTask();
player.cancelSkillCooldownTask();
player.cancelQuestExpirationTask();
//Cancelling magicdoor? Nope
//Cancelling mounts? Noty
player.getInventory(InventoryType.EQUIPPED).checked(false); //test
player.getMap().removePlayer(player);
player.clearBanishPlayerData();
player.getClient().getChannelServer().removePlayer(player);
player.saveCharToDB();
player.setSessionTransitionState();
try {
sendPacket(PacketCreator.getChannelChange(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1])));
} catch (IOException e) {
e.printStackTrace();
}
}
public long getSessionId() {
return this.sessionId;
}
@@ -1585,4 +1519,4 @@ public class Client extends ChannelInboundHandlerAdapter {
public void setLanguage(int lingua) {
this.lang = lingua;
}
}
}

View File

@@ -2,13 +2,15 @@ package client.command;
import database.drop.DropProvider;
import server.shop.ShopFactory;
import service.ChannelService;
/**
* @author Ponk
*/
public record CommandContext(CommandsExecutor commandsExecutor, DropProvider dropProvider, ShopFactory shopFactory) {
public record CommandContext(CommandsExecutor commandsExecutor, DropProvider dropProvider, ShopFactory shopFactory,
ChannelService channelService) {
public CommandContext with(CommandsExecutor ce) {
return new CommandContext(ce, this.dropProvider, this.shopFactory);
return new CommandContext(ce, this.dropProvider, this.shopFactory, this.channelService);
}
}

View File

@@ -63,7 +63,7 @@ public class SummonCommand extends Command {
if (player.getClient().getChannel() != victim.getClient().getChannel()) {//And then change channel if needed.
victim.dropMessage("Changing channel, please wait a moment.");
victim.getClient().changeChannel(player.getClient().getChannel());
ctx.channelService().changeChannel(victim.getClient(), player.getClient().getChannel());
}
try {

View File

@@ -5,6 +5,7 @@ import database.drop.MonsterDropRowMapper;
import database.maker.MakerIngredientRowMapper;
import database.maker.MakerReagentRowMapper;
import database.maker.MakerRecipeRowMapper;
import database.monsterbook.MonsterCardRowMapper;
import database.note.NoteRowMapper;
import database.shop.ShopItemRowMapper;
import database.shop.ShopRowMapper;
@@ -32,7 +33,8 @@ public final class JdbiConfig {
new MonsterDropRowMapper(),
new GlobalMonsterDropRowMapper(),
new ShopRowMapper(),
new ShopItemRowMapper()
new ShopItemRowMapper(),
new MonsterCardRowMapper()
);
}
}

View File

@@ -0,0 +1,20 @@
package database.character;
import client.Character;
import database.monsterbook.MonsterCardDao;
public class CharacterSaver {
private final MonsterCardDao monsterCardDao;
public CharacterSaver(MonsterCardDao monsterCardDao) {
this.monsterCardDao = monsterCardDao;
}
public void save(Character chr) {
chr.saveCharToDB(false);
// Saving monster cards to both MySQL and Postgres for now
monsterCardDao.save(chr.getId(), chr.getMonsterBook().getCards());
}
}

View File

@@ -4,6 +4,7 @@ import database.DaoException;
import database.PgDatabaseConnection;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.JdbiException;
import org.jdbi.v3.core.statement.PreparedBatch;
import java.util.List;
@@ -24,7 +25,26 @@ public class MonsterCardDao {
.mapTo(MonsterCard.class)
.list();
} catch (JdbiException e) {
throw new DaoException("Failed to find monster cards for chr id %d".formatted(chrId), e);
throw new DaoException("Failed to find monster cards (chrId %d)".formatted(chrId), e);
}
}
public void save(int chrId, List<MonsterCard> cards) {
try (Handle handle = connection.getHandle()) {
PreparedBatch batch = handle.prepareBatch("""
INSERT INTO monster_card (chr_id, card_id, level)
VALUES (?, ?, ?)
ON CONFLICT (chr_id, card_id)
DO UPDATE SET level = excluded.level;""");
batch.bind(0, chrId);
cards.forEach(card -> {
batch.bind(1, card.cardId());
batch.bind(2, card.level());
batch.add();
});
batch.execute();
} catch (JdbiException e) {
throw new DaoException("Failed to save monster cards (chrId %d)".formatted(chrId), e);
}
}
}

View File

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

View File

@@ -140,7 +140,7 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.NAME_TRANSFER, new TransferNameHandler());
registerHandler(RecvOpcode.CHECK_CHAR_NAME, new TransferNameResultHandler());
registerHandler(RecvOpcode.WORLD_TRANSFER, new TransferWorldHandler());
registerHandler(RecvOpcode.CHANGE_CHANNEL, new ChangeChannelHandler());
registerHandler(RecvOpcode.CHANGE_CHANNEL, new ChangeChannelHandler(channelDeps.channelService()));
registerHandler(RecvOpcode.STRANGE_DATA, LoginRequiringNoOpHandler.getInstance());
registerHandler(RecvOpcode.GENERAL_CHAT, new GeneralChatHandler(channelDeps.commandsExecutor()));
registerHandler(RecvOpcode.WHISPER, new WhisperHandler());
@@ -160,7 +160,8 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.MAGIC_ATTACK, new MagicDamageHandler(channelDeps.dropProvider()));
registerHandler(RecvOpcode.TAKE_DAMAGE, new TakeDamageHandler());
registerHandler(RecvOpcode.MOVE_PLAYER, new MovePlayerHandler());
registerHandler(RecvOpcode.USE_CASH_ITEM, new UseCashItemHandler(channelDeps.noteService(), channelDeps.shopFactory()));
registerHandler(RecvOpcode.USE_CASH_ITEM, new UseCashItemHandler(channelDeps.noteService(),
channelDeps.shopFactory()));
registerHandler(RecvOpcode.USE_ITEM, new UseItemHandler());
registerHandler(RecvOpcode.USE_RETURN_SCROLL, new UseItemHandler());
registerHandler(RecvOpcode.USE_UPGRADE_SCROLL, new ScrollHandler());

View File

@@ -43,11 +43,13 @@ import constants.net.OpcodeConstants;
import constants.net.ServerConstants;
import database.PgDatabaseConfig;
import database.PgDatabaseConnection;
import database.character.CharacterSaver;
import database.drop.DropDao;
import database.drop.DropProvider;
import database.maker.MakerDao;
import database.maker.MakerInfoProvider;
import database.migration.FlywayRunner;
import database.monsterbook.MonsterCardDao;
import database.note.NoteDao;
import database.shop.ShopDao;
import net.ChannelDependencies;
@@ -73,6 +75,7 @@ import server.expeditions.ExpeditionBossLog;
import server.life.PlayerNPCFactory;
import server.quest.Quest;
import server.shop.ShopFactory;
import service.ChannelService;
import service.NoteService;
import tools.DatabaseConnection;
import tools.Pair;
@@ -975,15 +978,19 @@ public class Server {
}
private ChannelDependencies registerChannelDependencies(PgDatabaseConnection connection) {
MonsterCardDao monsterCardDao = new MonsterCardDao(connection);
CharacterSaver characterSaver = new CharacterSaver(monsterCardDao);
ChannelService channelService = new ChannelService(characterSaver);
NoteService noteService = new NoteService(new NoteDao(connection));
MakerProcessor makerProcessor = new MakerProcessor(new MakerInfoProvider(new MakerDao(connection)));
FredrickProcessor fredrickProcessor = new FredrickProcessor(noteService);
DropProvider dropProvider = new DropProvider(new DropDao(connection));
ShopFactory shopFactory = new ShopFactory(new ShopDao(connection));
CommandContext commandContext = new CommandContext(null, dropProvider, shopFactory);
CommandContext commandContext = new CommandContext(null, dropProvider, shopFactory,
channelService);
CommandsExecutor commandsExecutor = new CommandsExecutor(commandContext);
ChannelDependencies channelDependencies = new ChannelDependencies(noteService, fredrickProcessor,
makerProcessor, dropProvider, commandsExecutor, shopFactory);
ChannelDependencies channelDependencies = new ChannelDependencies(characterSaver, noteService,
fredrickProcessor, makerProcessor, dropProvider, commandsExecutor, shopFactory, channelService);
PacketProcessor.registerGameHandlerDependencies(channelDependencies);

View File

@@ -26,11 +26,17 @@ import client.autoban.AutobanFactory;
import net.AbstractPacketHandler;
import net.packet.InPacket;
import net.server.Server;
import service.ChannelService;
/**
* @author Matze
*/
public final class ChangeChannelHandler extends AbstractPacketHandler {
private final ChannelService channelService;
public ChangeChannelHandler(ChannelService channelService) {
this.channelService = channelService;
}
@Override
public final void handlePacket(InPacket p, Client c) {
@@ -45,6 +51,6 @@ public final class ChangeChannelHandler extends AbstractPacketHandler {
return;
}
c.changeChannel(channel);
channelService.changeChannel(c, channel);
}
}
}

View File

@@ -0,0 +1,79 @@
package service;
import client.Client;
import client.inventory.InventoryType;
import database.character.CharacterSaver;
import net.server.Server;
import server.maps.FieldLimit;
import server.maps.MiniDungeonInfo;
import tools.PacketCreator;
import java.io.IOException;
import java.net.InetAddress;
public class ChannelService {
private final Server server = Server.getInstance();
private final CharacterSaver chrSaver;
public ChannelService(CharacterSaver characterSaver) {
this.chrSaver = characterSaver;
}
public void changeChannel(Client c, int channel) {
var chr = c.getPlayer();
if (chr.isBanned()) {
c.disconnect(false, false);
return;
}
if (!chr.isAlive() || FieldLimit.CANNOTMIGRATE.check(chr.getMap().getFieldLimit())) {
c.sendPacket(PacketCreator.enableActions());
return;
}
if (MiniDungeonInfo.isDungeonMap(chr.getMapId())) {
c.sendPacket(PacketCreator.serverNotice(5, "Changing channels or entering Cash Shop or MTS are disabled when inside a Mini-Dungeon."));
c.sendPacket(PacketCreator.enableActions());
return;
}
String[] socket = Server.getInstance().getInetSocket(c, c.getWorld(), channel);
if (socket == null) {
c.sendPacket(PacketCreator.serverNotice(1, "Channel " + channel + " is currently disabled. Try another channel."));
c.sendPacket(PacketCreator.enableActions());
return;
}
chr.closePlayerInteractions();
chr.closePartySearchInteractions();
chr.unregisterChairBuff();
server.getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
server.getPlayerBuffStorage().addDiseasesToStorage(chr.getId(), chr.getAllDiseases());
chr.setDisconnectedFromChannelWorld();
chr.notifyMapTransferToPartner(-1);
chr.removeIncomingInvites();
chr.cancelAllBuffs(true);
chr.cancelAllDebuffs();
chr.cancelBuffExpireTask();
chr.cancelDiseaseExpireTask();
chr.cancelSkillCooldownTask();
chr.cancelQuestExpirationTask();
//Cancelling magicdoor? Nope
//Cancelling mounts? Noty
chr.getInventory(InventoryType.EQUIPPED).checked(false); //test
chr.getMap().removePlayer(chr);
chr.clearBanishPlayerData();
c.getChannelServer().removePlayer(chr);
chrSaver.save(chr);
chr.setSessionTransitionState();
try {
c.sendPacket(PacketCreator.getChannelChange(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1])));
} catch (IOException e) {
e.printStackTrace();
}
}
}