diff --git a/dist/sql/log_chat.sql b/dist/sql/log_chat.sql new file mode 100644 index 000000000..e6003452b --- /dev/null +++ b/dist/sql/log_chat.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS `log_chat` ( + `message_id` int(12) NOT NULL AUTO_INCREMENT, + `type` enum('ALL','SHOUT','TELL','PARTY','CLAN','GM','PETITION_PLAYER','PETITION_GM','TRADE','ALLIANCE','ANNOUNCEMENT','BOAT','L2FRIEND','MSNCHAT','PARTYMATCH_ROOM','PARTYROOM_COMMANDER','PARTYROOM_ALL','HERO_VOICE','CRITICAL_ANNOUNCE','SCREEN_ANNOUNCE','BATTLEFIELD','MPCC_ROOM') NOT NULL, + `channel_id` int(12) NOT NULL, + `sender` int(12) NOT NULL, + `date` int(12) NOT NULL, + `message` text NOT NULL, + PRIMARY KEY (`message_id`) +) ENGINE=MyISAM; \ No newline at end of file diff --git a/src/dao/com/l2jserver/db/H2DAOModule.java b/src/dao/com/l2jserver/db/H2DAOModule.java index 2d03e9eee..91fb94839 100644 --- a/src/dao/com/l2jserver/db/H2DAOModule.java +++ b/src/dao/com/l2jserver/db/H2DAOModule.java @@ -21,11 +21,13 @@ import com.google.inject.Module; import com.google.inject.Scopes; import com.l2jserver.db.dao.CharacterDAO; import com.l2jserver.db.dao.CharacterFriendDAO; +import com.l2jserver.db.dao.ChatMessageDAO; import com.l2jserver.db.dao.ClanDAO; import com.l2jserver.db.dao.ItemDAO; import com.l2jserver.db.dao.NPCDAO; import com.l2jserver.db.dao.jdbc.h2.H2CharacterDAO; import com.l2jserver.db.dao.jdbc.h2.H2CharacterFriendDAO; +import com.l2jserver.db.dao.jdbc.h2.H2ChatMessageDAO; import com.l2jserver.db.dao.jdbc.h2.H2ClanDAO; import com.l2jserver.db.dao.jdbc.h2.H2ItemDAO; import com.l2jserver.db.dao.jdbc.h2.H2NPCDAO; @@ -46,5 +48,9 @@ public class H2DAOModule extends AbstractModule { bind(ItemDAO.class).to(H2ItemDAO.class).in(Scopes.SINGLETON); bind(ClanDAO.class).to(H2ClanDAO.class).in(Scopes.SINGLETON); + + // logs + bind(ChatMessageDAO.class).to(H2ChatMessageDAO.class).in( + Scopes.SINGLETON); } } diff --git a/src/dao/com/l2jserver/db/MySQL5DAOModule.java b/src/dao/com/l2jserver/db/MySQL5DAOModule.java index be9ca0ba4..362c686d1 100644 --- a/src/dao/com/l2jserver/db/MySQL5DAOModule.java +++ b/src/dao/com/l2jserver/db/MySQL5DAOModule.java @@ -21,11 +21,13 @@ import com.google.inject.Module; import com.google.inject.Scopes; import com.l2jserver.db.dao.CharacterDAO; import com.l2jserver.db.dao.CharacterFriendDAO; +import com.l2jserver.db.dao.ChatMessageDAO; import com.l2jserver.db.dao.ClanDAO; import com.l2jserver.db.dao.ItemDAO; import com.l2jserver.db.dao.NPCDAO; import com.l2jserver.db.dao.jdbc.mysql5.MySQL5CharacterDAO; import com.l2jserver.db.dao.jdbc.mysql5.MySQL5CharacterFriendDAO; +import com.l2jserver.db.dao.jdbc.mysql5.MySQL5ChatMessageDAO; import com.l2jserver.db.dao.jdbc.mysql5.MySQL5ClanDAO; import com.l2jserver.db.dao.jdbc.mysql5.MySQL5ItemDAO; import com.l2jserver.db.dao.jdbc.mysql5.MySQL5NPCDAO; @@ -47,5 +49,9 @@ public class MySQL5DAOModule extends AbstractModule { bind(ItemDAO.class).to(MySQL5ItemDAO.class).in(Scopes.SINGLETON); bind(ClanDAO.class).to(MySQL5ClanDAO.class).in(Scopes.SINGLETON); + + // logs + bind(ChatMessageDAO.class).to(MySQL5ChatMessageDAO.class).in( + Scopes.SINGLETON); } } diff --git a/src/dao/com/l2jserver/db/dao/ChatMessageDAO.java b/src/dao/com/l2jserver/db/dao/ChatMessageDAO.java new file mode 100644 index 000000000..241728724 --- /dev/null +++ b/src/dao/com/l2jserver/db/dao/ChatMessageDAO.java @@ -0,0 +1,32 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.db.dao; + +import com.l2jserver.model.id.ChatMessageID; +import com.l2jserver.model.server.ChatMessage; +import com.l2jserver.service.cache.Cacheable; +import com.l2jserver.service.database.DataAccessObject; + +/** + * The {@link ChatMessageDAO} is can load and save {@link ChatMessage chat + * messages}. + * + * @author Rogiel + */ +public interface ChatMessageDAO extends + DataAccessObject, Cacheable { +} diff --git a/src/dao/com/l2jserver/db/dao/jdbc/JDBCChatMessageDAO.java b/src/dao/com/l2jserver/db/dao/jdbc/JDBCChatMessageDAO.java new file mode 100644 index 000000000..767d03498 --- /dev/null +++ b/src/dao/com/l2jserver/db/dao/jdbc/JDBCChatMessageDAO.java @@ -0,0 +1,210 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.db.dao.jdbc; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Date; +import java.util.List; + +import com.google.inject.Inject; +import com.l2jserver.db.dao.CharacterDAO; +import com.l2jserver.db.dao.ChatMessageDAO; +import com.l2jserver.model.id.ChatMessageID; +import com.l2jserver.model.id.object.CharacterID; +import com.l2jserver.model.id.object.provider.CharacterIDProvider; +import com.l2jserver.model.id.provider.ChatMessageIDProvider; +import com.l2jserver.model.server.ChatMessage; +import com.l2jserver.service.database.DatabaseService; +import com.l2jserver.service.database.JDBCDatabaseService.CachedMapper; +import com.l2jserver.service.database.JDBCDatabaseService.InsertUpdateQuery; +import com.l2jserver.service.database.JDBCDatabaseService.Mapper; +import com.l2jserver.service.database.JDBCDatabaseService.SelectListQuery; +import com.l2jserver.service.database.JDBCDatabaseService.SelectSingleQuery; +import com.l2jserver.service.game.chat.ChatMessageType; + +/** + * {@link CharacterDAO} implementation for JDBC + * + * @author Rogiel + */ +public abstract class JDBCChatMessageDAO extends + AbstractJDBCDAO implements ChatMessageDAO { + /** + * The {@link ChatMessageID} factory + */ + private final ChatMessageIDProvider idFactory; + /** + * The {@link CharacterID} factory + */ + private final CharacterIDProvider charIdFactory; + + /** + * Character table name + */ + public static final String TABLE = "log_chat"; + // FIELDS + public static final String MESSAGE_ID = "message_id"; + public static final String TYPE = "type"; + public static final String CHANNEL_ID = "channel_id"; + public static final String SENDER = "sender"; + public static final String DATE = "date"; + public static final String MESSAGE = "message"; + + @Inject + public JDBCChatMessageDAO(DatabaseService database, + ChatMessageIDProvider idFactory, + final CharacterIDProvider charIdFactory) { + super(database); + this.idFactory = idFactory; + this.charIdFactory = charIdFactory; + } + + /** + * The {@link Mapper} for {@link ChatMessageID} + */ + private final Mapper idMapper = new Mapper() { + @Override + public ChatMessageID map(ResultSet rs) throws SQLException { + return idFactory.createID(rs.getInt(MESSAGE_ID)); + } + }; + + /** + * The {@link Mapper} for {@link ChatMessage} + */ + private final Mapper mapper = new CachedMapper( + database, idMapper) { + @Override + protected ChatMessage map(ChatMessageID id, ResultSet rs) + throws SQLException { + final ChatMessage message = new ChatMessage(); + message.setID(id); + + message.setType(ChatMessageType.valueOf(rs.getString(TYPE))); + switch (message.getType()) { + case SHOUT: + message.setTarget(charIdFactory.createID(rs.getInt(CHANNEL_ID))); + break; + default: + message.setChannelID(rs.getInt(CHANNEL_ID)); + break; + } + message.setSender(charIdFactory.createID(rs.getInt(SENDER))); + message.setDate(new Date(rs.getTimestamp(DATE).getTime())); + message.setMessage(rs.getString(MESSAGE)); + + return message; + } + }; + + @Override + public ChatMessage select(final ChatMessageID id) { + return database.query(new SelectSingleQuery() { + @Override + protected String query() { + return "SELECT * FROM `" + TABLE + "` WHERE `" + MESSAGE_ID + + "` = ?"; + } + + @Override + protected void parametize(PreparedStatement st) throws SQLException { + st.setInt(1, id.getID()); + } + + @Override + protected Mapper mapper() { + return mapper; + } + }); + } + + @Override + public List selectIDs() { + return database.query(new SelectListQuery() { + @Override + protected String query() { + return "SELECT * FROM `" + TABLE + "`"; + } + + @Override + protected Mapper mapper() { + return idMapper; + } + }); + } + + @Override + public boolean insert(ChatMessage message) { + return database.query(new InsertUpdateQuery(message) { + @Override + protected String query() { + return "INSERT INTO `" + TABLE + "` (`" + TYPE + "`,`" + + CHANNEL_ID + "`,`" + SENDER + "`,`" + DATE + "`,`" + + MESSAGE + "`) VALUES(?,?,?,?,?)"; + } + + @Override + protected void parametize(PreparedStatement st, ChatMessage message) + throws SQLException { + int i = 1; + st.setString(i++, message.getType().name()); + switch (message.getType()) { + case SHOUT: + st.setInt(i++, message.getTarget().getID()); + break; + default: + st.setInt(i++, message.getChannelID()); + break; + } + st.setInt(i++, message.getSender().getID()); + st.setTimestamp(i++, new Timestamp(message.getDate().getTime())); + st.setString(i++, message.getMessage()); + } + + @Override + protected Mapper keyMapper() { + return idMapper; + } + }) > 0; + } + + @Override + public boolean update(ChatMessage message) { + // cannot update chat message logs + return false; + } + + @Override + public boolean delete(ChatMessage message) { + return database.query(new InsertUpdateQuery(message) { + @Override + protected String query() { + return "DELETE FROM `" + TABLE + "` WHERE `" + MESSAGE_ID + + "` = ?"; + } + + @Override + protected void parametize(PreparedStatement st, ChatMessage message) + throws SQLException { + st.setInt(1, message.getID().getID()); + } + }) > 0; + } +} diff --git a/src/dao/com/l2jserver/db/dao/jdbc/h2/H2ChatMessageDAO.java b/src/dao/com/l2jserver/db/dao/jdbc/h2/H2ChatMessageDAO.java new file mode 100644 index 000000000..56bba9f40 --- /dev/null +++ b/src/dao/com/l2jserver/db/dao/jdbc/h2/H2ChatMessageDAO.java @@ -0,0 +1,38 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.db.dao.jdbc.h2; + +import com.google.inject.Inject; +import com.l2jserver.db.dao.ChatMessageDAO; +import com.l2jserver.db.dao.jdbc.JDBCChatMessageDAO; +import com.l2jserver.model.id.object.provider.CharacterIDProvider; +import com.l2jserver.model.id.provider.ChatMessageIDProvider; +import com.l2jserver.service.database.DatabaseService; + +/** + * {@link ChatMessageDAO} implementation for H2 database + * + * @author Rogiel + */ +public class H2ChatMessageDAO extends JDBCChatMessageDAO implements + ChatMessageDAO { + @Inject + public H2ChatMessageDAO(DatabaseService database, + ChatMessageIDProvider idFactory, CharacterIDProvider charIdFactory) { + super(database, idFactory, charIdFactory); + } +} diff --git a/src/dao/com/l2jserver/db/dao/jdbc/mysql5/MySQL5ChatMessageDAO.java b/src/dao/com/l2jserver/db/dao/jdbc/mysql5/MySQL5ChatMessageDAO.java new file mode 100644 index 000000000..76ace5742 --- /dev/null +++ b/src/dao/com/l2jserver/db/dao/jdbc/mysql5/MySQL5ChatMessageDAO.java @@ -0,0 +1,38 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.db.dao.jdbc.mysql5; + +import com.google.inject.Inject; +import com.l2jserver.db.dao.ChatMessageDAO; +import com.l2jserver.db.dao.jdbc.JDBCChatMessageDAO; +import com.l2jserver.model.id.object.provider.CharacterIDProvider; +import com.l2jserver.model.id.provider.ChatMessageIDProvider; +import com.l2jserver.service.database.DatabaseService; + +/** + * {@link ChatMessageDAO} implementation for MySQL5 + * + * @author Rogiel + */ +public class MySQL5ChatMessageDAO extends JDBCChatMessageDAO implements + ChatMessageDAO { + @Inject + public MySQL5ChatMessageDAO(DatabaseService database, + ChatMessageIDProvider idFactory, CharacterIDProvider charIdFactory) { + super(database, idFactory, charIdFactory); + } +} diff --git a/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketReader.java b/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketReader.java index 65fb21246..6ffcf6979 100644 --- a/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketReader.java +++ b/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketReader.java @@ -140,7 +140,7 @@ public class Lineage2PacketReader extends OneToOneDecoder { return CM_CHAR_CREATE.class; case CM_REQUEST_CHAR_TEMPLATE.OPCODE: return CM_REQUEST_CHAR_TEMPLATE.class; - case 0xd0: // CM_EXTENDED + case 0xd0: // CM_REQ_************** final int opcode2 = buffer.readUnsignedShort(); switch (opcode2) { case CM_GOTO_LOBBY.OPCODE2: @@ -152,7 +152,7 @@ public class Lineage2PacketReader extends OneToOneDecoder { case CM_EXT_REQ_ALL_FORTRESS_INFO.OPCODE2: return CM_EXT_REQ_ALL_FORTRESS_INFO.class; default: - logger.warn("Unknown opcode2 for 0xd0: 0x{}", + logger.warn("Unknown packet for 0xd0{}", Integer.toHexString(opcode2)); break; } @@ -188,7 +188,7 @@ public class Lineage2PacketReader extends OneToOneDecoder { case CM_ATTACK.OPCODE: return CM_ATTACK.class; default: - logger.warn("Unknown opcode: 0x{}", Integer.toHexString(opcode)); + logger.warn("Unknown packet for 0x{}", Integer.toHexString(opcode)); break; } return null; diff --git a/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketWriter.java b/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketWriter.java index 007e771a6..fbafc93ea 100644 --- a/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketWriter.java +++ b/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketWriter.java @@ -53,7 +53,7 @@ public class Lineage2PacketWriter extends OneToOneEncoder { final ChannelBuffer buffer = ChannelBuffers.dynamicBuffer( ByteOrder.LITTLE_ENDIAN, 10); final ServerPacket packet = (ServerPacket) msg; - buffer.writeShort(0); + buffer.writeShort(0); // wrap 2 bytes for packet length buffer.writeByte(packet.getOpcode()); // packet opcode packet.write(connection, buffer); diff --git a/src/main/java/com/l2jserver/game/net/packet/client/CM_CHAT.java b/src/main/java/com/l2jserver/game/net/packet/client/CM_CHAT.java index 7eed162cf..62fb04bee 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/CM_CHAT.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/CM_CHAT.java @@ -25,7 +25,7 @@ import com.l2jserver.game.net.packet.AbstractClientPacket; import com.l2jserver.game.net.packet.server.SM_ACTION_FAILED; import com.l2jserver.service.game.chat.CannotChatToSelfChatServiceException; import com.l2jserver.service.game.chat.ChatBanActiveChatServiceException; -import com.l2jserver.service.game.chat.ChatMessageDestination; +import com.l2jserver.service.game.chat.ChatMessageType; import com.l2jserver.service.game.chat.ChatService; import com.l2jserver.service.game.chat.ChatTargetOfflineServiceException; import com.l2jserver.service.game.chat.TargetNotFoundChatServiceException; @@ -50,7 +50,7 @@ public class CM_CHAT extends AbstractClientPacket { private final ChatService chatService; private String message; - private ChatMessageDestination destination; + private ChatMessageType destination; private String target; @@ -62,8 +62,8 @@ public class CM_CHAT extends AbstractClientPacket { @Override public void read(Lineage2Client conn, ChannelBuffer buffer) { this.message = BufferUtils.readString(buffer); - this.destination = ChatMessageDestination.fromID(buffer.readInt()); - if (this.destination == ChatMessageDestination.TELL) { // private + this.destination = ChatMessageType.fromID(buffer.readInt()); + if (this.destination == ChatMessageType.TELL) { // private // message this.target = BufferUtils.readString(buffer); } diff --git a/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAT.java b/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAT.java index 0e928eaaf..60c4a118d 100644 --- a/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAT.java +++ b/src/main/java/com/l2jserver/game/net/packet/server/SM_CHAT.java @@ -22,7 +22,7 @@ import com.l2jserver.game.net.Lineage2Client; import com.l2jserver.game.net.packet.AbstractServerPacket; import com.l2jserver.model.world.Actor; import com.l2jserver.model.world.L2Character; -import com.l2jserver.service.game.chat.ChatMessageDestination; +import com.l2jserver.service.game.chat.ChatMessageType; import com.l2jserver.util.BufferUtils; /** @@ -44,7 +44,7 @@ public class SM_CHAT extends AbstractServerPacket { /** * The message destination */ - private ChatMessageDestination destination; + private ChatMessageType destination; /** * The message */ @@ -54,7 +54,7 @@ public class SM_CHAT extends AbstractServerPacket { */ private int messageID = 0; - public SM_CHAT(Actor character, ChatMessageDestination destination, + public SM_CHAT(Actor character, ChatMessageType destination, String message) { super(OPCODE); this.actor = character; @@ -62,7 +62,7 @@ public class SM_CHAT extends AbstractServerPacket { this.message = message; } - public SM_CHAT(Actor actor, ChatMessageDestination destination, + public SM_CHAT(Actor actor, ChatMessageType destination, int messageID) { super(OPCODE); this.actor = actor; diff --git a/src/main/java/com/l2jserver/game/net/packet/server/SM_GG_QUERY.java b/src/main/java/com/l2jserver/game/net/packet/server/SM_GG_QUERY.java index 925e411d2..3847be749 100644 --- a/src/main/java/com/l2jserver/game/net/packet/server/SM_GG_QUERY.java +++ b/src/main/java/com/l2jserver/game/net/packet/server/SM_GG_QUERY.java @@ -18,6 +18,7 @@ package com.l2jserver.game.net.packet.server; import org.jboss.netty.buffer.ChannelBuffer; +import com.google.common.base.Preconditions; import com.l2jserver.game.net.Lineage2Client; import com.l2jserver.game.net.packet.AbstractServerPacket; @@ -33,16 +34,28 @@ public class SM_GG_QUERY extends AbstractServerPacket { */ public static final int OPCODE = 0x74; - public SM_GG_QUERY() { - super(OPCODE); + private final int[] key; + public SM_GG_QUERY(int[] key) { + super(OPCODE); + Preconditions.checkArgument(key.length == 4, + "key must by an 4-length array"); + this.key = key; + } + + public SM_GG_QUERY(int key1, int key2, int key3, int key4) { + super(OPCODE); + this.key = new int[4]; + this.key[0] = key1; + this.key[1] = key2; + this.key[2] = key3; + this.key[3] = key4; } @Override public void write(Lineage2Client conn, ChannelBuffer buffer) { - buffer.writeInt(0x27533DD9); - buffer.writeInt(0x2E72A51D); - buffer.writeInt(0x2017038B); - buffer.writeInt(0xC35B1EA3); + for (final int part : key) { + buffer.writeInt(part); + } } } diff --git a/src/main/java/com/l2jserver/model/id/ChatMessageID.java b/src/main/java/com/l2jserver/model/id/ChatMessageID.java new file mode 100644 index 000000000..b95ec4070 --- /dev/null +++ b/src/main/java/com/l2jserver/model/id/ChatMessageID.java @@ -0,0 +1,39 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.model.id; + +import com.google.inject.Inject; +import com.google.inject.assistedinject.Assisted; +import com.l2jserver.model.server.ChatMessage; + +/** + * Each {@link ChatMessage} log entry is identified by an {@link ID}. + * + * @author Rogiel + */ +public class ChatMessageID extends ID { + /** + * Creates a new instance + * + * @param id + * the id + */ + @Inject + public ChatMessageID(@Assisted int id) { + super(id); + } +} diff --git a/src/main/java/com/l2jserver/model/id/provider/ChatMessageIDProvider.java b/src/main/java/com/l2jserver/model/id/provider/ChatMessageIDProvider.java new file mode 100644 index 000000000..be2be8525 --- /dev/null +++ b/src/main/java/com/l2jserver/model/id/provider/ChatMessageIDProvider.java @@ -0,0 +1,28 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.model.id.provider; + +import com.l2jserver.model.id.ChatMessageID; + +/** + * Creates a new {@link ChatMessageID} + * + * @author Rogiel + */ +public interface ChatMessageIDProvider extends + IDProvider { +} diff --git a/src/main/java/com/l2jserver/model/server/ChatMessage.java b/src/main/java/com/l2jserver/model/server/ChatMessage.java new file mode 100644 index 000000000..ffc568fb2 --- /dev/null +++ b/src/main/java/com/l2jserver/model/server/ChatMessage.java @@ -0,0 +1,155 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.model.server; + +import java.util.Date; + +import com.l2jserver.model.AbstractModel; +import com.l2jserver.model.Model; +import com.l2jserver.model.id.ChatMessageID; +import com.l2jserver.model.id.object.CharacterID; +import com.l2jserver.service.game.chat.ChatMessageType; + +/** + * This is an chat message stored in the database for logging purposes. It can, + * however, be used as a form of flood-checking. + * + * @author Rogiel + */ +public class ChatMessage extends AbstractModel implements + Model { + /** + * The chat message type. + *

+ * If {@link ChatMessageType#SHOUT} target will be set and + * channelID will be null.
+ * Otherwise, target is null and channelID will + * be set. + */ + private ChatMessageType type; + /** + * The channel numeric ID + */ + private int channelID; + /** + * The message target ID, if any. + */ + private CharacterID target; + + /** + * The sender ID, if any. + */ + private CharacterID sender; + /** + * The message log date + */ + private Date date; + /** + * The message content + */ + private String message; + + /** + * @return the type + */ + public ChatMessageType getType() { + return type; + } + + /** + * @param type + * the type to set + */ + public void setType(ChatMessageType type) { + this.type = type; + } + + /** + * @return the channelID + */ + public int getChannelID() { + return channelID; + } + + /** + * @param channelID + * the channelID to set + */ + public void setChannelID(int channelID) { + this.channelID = channelID; + } + + /** + * @return the target + */ + public CharacterID getTarget() { + return target; + } + + /** + * @param target + * the target to set + */ + public void setTarget(CharacterID target) { + this.target = target; + } + + /** + * @return the sender + */ + public CharacterID getSender() { + return sender; + } + + /** + * @param sender + * the sender to set + */ + public void setSender(CharacterID sender) { + this.sender = sender; + } + + /** + * @return the date + */ + public Date getDate() { + return date; + } + + /** + * @param date + * the date to set + */ + public void setDate(Date date) { + this.date = date; + } + + /** + * @return the message + */ + public String getMessage() { + return message; + } + + /** + * @param message + * the message to set + */ + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/com/l2jserver/service/ServiceModule.java b/src/main/java/com/l2jserver/service/ServiceModule.java index 10a4b8cb6..a447e66e0 100644 --- a/src/main/java/com/l2jserver/service/ServiceModule.java +++ b/src/main/java/com/l2jserver/service/ServiceModule.java @@ -37,7 +37,9 @@ import com.l2jserver.service.game.admin.AdministratorService; import com.l2jserver.service.game.admin.AdministratorServiceImpl; import com.l2jserver.service.game.character.CharacterService; import com.l2jserver.service.game.character.CharacterServiceImpl; +import com.l2jserver.service.game.chat.ChatLoggingService; import com.l2jserver.service.game.chat.ChatService; +import com.l2jserver.service.game.chat.DatabaseChatLoggingService; import com.l2jserver.service.game.chat.SimpleChatService; import com.l2jserver.service.game.map.pathing.MapperPathingService; import com.l2jserver.service.game.map.pathing.PathingService; @@ -104,6 +106,8 @@ public class ServiceModule extends AbstractModule { bind(ChatService.class).to(SimpleChatService.class) .in(Scopes.SINGLETON); + bind(ChatLoggingService.class).to(DatabaseChatLoggingService.class).in( + Scopes.SINGLETON); bind(AdministratorService.class).to(AdministratorServiceImpl.class).in( Scopes.SINGLETON); bind(SpawnService.class).to(SpawnServiceImpl.class) diff --git a/src/main/java/com/l2jserver/service/core/log4j/TruncateToZipFileAppender.java b/src/main/java/com/l2jserver/service/core/log4j/TruncateToZipFileAppender.java index 6c8aaf077..b1a43031c 100644 --- a/src/main/java/com/l2jserver/service/core/log4j/TruncateToZipFileAppender.java +++ b/src/main/java/com/l2jserver/service/core/log4j/TruncateToZipFileAppender.java @@ -41,7 +41,6 @@ import org.apache.log4j.helpers.LogLog; * @author Rogiel */ public class TruncateToZipFileAppender extends FileAppender { - /** * String that points to root directory for backups */ diff --git a/src/main/java/com/l2jserver/service/database/JDBCDatabaseService.java b/src/main/java/com/l2jserver/service/database/JDBCDatabaseService.java index 54b410fe2..41201633b 100644 --- a/src/main/java/com/l2jserver/service/database/JDBCDatabaseService.java +++ b/src/main/java/com/l2jserver/service/database/JDBCDatabaseService.java @@ -67,7 +67,7 @@ import com.l2jserver.util.ClassUtils; import com.l2jserver.util.factory.CollectionFactory; /** - * The database service implementation for MySQL database + * The database service implementation for JDBC database * * @author Rogiel */ @@ -325,6 +325,7 @@ public class JDBCDatabaseService extends AbstractService implements this.iterator = iterator; } + @SuppressWarnings("unchecked") @Override public Integer query(Connection conn) throws SQLException { Preconditions.checkNotNull(conn, "conn"); @@ -336,15 +337,17 @@ public class JDBCDatabaseService extends AbstractService implements rows += st.executeUpdate(); // update object desire --it has been realized - if (object instanceof Model) + if (object instanceof Model) { ((Model) object).setObjectDesire(ObjectDesire.NONE); - final Mapper mapper = keyMapper(object); - if (mapper == null) - continue; - final ResultSet rs = st.getGeneratedKeys(); - while (rs.next()) { - mapper.map(rs); + final Mapper> mapper = keyMapper(); + if (mapper == null) + continue; + final ResultSet rs = st.getGeneratedKeys(); + while (rs.next()) { + ((Model>) object).setID(mapper.map(rs)); + mapper.map(rs); + } } } return rows; @@ -377,7 +380,7 @@ public class JDBCDatabaseService extends AbstractService implements * the object * @return the key mapper */ - protected Mapper keyMapper(T object) { + protected Mapper> keyMapper() { return null; } } diff --git a/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java b/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java index b05362c8c..c0f3ac086 100644 --- a/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java +++ b/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java @@ -30,6 +30,7 @@ import com.l2jserver.game.net.packet.server.SM_MOVE; import com.l2jserver.game.net.packet.server.SM_MOVE_TYPE; import com.l2jserver.game.net.packet.server.SM_TARGET; import com.l2jserver.model.id.object.CharacterID; +import com.l2jserver.model.server.ChatMessage; import com.l2jserver.model.world.Actor; import com.l2jserver.model.world.Actor.ActorState; import com.l2jserver.model.world.L2Character; @@ -49,7 +50,7 @@ import com.l2jserver.service.AbstractService.Depends; import com.l2jserver.service.game.AttackService; import com.l2jserver.service.game.chat.ChatChannel; import com.l2jserver.service.game.chat.ChatChannelListener; -import com.l2jserver.service.game.chat.ChatMessageDestination; +import com.l2jserver.service.game.chat.ChatMessageType; import com.l2jserver.service.game.chat.ChatService; import com.l2jserver.service.game.npc.NPCService; import com.l2jserver.service.game.npc.NotAttackableNPCServiceException; @@ -148,18 +149,16 @@ public class CharacterServiceImpl extends AbstractService implements // chat listener final ChatChannelListener globalChatListener = new ChatChannelListener() { @Override - public void onMessage(ChatChannel channel, CharacterID source, - String message) { - conn.write(new SM_CHAT(source.getObject(), - ChatMessageDestination.ALL, message)); + public void onMessage(ChatChannel channel, ChatMessage message) { + conn.write(new SM_CHAT(message.getSender().getObject(), + ChatMessageType.ALL, message.getMessage())); } }; final ChatChannelListener tradeChatListener = new ChatChannelListener() { @Override - public void onMessage(ChatChannel channel, CharacterID source, - String message) { - conn.write(new SM_CHAT(source.getObject(), - ChatMessageDestination.TRADE, message)); + public void onMessage(ChatChannel channel, ChatMessage message) { + conn.write(new SM_CHAT(message.getSender().getObject(), + ChatMessageType.TRADE, message.getMessage())); } }; @@ -205,7 +204,7 @@ public class CharacterServiceImpl extends AbstractService implements // start broadcasting -- will broadcast all nearby objects broadcastService.broadcast(conn); - + conn.write(new SM_ITEM_GROUND()); // characters start in run mode diff --git a/src/main/java/com/l2jserver/service/game/chat/ChatChannel.java b/src/main/java/com/l2jserver/service/game/chat/ChatChannel.java index 241539111..9ee738e4e 100644 --- a/src/main/java/com/l2jserver/service/game/chat/ChatChannel.java +++ b/src/main/java/com/l2jserver/service/game/chat/ChatChannel.java @@ -17,6 +17,7 @@ package com.l2jserver.service.game.chat; import com.l2jserver.model.id.object.CharacterID; +import com.l2jserver.model.server.ChatMessage; /** * The {@link ChatChannel} object is used to send messages to a channel. @@ -29,7 +30,10 @@ import com.l2jserver.model.id.object.CharacterID; */ public interface ChatChannel { /** - * Sends a message to this channel + * Sends a message to this channel. + *

+ * Unless otherwise stated, all messages sent will be automatically logged + * using {@link ChatLoggingService}. * * @param sender * the character sending the message @@ -40,8 +44,10 @@ public interface ChatChannel { * @throws ChatTargetOfflineServiceException * if the target is offline. Will be be thrown in * {@link PrivateChatChannel}. + * @return the created {@link ChatMessage}. The object will be created by + * {@link ChatLoggingService}. */ - void send(CharacterID sender, String message) + ChatMessage send(CharacterID sender, String message) throws ChatBanActiveChatServiceException, ChatTargetOfflineServiceException; @@ -61,4 +67,19 @@ public interface ChatChannel { * the listener */ void removeChatChannelListener(ChatChannelListener listener); + + /** + * @return the chat channel numeric ID + */ + int getChannelID(); + + /** + * @return the chat message type accepted by this channel + */ + ChatMessageType getMessageType(); + + /** + * @return the chat channel name + */ + String getChannelName(); } diff --git a/src/main/java/com/l2jserver/service/game/chat/ChatChannelListener.java b/src/main/java/com/l2jserver/service/game/chat/ChatChannelListener.java index 1f3ba31db..3dec87785 100644 --- a/src/main/java/com/l2jserver/service/game/chat/ChatChannelListener.java +++ b/src/main/java/com/l2jserver/service/game/chat/ChatChannelListener.java @@ -16,7 +16,7 @@ */ package com.l2jserver.service.game.chat; -import com.l2jserver.model.id.object.CharacterID; +import com.l2jserver.model.server.ChatMessage; /** * This listener is used to received notifications once a new message is sent to @@ -30,10 +30,8 @@ public interface ChatChannelListener { * * @param channel * the chat channel - * @param source - * the character sending this message * @param message * the message */ - void onMessage(ChatChannel channel, CharacterID source, String message); + void onMessage(ChatChannel channel, ChatMessage message); } diff --git a/src/main/java/com/l2jserver/service/game/chat/ChatLoggingService.java b/src/main/java/com/l2jserver/service/game/chat/ChatLoggingService.java new file mode 100644 index 000000000..b0d155e08 --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/chat/ChatLoggingService.java @@ -0,0 +1,42 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.service.game.chat; + +import com.l2jserver.model.id.object.CharacterID; +import com.l2jserver.model.server.ChatMessage; +import com.l2jserver.service.Service; + +/** + * This service logs each message sent in the server. Implementarions may choose + * to store in a database, plain text, XML or any other form of logging. + * + * @author Rogiel + */ +public interface ChatLoggingService extends Service { + /** + * Sends a message to a public chat channel. + * + * @param sender + * the sender + * @param channel + * the chat channel + * @param message + * the message + * @return the new ChatMessage created + */ + ChatMessage log(CharacterID sender, ChatChannel channel, String message); +} diff --git a/src/main/java/com/l2jserver/service/game/chat/ChatMessageDestination.java b/src/main/java/com/l2jserver/service/game/chat/ChatMessageType.java similarity index 86% rename from src/main/java/com/l2jserver/service/game/chat/ChatMessageDestination.java rename to src/main/java/com/l2jserver/service/game/chat/ChatMessageType.java index 24a093637..d204be812 100644 --- a/src/main/java/com/l2jserver/service/game/chat/ChatMessageDestination.java +++ b/src/main/java/com/l2jserver/service/game/chat/ChatMessageType.java @@ -17,11 +17,11 @@ package com.l2jserver.service.game.chat; /** - * Enumeration of all possible message destinations + * Enumeration of all possible message types * * @author Rogiel */ -public enum ChatMessageDestination { +public enum ChatMessageType { /** * Everyone */ @@ -63,12 +63,12 @@ public enum ChatMessageDestination { public final int id; - ChatMessageDestination(int id) { + ChatMessageType(int id) { this.id = id; } - public static ChatMessageDestination fromID(int id) { - for (final ChatMessageDestination dest : values()) { + public static ChatMessageType fromID(int id) { + for (final ChatMessageType dest : values()) { if (dest.id == id) return dest; } diff --git a/src/main/java/com/l2jserver/service/game/chat/ChatService.java b/src/main/java/com/l2jserver/service/game/chat/ChatService.java index a787f40ab..df21f6587 100644 --- a/src/main/java/com/l2jserver/service/game/chat/ChatService.java +++ b/src/main/java/com/l2jserver/service/game/chat/ChatService.java @@ -18,18 +18,22 @@ package com.l2jserver.service.game.chat; import com.l2jserver.model.id.object.CharacterID; import com.l2jserver.model.id.object.ClanID; +import com.l2jserver.model.server.ChatMessage; import com.l2jserver.model.world.L2Character; import com.l2jserver.service.Service; /** - * This service chatting in the server. Implementations can be local or can use - * another service like an IRC server. + * This service provides chatting in the server. Implementations can be local or + * can use another service like an IRC server. * * @author Rogiel */ public interface ChatService extends Service { /** * Sends a message to a public chat channel. + *

+ * Messages sent will be automatically logged using + * {@link ChatLoggingService}. * * @param sender * the sender @@ -47,8 +51,10 @@ public interface ChatService extends Service { * if there is chat ban active * @throws ChatTargetOfflineServiceException * if the chat target is offline + * @return the created {@link ChatMessage}. The object will be created by + * {@link ChatLoggingService}. */ - void send(CharacterID sender, ChatMessageDestination chat, String message, + ChatMessage send(CharacterID sender, ChatMessageType chat, String message, String extra) throws TargetNotFoundChatServiceException, CannotChatToSelfChatServiceException, ChatBanActiveChatServiceException, diff --git a/src/main/java/com/l2jserver/service/game/chat/DatabaseChatLoggingService.java b/src/main/java/com/l2jserver/service/game/chat/DatabaseChatLoggingService.java new file mode 100644 index 000000000..b56a32489 --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/chat/DatabaseChatLoggingService.java @@ -0,0 +1,78 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.service.game.chat; + +import java.util.Date; + +import com.google.inject.Inject; +import com.l2jserver.db.dao.ChatMessageDAO; +import com.l2jserver.model.id.object.CharacterID; +import com.l2jserver.model.id.object.provider.CharacterIDProvider; +import com.l2jserver.model.server.ChatMessage; +import com.l2jserver.service.AbstractService; + +/** + * {@link ChatLoggingService} implementation that stores logs in the database + * + * @author Rogiel + */ +public class DatabaseChatLoggingService extends AbstractService implements + ChatLoggingService { + /** + * The {@link ChatMessage} DAO + */ + private final ChatMessageDAO chatMessageDao; + /** + * The {@link CharacterID} provider + */ + private final CharacterIDProvider charIdProvider; + + @Inject + protected DatabaseChatLoggingService(ChatMessageDAO chatMessageDao, + CharacterIDProvider charIdProvider) { + this.chatMessageDao = chatMessageDao; + this.charIdProvider = charIdProvider; + } + + @Override + public ChatMessage log(CharacterID sender, ChatChannel channel, + String messageText) { + final ChatMessage message = new ChatMessage(); + + // message type and destination + message.setType(channel.getMessageType()); + switch (channel.getMessageType()) { + case SHOUT: // if type is SHOUT the ChannelID is the CharacterID + // (target) + message.setTarget(charIdProvider.createID(channel.getChannelID())); + break; + default: + message.setChannelID(channel.getChannelID()); + break; + } + + // message information + message.setSender(sender); + message.setDate(new Date()); + message.setMessage(messageText); + + // save in database + chatMessageDao.save(message, true); + + return message; + } +} diff --git a/src/main/java/com/l2jserver/service/game/chat/SimpleChatService.java b/src/main/java/com/l2jserver/service/game/chat/SimpleChatService.java index bcb5be274..0045a27a3 100644 --- a/src/main/java/com/l2jserver/service/game/chat/SimpleChatService.java +++ b/src/main/java/com/l2jserver/service/game/chat/SimpleChatService.java @@ -24,6 +24,7 @@ import com.google.inject.Inject; import com.l2jserver.db.dao.CharacterDAO; import com.l2jserver.model.id.object.CharacterID; import com.l2jserver.model.id.object.ClanID; +import com.l2jserver.model.server.ChatMessage; import com.l2jserver.model.world.Clan; import com.l2jserver.model.world.L2Character; import com.l2jserver.service.AbstractService; @@ -40,6 +41,8 @@ import com.l2jserver.util.factory.CollectionFactory; */ // @Depends(RegionService.class) public class SimpleChatService extends AbstractService implements ChatService { + private final ChatLoggingService chatLoggingService; + /** * The {@link RegionService} */ @@ -83,7 +86,9 @@ public class SimpleChatService extends AbstractService implements ChatService { * the region service */ @Inject - public SimpleChatService(CharacterDAO charDao) { + public SimpleChatService(ChatLoggingService chatLogService, + CharacterDAO charDao) { + this.chatLoggingService = chatLogService; // this.regionService = regionService; this.regionService = null; this.charDao = charDao; @@ -100,11 +105,11 @@ public class SimpleChatService extends AbstractService implements ChatService { } @Override - public void send(CharacterID sender, ChatMessageDestination chat, - String message, String extra) - throws TargetNotFoundChatServiceException, + public ChatMessage send(CharacterID sender, ChatMessageType chat, String message, + String extra) throws TargetNotFoundChatServiceException, CannotChatToSelfChatServiceException, - ChatBanActiveChatServiceException, ChatTargetOfflineServiceException { + ChatBanActiveChatServiceException, + ChatTargetOfflineServiceException { Preconditions.checkNotNull(sender, "sender"); Preconditions.checkNotNull(message, "message"); @@ -131,9 +136,9 @@ public class SimpleChatService extends AbstractService implements ChatService { channel = getAnnouncementChannel(); break; default: - return; + return null; } - channel.send(sender, message); + return channel.send(sender, message); } @Override @@ -210,13 +215,20 @@ public class SimpleChatService extends AbstractService implements ChatService { .newSet(); @Override - public void send(CharacterID sender, String message) { + public ChatMessage send(CharacterID sender, String textMessage) { Preconditions.checkNotNull(sender, "sender"); - Preconditions.checkNotNull(message, "message"); + Preconditions.checkNotNull(textMessage, "message"); // TODO throw exception if sender is banned from chat + + // log this chat message + ChatMessage message = chatLoggingService.log(sender, this, + textMessage); + for (final ChatChannelListener listener : listeners) { - listener.onMessage(this, sender, message); + listener.onMessage(this, message); } + + return message; } @Override @@ -230,6 +242,16 @@ public class SimpleChatService extends AbstractService implements ChatService { Preconditions.checkNotNull(listener, "listener"); listeners.remove(listener); } + + @Override + public String getChannelName() { + return getMessageType().name(); + } + + @Override + public int getChannelID() { + return getMessageType().id; + } } /** @@ -250,6 +272,16 @@ public class SimpleChatService extends AbstractService implements ChatService { public CharacterID getDestination() { return character; } + + @Override + public int getChannelID() { + return character.getID(); + } + + @Override + public ChatMessageType getMessageType() { + return ChatMessageType.SHOUT; + } } /** @@ -259,6 +291,10 @@ public class SimpleChatService extends AbstractService implements ChatService { */ private class GlobalChatChannelImpl extends ChatChannelImpl implements PublicChatChannel { + @Override + public ChatMessageType getMessageType() { + return ChatMessageType.ALL; + } } /** @@ -268,6 +304,10 @@ public class SimpleChatService extends AbstractService implements ChatService { */ private class TradeChatChannelImpl extends ChatChannelImpl implements PublicChatChannel { + @Override + public ChatMessageType getMessageType() { + return ChatMessageType.TRADE; + } } /** @@ -277,6 +317,10 @@ public class SimpleChatService extends AbstractService implements ChatService { */ private class AnnouncementChatChannelImpl extends ChatChannelImpl implements PublicChatChannel { + @Override + public ChatMessageType getMessageType() { + return ChatMessageType.ANNOUNCEMENT; + } } /** @@ -301,6 +345,11 @@ public class SimpleChatService extends AbstractService implements ChatService { Preconditions.checkNotNull(clanID, "clanID"); this.clanID = clanID; } + + @Override + public ChatMessageType getMessageType() { + return ChatMessageType.CLAN; + } } /** @@ -325,5 +374,10 @@ public class SimpleChatService extends AbstractService implements ChatService { Preconditions.checkNotNull(region, "region"); this.region = region; } + + @Override + public ChatMessageType getMessageType() { + return ChatMessageType.ALL; + } } } diff --git a/src/main/java/com/l2jserver/service/network/gameguard/GameGuardServiceImpl.java b/src/main/java/com/l2jserver/service/network/gameguard/GameGuardServiceImpl.java index 5c7e4453d..9f3d60194 100644 --- a/src/main/java/com/l2jserver/service/network/gameguard/GameGuardServiceImpl.java +++ b/src/main/java/com/l2jserver/service/network/gameguard/GameGuardServiceImpl.java @@ -43,13 +43,19 @@ import com.l2jserver.util.factory.CollectionFactory; public class GameGuardServiceImpl extends AbstractService implements GameGuardService { /** - * The valid GG SHA1 response + * The static key used to validate game guards + */ + private static final int[] STATIC_KEY = { 0x27533DD9, 0x2E72A51D, + 0x2017038B, 0xC35B1EA3 }; + /** + * The valid GG SHA1 response -- for a single key, the answer must be always + * the same */ @SuppressWarnings("unused") - private static final byte[] VALID_KEY_SHA1 = { (byte) 0x88, 0x40, 0x1c, - (byte) 0xa7, (byte) 0x83, 0x42, (byte) 0xe9, 0x15, (byte) 0xde, - (byte) 0xc3, 0x68, (byte) 0xf6, 0x2d, 0x23, (byte) 0xf1, 0x3f, - (byte) 0xee, 0x68, 0x5b, (byte) 0xc5 }; + private static final byte[] STATIC_KEY_VALIDATION = { (byte) 0x88, 0x40, + 0x1c, (byte) 0xa7, (byte) 0x83, 0x42, (byte) 0xe9, 0x15, + (byte) 0xde, (byte) 0xc3, 0x68, (byte) 0xf6, 0x2d, 0x23, + (byte) 0xf1, 0x3f, (byte) 0xee, 0x68, 0x5b, (byte) 0xc5 }; /** * The map containing all pending futures @@ -75,15 +81,16 @@ public class GameGuardServiceImpl extends AbstractService implements @Override public Future query(final Lineage2Client conn) { - conn.write(new SM_GG_QUERY()).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) - throws Exception { - if (future.getCause() != null) { - futures.remove(conn); - } - } - }); + conn.write(new SM_GG_QUERY(STATIC_KEY)).addListener( + new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) + throws Exception { + if (future.getCause() != null) { + futures.remove(conn); + } + } + }); final GGFuture future = new GGFuture(); futures.put(conn, future); return future; diff --git a/src/main/java/com/l2jserver/service/network/keygen/SecureBlowfishKeygenService.java b/src/main/java/com/l2jserver/service/network/keygen/SecureBlowfishKeygenService.java index 4256592cf..ca53f5361 100644 --- a/src/main/java/com/l2jserver/service/network/keygen/SecureBlowfishKeygenService.java +++ b/src/main/java/com/l2jserver/service/network/keygen/SecureBlowfishKeygenService.java @@ -50,7 +50,8 @@ public class SecureBlowfishKeygenService extends AbstractService implements key[i] = (byte) random.nextSecureInt(0, 255); } - // the last 8 bytes are static + // the last 8 bytes are static and are assumed by the client, they are + // never sent in the SM_KEY packet key[8] = (byte) 0xc8; key[9] = (byte) 0x27; key[10] = (byte) 0x93;