diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 000000000..0c17b5b9d --- /dev/null +++ b/data/.gitignore @@ -0,0 +1,2 @@ +/cache +/pathing.db diff --git a/pom.xml b/pom.xml index a7cec6dd6..e64ba5ddc 100644 --- a/pom.xml +++ b/pom.xml @@ -118,14 +118,7 @@ htmlparser 2.1 jar - compile - - - org.htmlparser - sitecapturer - 2.1 - jar - compile + runtime diff --git a/src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5ItemDAO.java b/src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5ItemDAO.java index c95095d84..28907baf7 100644 --- a/src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5ItemDAO.java +++ b/src/dao/mysql5/com/l2jserver/db/dao/mysql5/MySQL5ItemDAO.java @@ -33,11 +33,14 @@ import com.l2jserver.model.template.ItemTemplate; import com.l2jserver.model.world.Item; import com.l2jserver.model.world.L2Character; import com.l2jserver.model.world.character.CharacterInventory; +import com.l2jserver.model.world.character.CharacterInventory.InventoryLocation; +import com.l2jserver.model.world.character.CharacterInventory.InventoryPaperdoll; import com.l2jserver.service.database.DatabaseService; import com.l2jserver.service.database.MySQLDatabaseService.CachedMapper; import com.l2jserver.service.database.MySQLDatabaseService.Mapper; import com.l2jserver.service.database.MySQLDatabaseService.SelectListQuery; import com.l2jserver.service.database.MySQLDatabaseService.SelectSingleQuery; +import com.l2jserver.util.dimensional.Coordinate; /** * {@link ItemDAO} implementation for MySQL5 @@ -67,6 +70,13 @@ public class MySQL5ItemDAO extends AbstractMySQL5DAO implements ItemDAO { public static final String TEMPLATE_ID = "template_id"; public static final String CHAR_ID = MySQL5CharacterDAO.CHAR_ID; + public static final String LOCATION = "location"; + public static final String PAPERDOLL = "paperdoll"; + public static final String COUNT = "count"; + public static final String COORD_X = "coord_x"; + public static final String COORD_Y = "coord_y"; + public static final String COORD_Z = "coord_z"; + @Inject public MySQL5ItemDAO(DatabaseService database, final ItemIDProvider idFactory, @@ -95,7 +105,21 @@ public class MySQL5ItemDAO extends AbstractMySQL5DAO implements ItemDAO { final Item item = template.create(); item.setID(id); - item.setOwnerID(charIdFactory.createID(rs.getInt(CHAR_ID))); + if (rs.getObject(CHAR_ID) != null) + item.setOwnerID(charIdFactory.createID(rs.getInt(CHAR_ID))); + if (rs.getObject(LOCATION) != null) + item.setLocation(InventoryLocation.valueOf(rs + .getString(LOCATION))); + if (rs.getObject(PAPERDOLL) != null) + item.setPaperdoll(InventoryPaperdoll.valueOf(rs + .getString(PAPERDOLL))); + + item.setCount(rs.getInt(COUNT)); + + if (rs.getObject(COORD_X) != null && rs.getObject(COORD_Y) != null + && rs.getObject(COORD_Z) != null) + item.setPosition(Coordinate.fromXYZ(rs.getInt(COORD_X), + rs.getInt(COORD_Y), rs.getInt(COORD_Z))); return item; } @@ -107,7 +131,7 @@ public class MySQL5ItemDAO extends AbstractMySQL5DAO implements ItemDAO { private final Mapper idMapper = new Mapper() { @Override public ItemID map(ResultSet rs) throws SQLException { - return idFactory.createID(rs.getInt(CHAR_ID)); + return idFactory.createID(rs.getInt(ITEM_ID)); } }; @@ -161,7 +185,7 @@ public class MySQL5ItemDAO extends AbstractMySQL5DAO implements ItemDAO { return database.query(new SelectListQuery() { @Override protected String query() { - return "SELECT `" + CHAR_ID + "` FROM `" + TABLE + "`"; + return "SELECT `" + ITEM_ID + "` FROM `" + TABLE + "`"; } @Override diff --git a/src/main/java/com/l2jserver/L2JConstants.java b/src/main/java/com/l2jserver/L2JConstant.java similarity index 97% rename from src/main/java/com/l2jserver/L2JConstants.java rename to src/main/java/com/l2jserver/L2JConstant.java index 8633d4d51..a52adfba1 100644 --- a/src/main/java/com/l2jserver/L2JConstants.java +++ b/src/main/java/com/l2jserver/L2JConstant.java @@ -23,7 +23,7 @@ import com.l2jserver.game.ProtocolVersion; * * @author Rogiel */ -public class L2JConstants { +public class L2JConstant { /** * Indicate the supported protocol for this compilation. *

diff --git a/src/main/java/com/l2jserver/L2JGameServerMain.java b/src/main/java/com/l2jserver/L2JGameServerMain.java index ddd76743e..ec2b2ba58 100644 --- a/src/main/java/com/l2jserver/L2JGameServerMain.java +++ b/src/main/java/com/l2jserver/L2JGameServerMain.java @@ -17,19 +17,25 @@ package com.l2jserver; import com.google.inject.Injector; +import com.l2jserver.db.dao.ItemDAO; +import com.l2jserver.model.id.ObjectID; import com.l2jserver.model.id.object.provider.NPCIDProvider; +import com.l2jserver.model.id.object.provider.ObjectIDResolver; import com.l2jserver.model.id.template.NPCTemplateID; import com.l2jserver.model.id.template.provider.NPCTemplateIDProvider; +import com.l2jserver.model.world.L2Character; import com.l2jserver.model.world.NPC; import com.l2jserver.service.ServiceManager; import com.l2jserver.service.cache.CacheService; import com.l2jserver.service.configuration.ConfigurationService; import com.l2jserver.service.database.DatabaseService; +import com.l2jserver.service.game.CharacterService; import com.l2jserver.service.game.SpawnService; import com.l2jserver.service.game.chat.ChatService; +import com.l2jserver.service.game.pathing.PathingService; import com.l2jserver.service.game.scripting.ScriptingService; import com.l2jserver.service.game.template.TemplateService; -import com.l2jserver.service.game.world.id.WorldIDService; +import com.l2jserver.service.game.world.WorldIDService; import com.l2jserver.service.network.NetworkService; import com.l2jserver.service.network.keygen.BlowfishKeygenService; import com.l2jserver.util.dimensional.Point; @@ -55,6 +61,9 @@ public class L2JGameServerMain { serviceManager.start(ChatService.class); + serviceManager.start(CharacterService.class); + serviceManager.start(PathingService.class); + serviceManager.start(BlowfishKeygenService.class); serviceManager.start(NetworkService.class); @@ -86,5 +95,16 @@ public class L2JGameServerMain { npc.setPoint(Point.fromXYZ(-71301, 258259, -3134)); spawnService.spawn(npc, null); + + final ObjectIDResolver resolver = injector + .getInstance(ObjectIDResolver.class); + final ObjectID cid = resolver.resolve(268437456); + L2Character c = cid.getObject(); + + System.out + .println(injector.getInstance(ItemDAO.class).loadInventory(c)); + + System.out.println(injector.getInstance(ObjectIDResolver.class) + .resolve(268635457).getObject()); } } 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 2c83f36b0..92350270e 100644 --- a/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketReader.java +++ b/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketReader.java @@ -31,6 +31,7 @@ import com.l2jserver.game.net.packet.client.AuthLoginPacket; import com.l2jserver.game.net.packet.client.CharacterActionPacket; import com.l2jserver.game.net.packet.client.CharacterChatMessagePacket; import com.l2jserver.game.net.packet.client.CharacterCreatePacket; +import com.l2jserver.game.net.packet.client.CharacterRequestInventoryPacket; import com.l2jserver.game.net.packet.client.CharacterRequestMovePacket; import com.l2jserver.game.net.packet.client.CharacterSelectPacket; import com.l2jserver.game.net.packet.client.CharacterValidatePositionPacket; @@ -163,6 +164,8 @@ public class Lineage2PacketReader extends OneToOneDecoder { return EnterWorld.class; case CharacterActionPacket.OPCODE: return CharacterActionPacket.class; + case CharacterRequestInventoryPacket.OPCODE: + return CharacterRequestInventoryPacket.class; default: logger.warn("Unknown opcode: 0x{}", Integer.toHexString(opcode)); break; diff --git a/src/main/java/com/l2jserver/game/net/packet/client/CharacterActionPacket.java b/src/main/java/com/l2jserver/game/net/packet/client/CharacterActionPacket.java index 88dc9e498..a0ba8b1cb 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/CharacterActionPacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/CharacterActionPacket.java @@ -17,8 +17,6 @@ package com.l2jserver.game.net.packet.client; import org.jboss.netty.buffer.ChannelBuffer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.inject.Inject; import com.l2jserver.game.net.Lineage2Connection; @@ -27,7 +25,6 @@ import com.l2jserver.model.id.ObjectID; import com.l2jserver.model.id.object.NPCID; import com.l2jserver.model.id.object.provider.ObjectIDResolver; import com.l2jserver.model.world.NPC; -import com.l2jserver.service.game.world.WorldService; import com.l2jserver.util.dimensional.Coordinate; /** @@ -85,7 +82,6 @@ public class CharacterActionPacket extends AbstractClientPacket { @Override public void process(final Lineage2Connection conn) { // since this is an erasure type, this is safe. - System.out.println(objectId); final ObjectID id = idResolver.resolve(objectId); if (!(id instanceof NPCID)) { System.out.println("Incorrect type: " + id); diff --git a/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestInventoryPacket.java b/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestInventoryPacket.java new file mode 100644 index 000000000..28bdcf256 --- /dev/null +++ b/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestInventoryPacket.java @@ -0,0 +1,47 @@ +/* + * 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.game.net.packet.client; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.l2jserver.game.net.Lineage2Connection; +import com.l2jserver.game.net.packet.AbstractClientPacket; +import com.l2jserver.game.net.packet.server.CharacterInventoryPacket; +import com.l2jserver.model.world.L2Character; + +/** + * Completes the creation of an character. Creates the object, inserts into the + * database and notifies the client about the status of the operation. + * + * @author Rogiel + */ +public class CharacterRequestInventoryPacket extends AbstractClientPacket { + /** + * The packet OPCODE + */ + public static final int OPCODE = 0x14; + + @Override + public void read(Lineage2Connection conn, ChannelBuffer buffer) { + } + + @Override + public void process(final Lineage2Connection conn) { + final L2Character character = conn.getCharacter(); + conn.write(new CharacterInventoryPacket(character.getInventory())); + } +} diff --git a/src/main/java/com/l2jserver/game/net/packet/client/CharacterValidatePositionPacket.java b/src/main/java/com/l2jserver/game/net/packet/client/CharacterValidatePositionPacket.java index 44ccf0d46..c25713b8c 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/CharacterValidatePositionPacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/CharacterValidatePositionPacket.java @@ -21,8 +21,7 @@ import org.jboss.netty.buffer.ChannelBuffer; import com.google.inject.Inject; import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.packet.AbstractClientPacket; -import com.l2jserver.model.world.character.event.CharacterMoveEvent; -import com.l2jserver.service.game.world.event.WorldEventDispatcher; +import com.l2jserver.service.game.CharacterService; import com.l2jserver.util.dimensional.Point; /** @@ -37,16 +36,16 @@ public class CharacterValidatePositionPacket extends AbstractClientPacket { public static final int OPCODE = 0x59; /** - * The World Event Dispatcher + * The {@link CharacterService} */ - private final WorldEventDispatcher eventDispatcher; + private final CharacterService charService; private Point point; private int extra; // vehicle id @Inject - public CharacterValidatePositionPacket(WorldEventDispatcher eventDispatcher) { - this.eventDispatcher = eventDispatcher; + public CharacterValidatePositionPacket(CharacterService charService) { + this.charService = charService; } @Override @@ -58,8 +57,6 @@ public class CharacterValidatePositionPacket extends AbstractClientPacket { @Override public void process(final Lineage2Connection conn) { - conn.getCharacter().setPoint(point); - eventDispatcher.dispatch(new CharacterMoveEvent(conn.getCharacter(), - point)); + charService.receivedValidation(conn.getCharacter(), point); } } diff --git a/src/main/java/com/l2jserver/game/net/packet/client/ProtocolVersionPacket.java b/src/main/java/com/l2jserver/game/net/packet/client/ProtocolVersionPacket.java index ad41d1af5..7d9164686 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/ProtocolVersionPacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/ProtocolVersionPacket.java @@ -23,7 +23,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Inject; -import com.l2jserver.L2JConstants; +import com.l2jserver.L2JConstant; import com.l2jserver.game.ProtocolVersion; import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.Lineage2CryptographyKey; @@ -87,9 +87,9 @@ public class ProtocolVersionPacket extends AbstractClientPacket { log.debug("Client protocol version: {}", version); conn.setVersion(version); - if (L2JConstants.SUPPORTED_PROTOCOL != version) { + if (L2JConstant.SUPPORTED_PROTOCOL != version) { log.info("Incorrect protocol version: {0}. Only {1} is supported.", - version, L2JConstants.SUPPORTED_PROTOCOL); + version, L2JConstant.SUPPORTED_PROTOCOL); // notify wrong protocol and close connection conn.write(new KeyPacket(inKey, false)).addListener( new ChannelFutureListener() { diff --git a/src/main/java/com/l2jserver/game/net/packet/server/ActorMovementPacket.java b/src/main/java/com/l2jserver/game/net/packet/server/ActorMovementPacket.java index c9a51ee1f..794f4b340 100644 --- a/src/main/java/com/l2jserver/game/net/packet/server/ActorMovementPacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/server/ActorMovementPacket.java @@ -42,26 +42,28 @@ public class ActorMovementPacket extends AbstractServerPacket { */ private final Actor actor; /** - * The source coordinate + * The source target */ - private Coordinate source; + private Coordinate target; - public ActorMovementPacket(Actor actor, Coordinate source) { + public ActorMovementPacket(Actor actor, Coordinate target) { super(OPCODE); this.actor = actor; - this.source = source; + this.target = target; } @Override public void write(Lineage2Connection conn, ChannelBuffer buffer) { buffer.writeInt(actor.getID().getID()); + // target + buffer.writeInt(target.getX()); + buffer.writeInt(target.getY()); + buffer.writeInt(target.getZ()); + + // source buffer.writeInt(actor.getPoint().getX()); buffer.writeInt(actor.getPoint().getY()); buffer.writeInt(actor.getPoint().getZ()); - - buffer.writeInt(source.getX()); - buffer.writeInt(source.getY()); - buffer.writeInt(source.getZ()); } } diff --git a/src/main/java/com/l2jserver/game/net/packet/server/CharacterInformationPacket.java b/src/main/java/com/l2jserver/game/net/packet/server/CharacterInformationPacket.java index bca855341..d2da9d2ca 100644 --- a/src/main/java/com/l2jserver/game/net/packet/server/CharacterInformationPacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/server/CharacterInformationPacket.java @@ -281,7 +281,7 @@ public class CharacterInformationPacket extends AbstractServerPacket { buffer.writeInt(0x01); // special effects? circles around player... buffer.writeInt(200); // max cp buffer.writeInt(200); // cur cp - buffer.writeByte(127); // is mount or is airshilhelp = 0; otherwise + buffer.writeByte(0x00); // is mount or is airshilhelp = 0; otherwise // enchant effect (minimum 127) buffer.writeByte(0x00);// team, 1=blue,2 red,0 is unknown diff --git a/src/main/java/com/l2jserver/game/net/packet/server/CharacterInventoryPacket.java b/src/main/java/com/l2jserver/game/net/packet/server/CharacterInventoryPacket.java index 367e3b26f..3cb3fe7ad 100644 --- a/src/main/java/com/l2jserver/game/net/packet/server/CharacterInventoryPacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/server/CharacterInventoryPacket.java @@ -51,26 +51,29 @@ public class CharacterInventoryPacket extends AbstractServerPacket { @Override public void write(Lineage2Connection conn, ChannelBuffer buffer) { - buffer.writeByte((showWindow ? 0x01 : 0x00)); - buffer.writeInt(inventory.getItemCount()); // item count + buffer.writeShort((showWindow ? 0x01 : 0x00)); + // TODO warehouse items will have an issue here! + buffer.writeShort(inventory.getItemCount()); // item count + + // TODO implement real item slot + int slot = 0; for (Item item : inventory) { + if (item.getLocation() == InventoryLocation.WAREHOUSE + || item.getLocation() == null) { + continue; + } + buffer.writeInt(item.getID().getID()); // obj id buffer.writeInt(item.getTemplateID().getID()); // item id - if (item.getLocation() == InventoryLocation.PAPERDOLL) { - buffer.writeInt(item.getPaperdoll().id); // loc slot - } else { - buffer.writeInt(0x00); // loc slot - } + buffer.writeInt(slot); // loc slot buffer.writeLong(item.getCount()); // count buffer.writeShort(0x00); // item type2 buffer.writeShort(0x00); // item type3 - if (item.getLocation() == InventoryLocation.PAPERDOLL) { - buffer.writeShort(0x01); // equiped? - } else { - buffer.writeShort(0x00); // equiped? - } - buffer.writeInt(0x00); // body part - buffer.writeShort(0x00); // enchant level + buffer.writeShort((item.getLocation() == InventoryLocation.PAPERDOLL ? 0x01 + : 0x00)); // equiped? + buffer.writeInt((item.getPaperdoll() != null ? item.getPaperdoll().id + : 0)); // body part + buffer.writeShort(127); // enchant level // race tickets buffer.writeShort(0x00); // item type4 (custom type 2) buffer.writeInt(0x00); // augument @@ -85,6 +88,8 @@ public class CharacterInventoryPacket extends AbstractServerPacket { buffer.writeShort(0x00); buffer.writeShort(0x00); buffer.writeShort(0x00); + + slot++; } // TODO inventory block // buffer.writeShort(_inventory.getBlockItems().length); diff --git a/src/main/java/com/l2jserver/game/net/packet/server/NPCHtmlMessagePacket.java b/src/main/java/com/l2jserver/game/net/packet/server/NPCHtmlMessagePacket.java index e53fb2ccf..734a6f6eb 100644 --- a/src/main/java/com/l2jserver/game/net/packet/server/NPCHtmlMessagePacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/server/NPCHtmlMessagePacket.java @@ -23,6 +23,7 @@ import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.packet.AbstractServerPacket; import com.l2jserver.model.world.NPC; import com.l2jserver.util.BufferUtils; +import com.l2jserver.util.html.markup.HtmlTemplate; /** * This packet sends an HTML message to be displayed in the client. @@ -36,18 +37,24 @@ public class NPCHtmlMessagePacket extends AbstractServerPacket { public static final int OPCODE = 0x19; private final NPC npc; - private final Html html; + private final String html; public NPCHtmlMessagePacket(NPC npc, Html html) { super(OPCODE); this.npc = npc; - this.html = html; + this.html = html.toHtml(); + } + + public NPCHtmlMessagePacket(NPC npc, HtmlTemplate markup) { + super(OPCODE); + this.npc = npc; + this.html = markup.toHtmlString(); } @Override public void write(Lineage2Connection conn, ChannelBuffer buffer) { buffer.writeInt(npc.getID().getID()); - BufferUtils.writeString(buffer, html.toHtml()); + BufferUtils.writeString(buffer, html); buffer.writeInt(0x00); // item id } } diff --git a/src/main/java/com/l2jserver/model/id/object/provider/CharacterIDProvider.java b/src/main/java/com/l2jserver/model/id/object/provider/CharacterIDProvider.java index 267d37844..94458c873 100644 --- a/src/main/java/com/l2jserver/model/id/object/provider/CharacterIDProvider.java +++ b/src/main/java/com/l2jserver/model/id/object/provider/CharacterIDProvider.java @@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted; import com.l2jserver.model.id.object.CharacterID; import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.provider.IDProvider; -import com.l2jserver.service.game.world.id.WorldIDService; +import com.l2jserver.service.game.world.WorldIDService; /** * {@link IDProvider} for {@link CharacterID}. diff --git a/src/main/java/com/l2jserver/model/id/object/provider/ClanIDProvider.java b/src/main/java/com/l2jserver/model/id/object/provider/ClanIDProvider.java index a5a525649..a20eada1f 100644 --- a/src/main/java/com/l2jserver/model/id/object/provider/ClanIDProvider.java +++ b/src/main/java/com/l2jserver/model/id/object/provider/ClanIDProvider.java @@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted; import com.l2jserver.model.id.object.ClanID; import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.provider.IDProvider; -import com.l2jserver.service.game.world.id.WorldIDService; +import com.l2jserver.service.game.world.WorldIDService; /** * {@link IDProvider} for {@link ClanID}. diff --git a/src/main/java/com/l2jserver/model/id/object/provider/ItemIDProvider.java b/src/main/java/com/l2jserver/model/id/object/provider/ItemIDProvider.java index ff68659e0..52d09114f 100644 --- a/src/main/java/com/l2jserver/model/id/object/provider/ItemIDProvider.java +++ b/src/main/java/com/l2jserver/model/id/object/provider/ItemIDProvider.java @@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted; import com.l2jserver.model.id.object.ItemID; import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.provider.IDProvider; -import com.l2jserver.service.game.world.id.WorldIDService; +import com.l2jserver.service.game.world.WorldIDService; /** * {@link IDProvider} for {@link ItemID}. diff --git a/src/main/java/com/l2jserver/model/id/object/provider/NPCIDProvider.java b/src/main/java/com/l2jserver/model/id/object/provider/NPCIDProvider.java index f4459b031..64eb9c6fd 100644 --- a/src/main/java/com/l2jserver/model/id/object/provider/NPCIDProvider.java +++ b/src/main/java/com/l2jserver/model/id/object/provider/NPCIDProvider.java @@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted; import com.l2jserver.model.id.object.NPCID; import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.provider.IDProvider; -import com.l2jserver.service.game.world.id.WorldIDService; +import com.l2jserver.service.game.world.WorldIDService; /** * {@link IDProvider} for {@link NPCID}. diff --git a/src/main/java/com/l2jserver/model/id/object/provider/ObjectIDResolver.java b/src/main/java/com/l2jserver/model/id/object/provider/ObjectIDResolver.java index cc8fbad66..0bdc85cbb 100644 --- a/src/main/java/com/l2jserver/model/id/object/provider/ObjectIDResolver.java +++ b/src/main/java/com/l2jserver/model/id/object/provider/ObjectIDResolver.java @@ -18,7 +18,7 @@ package com.l2jserver.model.id.object.provider; import com.google.inject.Inject; import com.l2jserver.model.id.ObjectID; -import com.l2jserver.service.game.world.id.WorldIDService; +import com.l2jserver.service.game.world.WorldIDService; /** *

THIS PROVIDER IS READ ONLY!

diff --git a/src/main/java/com/l2jserver/model/id/object/provider/PetIDProvider.java b/src/main/java/com/l2jserver/model/id/object/provider/PetIDProvider.java index 48eefd14f..0407bf0ce 100644 --- a/src/main/java/com/l2jserver/model/id/object/provider/PetIDProvider.java +++ b/src/main/java/com/l2jserver/model/id/object/provider/PetIDProvider.java @@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted; import com.l2jserver.model.id.object.PetID; import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.provider.IDProvider; -import com.l2jserver.service.game.world.id.WorldIDService; +import com.l2jserver.service.game.world.WorldIDService; /** * {@link IDProvider} for {@link PetID}. diff --git a/src/main/java/com/l2jserver/model/template/NPCTemplate.java b/src/main/java/com/l2jserver/model/template/NPCTemplate.java index f2db60f7a..4f7ae526c 100644 --- a/src/main/java/com/l2jserver/model/template/NPCTemplate.java +++ b/src/main/java/com/l2jserver/model/template/NPCTemplate.java @@ -30,8 +30,7 @@ import com.l2jserver.model.world.capability.Actor; import com.l2jserver.service.game.CharacterService; import com.l2jserver.service.network.NetworkService; import com.l2jserver.util.calculator.Calculator; -import com.l2jserver.util.html.markup.Markup; -import com.l2jserver.util.html.markup.Markup.Builder; +import com.l2jserver.util.html.markup.HtmlTemplate; import com.l2jserver.util.html.markup.MarkupTag; /** @@ -110,16 +109,18 @@ public abstract class NPCTemplate extends ActorTemplate { // target this npc charService.target(character, npc); - + // generate not implemented message - final Markup markup = new Markup(name + " - Notice", new Builder() { + final HtmlTemplate template = new HtmlTemplate(name) { @Override public void build(MarkupTag body) { - body.text("This NPC is not yet implemented!"); + body.text("The NPC ${name} is not yet implemented!", "ff0000") + .p(); body.addLink("Click me!", "test"); } - }); - conn.write(new NPCHtmlMessagePacket(npc, markup.build())); + }; + template.register("name", name); + conn.write(new NPCHtmlMessagePacket(npc, template)); } /** diff --git a/src/main/java/com/l2jserver/model/world/character/CharacterInventory.java b/src/main/java/com/l2jserver/model/world/character/CharacterInventory.java index 11fae622e..e34b4805b 100644 --- a/src/main/java/com/l2jserver/model/world/character/CharacterInventory.java +++ b/src/main/java/com/l2jserver/model/world/character/CharacterInventory.java @@ -73,7 +73,8 @@ public class CharacterInventory implements Iterable { * the items to be added */ public void load(List items) { - items.addAll(items); + this.items.clear(); + this.items.addAll(items); } /** diff --git a/src/main/java/com/l2jserver/service/ServiceModule.java b/src/main/java/com/l2jserver/service/ServiceModule.java index 851a76417..541fc027f 100644 --- a/src/main/java/com/l2jserver/service/ServiceModule.java +++ b/src/main/java/com/l2jserver/service/ServiceModule.java @@ -31,16 +31,18 @@ import com.l2jserver.service.game.SpawnService; import com.l2jserver.service.game.SpawnServiceImpl; import com.l2jserver.service.game.chat.ChatService; import com.l2jserver.service.game.chat.SimpleChatService; +import com.l2jserver.service.game.pathing.MapperPathingService; +import com.l2jserver.service.game.pathing.PathingService; import com.l2jserver.service.game.scripting.ScriptingService; import com.l2jserver.service.game.scripting.ScriptingServiceImpl; import com.l2jserver.service.game.template.ScriptTemplateService; import com.l2jserver.service.game.template.TemplateService; +import com.l2jserver.service.game.world.CachedWorldIDService; +import com.l2jserver.service.game.world.WorldIDService; import com.l2jserver.service.game.world.WorldService; import com.l2jserver.service.game.world.WorldServiceImpl; import com.l2jserver.service.game.world.event.WorldEventDispatcher; import com.l2jserver.service.game.world.event.WorldEventDispatcherImpl; -import com.l2jserver.service.game.world.id.CachedWorldIDService; -import com.l2jserver.service.game.world.id.WorldIDService; import com.l2jserver.service.logging.Log4JLoggingService; import com.l2jserver.service.logging.LoggingService; import com.l2jserver.service.network.NettyNetworkService; @@ -67,6 +69,9 @@ public class ServiceModule extends AbstractModule { bind(WorldIDService.class).to(CachedWorldIDService.class).in( Scopes.SINGLETON); + bind(PathingService.class).to(MapperPathingService.class).in( + Scopes.SINGLETON); + bind(BlowfishKeygenService.class).to(SecureBlowfishKeygenService.class) .in(Scopes.SINGLETON); bind(NetworkService.class).to(NettyNetworkService.class).in( diff --git a/src/main/java/com/l2jserver/service/cache/EhCacheService.java b/src/main/java/com/l2jserver/service/cache/EhCacheService.java index 73dabf7fc..d28e77044 100644 --- a/src/main/java/com/l2jserver/service/cache/EhCacheService.java +++ b/src/main/java/com/l2jserver/service/cache/EhCacheService.java @@ -25,6 +25,8 @@ import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import net.sf.ehcache.config.CacheConfiguration; +import net.sf.ehcache.config.Configuration; +import net.sf.ehcache.config.DiskStoreConfiguration; import net.sf.ehcache.store.MemoryStoreEvictionPolicy; import com.l2jserver.service.AbstractService; @@ -48,7 +50,8 @@ public class EhCacheService extends AbstractService implements CacheService { @Override protected void doStart() throws ServiceStartException { - manager = new CacheManager(); + manager = new CacheManager(new Configuration().updateCheck(false) + .diskStore(new DiskStoreConfiguration().path("data/cache"))); interfaceCache = createCache("interface-cache"); } diff --git a/src/main/java/com/l2jserver/service/database/MySQLDatabaseService.java b/src/main/java/com/l2jserver/service/database/MySQLDatabaseService.java index 519eba010..c07322632 100644 --- a/src/main/java/com/l2jserver/service/database/MySQLDatabaseService.java +++ b/src/main/java/com/l2jserver/service/database/MySQLDatabaseService.java @@ -122,8 +122,7 @@ public class MySQLDatabaseService extends AbstractService implements objectCache = new Cache(new CacheConfiguration("database-service", IDAllocator.ALLOCABLE_IDS) .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU) - .overflowToDisk(true).eternal(false).timeToLiveSeconds(60) - .timeToIdleSeconds(30).diskPersistent(false) + .overflowToDisk(true).eternal(true).diskPersistent(false) .diskExpiryThreadIntervalSeconds(0)); cacheService.register(objectCache); } diff --git a/src/main/java/com/l2jserver/service/game/CharacterService.java b/src/main/java/com/l2jserver/service/game/CharacterService.java index b69805ef7..23c2e49fd 100644 --- a/src/main/java/com/l2jserver/service/game/CharacterService.java +++ b/src/main/java/com/l2jserver/service/game/CharacterService.java @@ -20,6 +20,7 @@ import com.l2jserver.model.world.L2Character; import com.l2jserver.model.world.capability.Actor; import com.l2jserver.service.Service; import com.l2jserver.util.dimensional.Coordinate; +import com.l2jserver.util.dimensional.Point; /** * This service manages {@link L2Character} instances @@ -73,6 +74,26 @@ public interface CharacterService extends Service { */ void move(L2Character character, Coordinate coordinate); + /** + * Validates the position of an character + * + * @param character + * the character + * @param point + * the validated point + */ + void validate(L2Character character, Point point); + + /** + * Called when received the validation of the position of an character + * + * @param character + * the character + * @param point + * the validated point + */ + void receivedValidation(L2Character character, Point point); + /** * Set the character to walking mode * diff --git a/src/main/java/com/l2jserver/service/game/CharacterServiceImpl.java b/src/main/java/com/l2jserver/service/game/CharacterServiceImpl.java index 9a0be4fe6..d17f3c699 100644 --- a/src/main/java/com/l2jserver/service/game/CharacterServiceImpl.java +++ b/src/main/java/com/l2jserver/service/game/CharacterServiceImpl.java @@ -17,6 +17,7 @@ package com.l2jserver.service.game; import com.google.inject.Inject; +import com.l2jserver.db.dao.ItemDAO; import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.SystemMessage; import com.l2jserver.game.net.packet.server.ActionFailedPacket; @@ -45,7 +46,6 @@ import com.l2jserver.model.world.character.event.CharacterTargetSelectedEvent; import com.l2jserver.model.world.npc.event.NPCSpawnEvent; import com.l2jserver.service.AbstractService; import com.l2jserver.service.AbstractService.Depends; -import com.l2jserver.service.game.ai.AIService; import com.l2jserver.service.game.chat.ChatMessageDestination; import com.l2jserver.service.game.chat.ChatService; import com.l2jserver.service.game.chat.channel.ChatChannel; @@ -58,6 +58,7 @@ import com.l2jserver.service.game.world.event.WorldListener; import com.l2jserver.service.game.world.filter.impl.KnownListFilter; import com.l2jserver.service.network.NetworkService; import com.l2jserver.util.dimensional.Coordinate; +import com.l2jserver.util.dimensional.Point; /** * Default implementation for {@link CharacterService}. @@ -65,7 +66,7 @@ import com.l2jserver.util.dimensional.Coordinate; * @author Rogiel */ @Depends({ WorldService.class, ChatService.class, NetworkService.class, - SpawnService.class, AIService.class }) + SpawnService.class }) public class CharacterServiceImpl extends AbstractService implements CharacterService { /** @@ -88,6 +89,10 @@ public class CharacterServiceImpl extends AbstractService implements * The {@link SpawnService} */ private final SpawnService spawnService; + /** + * The {@link ItemDAO} + */ + private final ItemDAO itemDao; // /** // * The {@link AIService} @@ -97,12 +102,14 @@ public class CharacterServiceImpl extends AbstractService implements @Inject public CharacterServiceImpl(WorldService worldService, WorldEventDispatcher eventDispatcher, ChatService chatService, - NetworkService networkService, SpawnService spawnService) { + NetworkService networkService, SpawnService spawnService, + ItemDAO itemDao) { this.worldService = worldService; this.eventDispatcher = eventDispatcher; this.chatService = chatService; this.networkService = networkService; this.spawnService = spawnService; + this.itemDao = itemDao; } @Override @@ -114,6 +121,8 @@ public class CharacterServiceImpl extends AbstractService implements if (!worldService.add(character)) // character is already in the world! return; + + itemDao.loadInventory(character); // chat listener final ChatChannelListener globalChatListener = new ChatChannelListener() { @@ -221,10 +230,11 @@ public class CharacterServiceImpl extends AbstractService implements // aiService.walk(character, coordinate); final Coordinate source = character.getPosition(); - character.setPosition(coordinate); - conn.write(new ActorMovementPacket(character, source)); + // we don't set the character coordinate yet, this will be done by + // validate coordinate + conn.write(new ActorMovementPacket(character, coordinate)); // we don't dispatch events here, they will be dispatched by - // CharacterValidatePositionPacket packets at fixed time intervals. + // receivedValidation at fixed time intervals. } @Override @@ -273,6 +283,17 @@ public class CharacterServiceImpl extends AbstractService implements } } + @Override + public void validate(L2Character character, Point point) { + // TODO implement position validation + } + + @Override + public void receivedValidation(L2Character character, Point point) { + character.setPoint(point); + eventDispatcher.dispatch(new CharacterMoveEvent(character, point)); + } + @Override public void walk(L2Character character) { final CharacterID id = character.getID(); diff --git a/src/main/java/com/l2jserver/service/game/pathing/MapperPathingService.java b/src/main/java/com/l2jserver/service/game/pathing/MapperPathingService.java new file mode 100644 index 000000000..803413620 --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/pathing/MapperPathingService.java @@ -0,0 +1,144 @@ +/* + * 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.pathing; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; + +import javolution.io.Struct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.inject.Inject; +import com.l2jserver.model.world.character.event.CharacterMoveEvent; +import com.l2jserver.service.AbstractService; +import com.l2jserver.service.AbstractService.Depends; +import com.l2jserver.service.ServiceStartException; +import com.l2jserver.service.ServiceStopException; +import com.l2jserver.service.game.CharacterService; +import com.l2jserver.service.game.world.WorldService; +import com.l2jserver.service.game.world.event.TypedWorldListener; +import com.l2jserver.service.game.world.event.WorldEventDispatcher; +import com.l2jserver.util.dimensional.Coordinate; +import com.l2jserver.util.dimensional.Point; + +/** + *

This implementation does not validate pathing!

+ *

+ * This service does not handle pathing yet, instead in monitors client packets + * that send a location validation. With those packets, a database will be + * generated will all valid points in terrain. Later on, an system that allows + * uploading this data will be implemented and allowing the pathing data to be + * shared across all servers. + * + * @author Rogiel + */ +@Depends({ CharacterService.class, WorldService.class }) +public class MapperPathingService extends AbstractService implements + PathingService { + /** + * The database file for the pathing engine + */ + private static final File file = new File("data/pathing.db"); + + /** + * The logger + */ + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + /** + * The {@link WorldService} event dispatcher + */ + private final WorldEventDispatcher eventDispatcher; + + /** + * The database channel, will reamain open until service is stopped. + */ + private FileChannel channel; + + /** + * Creates a new instance + * + * @param eventDispatcher + * the world event dispatcher + */ + @Inject + public MapperPathingService(WorldEventDispatcher eventDispatcher) { + this.eventDispatcher = eventDispatcher; + } + + @Override + protected void doStart() throws ServiceStartException { + try { + this.channel = new FileOutputStream(file).getChannel(); + } catch (FileNotFoundException e) { + throw new ServiceStartException( + "Could not open pathing database file", e); + } + eventDispatcher.addListener(new TypedWorldListener( + CharacterMoveEvent.class) { + @Override + protected boolean dispatch(CharacterMoveEvent e) { + final Point point = e.getPoint(); + final CoordinateStruct struct = CoordinateStruct + .fromCoordinate(point.getCoordinate()); + try { + channel.write(struct.getByteBuffer()); + } catch (IOException e1) { + log.warn("Error writing pathing file!", e1); + } + return true; + } + }); + } + + @Override + protected void doStop() throws ServiceStopException { + try { + this.channel.close(); + } catch (IOException e) { + throw new ServiceStopException( + "Could not close the pathing database file", e); + } finally { + this.channel = null; + } + } + + /** + * This is an Javolution {@link Struct} that represents a set of coordinate + * stored in the database file + * + * @author Rogiel + */ + public static class CoordinateStruct extends Struct { + public final Signed32 x = new Signed32(); + public final Signed32 y = new Signed32(); + public final Signed32 z = new Signed32(); + + public static CoordinateStruct fromCoordinate(Coordinate coordinate) { + final CoordinateStruct struct = new CoordinateStruct(); + struct.x.set(coordinate.getX()); + struct.y.set(coordinate.getY()); + struct.z.set(coordinate.getZ()); + return struct; + } + } +} diff --git a/src/main/java/com/l2jserver/service/game/pathing/PathingService.java b/src/main/java/com/l2jserver/service/game/pathing/PathingService.java new file mode 100644 index 000000000..7717290f0 --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/pathing/PathingService.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.service.game.pathing; + +import com.l2jserver.service.Service; + +/** + * This service handles the pathing. + * + * @author Rogiel + */ +public interface PathingService extends Service { + +} diff --git a/src/main/java/com/l2jserver/service/game/world/id/CachedWorldIDService.java b/src/main/java/com/l2jserver/service/game/world/CachedWorldIDService.java similarity index 87% rename from src/main/java/com/l2jserver/service/game/world/id/CachedWorldIDService.java rename to src/main/java/com/l2jserver/service/game/world/CachedWorldIDService.java index cece93543..3efab71d3 100644 --- a/src/main/java/com/l2jserver/service/game/world/id/CachedWorldIDService.java +++ b/src/main/java/com/l2jserver/service/game/world/CachedWorldIDService.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver. If not, see . */ -package com.l2jserver.service.game.world.id; +package com.l2jserver.service.game.world; import java.util.Collection; @@ -25,6 +25,7 @@ import net.sf.ehcache.store.MemoryStoreEvictionPolicy; import com.google.inject.Inject; import com.l2jserver.db.dao.CharacterDAO; +import com.l2jserver.db.dao.ItemDAO; import com.l2jserver.model.id.ID; import com.l2jserver.model.id.ObjectID; import com.l2jserver.model.id.object.allocator.IDAllocator; @@ -58,18 +59,28 @@ public class CachedWorldIDService extends AbstractService implements * The {@link CharacterDAO} */ private final CharacterDAO characterDao; + /** + * The {@link ItemDAO} + */ + private final ItemDAO itemDao; /** * The ID cache */ private Cache cache; + /** + * The loaded state + */ + private boolean loaded = false; + @Inject public CachedWorldIDService(CacheService cacheService, - IDAllocator allocator, CharacterDAO characterDao) { + IDAllocator allocator, CharacterDAO characterDao, ItemDAO itemDao) { this.cacheService = cacheService; this.allocator = allocator; this.characterDao = characterDao; + this.itemDao = itemDao; } @Override @@ -82,9 +93,13 @@ public class CachedWorldIDService extends AbstractService implements .timeToIdleSeconds(30).diskPersistent(false) .diskExpiryThreadIntervalSeconds(0)); cacheService.register(cache); + } - // load all ids + @Override + public void load() { load(characterDao.listIDs()); + load(itemDao.listIDs()); + loaded = true; } /** @@ -103,6 +118,11 @@ public class CachedWorldIDService extends AbstractService implements @Override @SuppressWarnings("unchecked") public > I resolve(int id) { + if (!loaded) { + // ignore resolving before all IDs are loaded + return null; + } + final Element element = cache.get(id); if (element == null) return null; @@ -111,9 +131,8 @@ public class CachedWorldIDService extends AbstractService implements @Override public > void add(I id) { - if(id == null) + if (id == null) return; - System.out.println("Registering ID: "+id); cache.put(new Element(id.getID(), id)); } diff --git a/src/main/java/com/l2jserver/service/game/world/id/WorldIDService.java b/src/main/java/com/l2jserver/service/game/world/WorldIDService.java similarity index 80% rename from src/main/java/com/l2jserver/service/game/world/id/WorldIDService.java rename to src/main/java/com/l2jserver/service/game/world/WorldIDService.java index ea75116c6..623586670 100644 --- a/src/main/java/com/l2jserver/service/game/world/id/WorldIDService.java +++ b/src/main/java/com/l2jserver/service/game/world/WorldIDService.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver. If not, see . */ -package com.l2jserver.service.game.world.id; +package com.l2jserver.service.game.world; import com.l2jserver.model.id.ObjectID; import com.l2jserver.model.id.object.allocator.IDAllocator; @@ -30,6 +30,11 @@ import com.l2jserver.service.database.DatabaseService; * @author Rogiel */ public interface WorldIDService extends Service { + /** + * Load all {@link ObjectID} from the database + */ + void load(); + /** * Tries to resolve an ID based on its raw value * @@ -43,7 +48,23 @@ public interface WorldIDService extends Service { */ > I resolve(int id); + /** + * Adds a new ID to be managed by this service + * + * @param + * the ID type + * @param id + * the id + */ > void add(I id); + /** + * Decouples an ID from this service + * + * @param + * the ID type + * @param id + * the id + */ > void remove(I id); } diff --git a/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java b/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java index e72275a9d..22937d334 100644 --- a/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java +++ b/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java @@ -50,7 +50,7 @@ import com.l2jserver.util.factory.CollectionFactory; * @author Rogiel */ @Depends({ LoggingService.class, TemplateService.class, ScriptingService.class, - DatabaseService.class }) + DatabaseService.class, WorldIDService.class }) public class WorldServiceImpl extends AbstractService implements WorldService { /** * The logger @@ -66,15 +66,22 @@ public class WorldServiceImpl extends AbstractService implements WorldService { * The world event dispatcher */ private final WorldEventDispatcherImpl dispatcher; + /** + * The {@link WorldIDService} + */ + private final WorldIDService idService; @Inject - public WorldServiceImpl(WorldEventDispatcher dispatcher) { + public WorldServiceImpl(WorldEventDispatcher dispatcher, + WorldIDService idService) { this.dispatcher = (WorldEventDispatcherImpl) dispatcher; + this.idService = idService; } @Override protected void doStart() throws ServiceStartException { objects.clear(); + idService.load(); } @Override diff --git a/src/main/java/com/l2jserver/util/html/L2BodyTag.java b/src/main/java/com/l2jserver/util/html/L2BodyTag.java index 4e2474746..1956fa5bd 100644 --- a/src/main/java/com/l2jserver/util/html/L2BodyTag.java +++ b/src/main/java/com/l2jserver/util/html/L2BodyTag.java @@ -22,8 +22,9 @@ import org.htmlparser.tags.BodyTag; import org.htmlparser.util.NodeList; /** - * @author Rogiel + * Lineage 2 {@link Tag}: body * + * @author Rogiel */ public class L2BodyTag extends BodyTag { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/l2jserver/util/html/L2BrTag.java b/src/main/java/com/l2jserver/util/html/L2BrTag.java index dbf0c513f..fa0514743 100644 --- a/src/main/java/com/l2jserver/util/html/L2BrTag.java +++ b/src/main/java/com/l2jserver/util/html/L2BrTag.java @@ -17,21 +17,17 @@ package com.l2jserver.util.html; import org.htmlparser.Tag; -import org.htmlparser.nodes.TagNode; import org.htmlparser.tags.Span; /** - * @author Rogiel + * Lineage 2 {@link Tag}: br * + * @author Rogiel */ public class L2BrTag extends Span { private static final long serialVersionUID = 1L; public L2BrTag() { super.setTagName("br"); - Tag end = new TagNode(); - end.setTagName("/br"); - super.setEndTag(end); - super.setEmptyXmlTag(true); } } diff --git a/src/main/java/com/l2jserver/util/html/L2CenterTag.java b/src/main/java/com/l2jserver/util/html/L2CenterTag.java index ad56a0c1f..84d129241 100644 --- a/src/main/java/com/l2jserver/util/html/L2CenterTag.java +++ b/src/main/java/com/l2jserver/util/html/L2CenterTag.java @@ -21,8 +21,9 @@ import org.htmlparser.nodes.TagNode; import org.htmlparser.tags.Span; /** - * @author Rogiel + * Lineage 2 {@link Tag}: center * + * @author Rogiel */ public class L2CenterTag extends Span { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/l2jserver/util/html/L2DivTag.java b/src/main/java/com/l2jserver/util/html/L2DivTag.java index 47081052f..d7d25987f 100644 --- a/src/main/java/com/l2jserver/util/html/L2DivTag.java +++ b/src/main/java/com/l2jserver/util/html/L2DivTag.java @@ -22,8 +22,9 @@ import org.htmlparser.tags.Div; import org.htmlparser.util.NodeList; /** - * @author Rogiel + * Lineage 2 {@link Tag}: div * + * @author Rogiel */ public class L2DivTag extends Div { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/l2jserver/util/html/L2FontTag.java b/src/main/java/com/l2jserver/util/html/L2FontTag.java index 1bb3870e9..de8789aff 100644 --- a/src/main/java/com/l2jserver/util/html/L2FontTag.java +++ b/src/main/java/com/l2jserver/util/html/L2FontTag.java @@ -22,8 +22,9 @@ import org.htmlparser.tags.Span; import org.htmlparser.util.NodeList; /** - * @author Rogiel + * Lineage 2 {@link Tag}: font * + * @author Rogiel */ public class L2FontTag extends Span { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/l2jserver/util/html/L2HeadTag.java b/src/main/java/com/l2jserver/util/html/L2HeadTag.java index 6f34be311..e5a24bddf 100644 --- a/src/main/java/com/l2jserver/util/html/L2HeadTag.java +++ b/src/main/java/com/l2jserver/util/html/L2HeadTag.java @@ -22,6 +22,8 @@ import org.htmlparser.tags.HeadTag; import org.htmlparser.util.NodeList; /** + * Lineage 2 {@link Tag}: head + * * @author Rogiel */ public class L2HeadTag extends HeadTag { diff --git a/src/main/java/com/l2jserver/util/html/L2HtmlTag.java b/src/main/java/com/l2jserver/util/html/L2HtmlTag.java index 5e41c1412..9704abc57 100644 --- a/src/main/java/com/l2jserver/util/html/L2HtmlTag.java +++ b/src/main/java/com/l2jserver/util/html/L2HtmlTag.java @@ -22,8 +22,9 @@ import org.htmlparser.tags.Html; import org.htmlparser.util.NodeList; /** - * @author Rogiel + * Lineage 2 {@link Tag}: html * + * @author Rogiel */ public class L2HtmlTag extends Html { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/l2jserver/util/html/L2ImageTag.java b/src/main/java/com/l2jserver/util/html/L2ImageTag.java index 662ff986e..1764c37b2 100644 --- a/src/main/java/com/l2jserver/util/html/L2ImageTag.java +++ b/src/main/java/com/l2jserver/util/html/L2ImageTag.java @@ -21,6 +21,8 @@ import org.htmlparser.nodes.TagNode; import org.htmlparser.tags.ImageTag; /** + * Lineage 2 {@link Tag}: img + * * @author Rogiel */ public class L2ImageTag extends ImageTag { @@ -31,6 +33,5 @@ public class L2ImageTag extends ImageTag { Tag end = new TagNode(); end.setTagName("/img"); super.setEndTag(end); - super.setEmptyXmlTag(true); } } diff --git a/src/main/java/com/l2jserver/util/html/L2LinkTag.java b/src/main/java/com/l2jserver/util/html/L2LinkTag.java index 8734a90f5..f243166a6 100644 --- a/src/main/java/com/l2jserver/util/html/L2LinkTag.java +++ b/src/main/java/com/l2jserver/util/html/L2LinkTag.java @@ -22,6 +22,8 @@ import org.htmlparser.tags.LinkTag; import org.htmlparser.util.NodeList; /** + * Lineage 2 {@link Tag}: a + * * @author Rogiel */ public class L2LinkTag extends LinkTag { @@ -33,6 +35,5 @@ public class L2LinkTag extends LinkTag { end.setTagName("/a"); super.setEndTag(end); super.setChildren(new NodeList()); - super.setEmptyXmlTag(true); } } diff --git a/src/main/java/com/l2jserver/util/html/L2NewLineTag.java b/src/main/java/com/l2jserver/util/html/L2NewLineTag.java index c313b1de6..d008323bd 100644 --- a/src/main/java/com/l2jserver/util/html/L2NewLineTag.java +++ b/src/main/java/com/l2jserver/util/html/L2NewLineTag.java @@ -17,21 +17,17 @@ package com.l2jserver.util.html; import org.htmlparser.Tag; -import org.htmlparser.nodes.TagNode; import org.htmlparser.tags.Span; /** - * @author Rogiel + * Lineage 2 {@link Tag}: p * + * @author Rogiel */ public class L2NewLineTag extends Span { private static final long serialVersionUID = 1L; public L2NewLineTag() { super.setTagName("p"); - Tag end = new TagNode(); - end.setTagName("/pp"); - super.setEndTag(end); - super.setEmptyXmlTag(true); } } diff --git a/src/main/java/com/l2jserver/util/html/L2TitleTag.java b/src/main/java/com/l2jserver/util/html/L2TitleTag.java index 68dc35445..6b34189e2 100644 --- a/src/main/java/com/l2jserver/util/html/L2TitleTag.java +++ b/src/main/java/com/l2jserver/util/html/L2TitleTag.java @@ -22,6 +22,8 @@ import org.htmlparser.tags.TitleTag; import org.htmlparser.util.NodeList; /** + * Lineage 2 {@link Tag}: title + * * @author Rogiel */ public class L2TitleTag extends TitleTag { diff --git a/src/main/java/com/l2jserver/util/html/markup/HtmlTemplate.java b/src/main/java/com/l2jserver/util/html/markup/HtmlTemplate.java new file mode 100644 index 000000000..78270872c --- /dev/null +++ b/src/main/java/com/l2jserver/util/html/markup/HtmlTemplate.java @@ -0,0 +1,151 @@ +/* + * 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.util.html.markup; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Pattern; + +import org.htmlparser.Tag; +import org.htmlparser.nodes.TextNode; +import org.htmlparser.tags.HeadTag; +import org.htmlparser.tags.Html; +import org.htmlparser.tags.TitleTag; + +import com.l2jserver.util.factory.CollectionFactory; +import com.l2jserver.util.html.L2BodyTag; +import com.l2jserver.util.html.L2HeadTag; +import com.l2jserver.util.html.L2HtmlTag; +import com.l2jserver.util.html.L2TitleTag; + +/** + * This an helper class used to build HTML documents. You should implement + * {@link HtmlTemplate} as an anonymous class: + * + *

+ * final HtmlTemplate template = new HtmlTemplate("Template implementation sample") {
+ * 	@Override
+ * 	public void build(MarkupTag body) {
+ * 		body.text("Hello world!").br().text("New line!");
+ * 	}
+ * };
+ * final String html = template.toHtmlString();
+ * 
+ * + * Using the {@link Html} object (from {@link #build()}) you can obtain the HTML + * code using {@link Html#toHtml()}. + *

+ * The generated code will be the smaller possible because the client has packet + * size limitations, it will not contain any formatting. + * + * @author Rogiel + */ +public abstract class HtmlTemplate { + /** + * The template title (will be displayed in the game window) + */ + private final String title; + /** + * The template variables + */ + private Map variables = CollectionFactory.newMap(); + + /** + * Creates a new instance + * + * @param title + * the title + */ + public HtmlTemplate(String title) { + this.title = title; + } + + /** + * Creates a new instance without a title + */ + public HtmlTemplate() { + this(null); + } + + /** + * Build the HTML structure + * + * @param body + * the body HTML node + */ + protected abstract void build(MarkupTag body); + + /** + * Replace the variables in the template + * + * @param template + * the generated template HTML + * @return the HTML with variables replaced + */ + public String replace(String template) { + for (final Entry variable : variables.entrySet()) { + template = template.replaceAll( + Pattern.quote("${" + variable.getKey() + "}"), + variable.getValue()); + } + return template; + } + + /** + * Register an variable for this template + * + * @param name + * the name + * @param value + * the value + */ + public void register(String name, String value) { + variables.put(name, value); + } + + /** + * Creates a new {@link Html} object using the {@link HtmlTemplate} provided + * in the constructor. This method can be invoked multiple times. + * + * @return the {@link Html} object + */ + public Html build() { + final Html html = new L2HtmlTag(); + if (title != null) { + final HeadTag head = new L2HeadTag(); + final TitleTag title = new L2TitleTag(); + html.getChildren().add(head); + head.getChildren().add(title); + title.getChildren().add(new TextNode(this.title)); + } + final Tag body = new L2BodyTag(); + html.getChildren().add(body); + + this.build(new MarkupTag(body)); + return html; + } + + /** + * Generates the HTML code for this template. It also replaces the + * variables. + * + * @return the HTML code + */ + public String toHtmlString() { + return this.replace(build().toHtml()); + } +} \ No newline at end of file diff --git a/src/main/java/com/l2jserver/util/html/markup/Markup.java b/src/main/java/com/l2jserver/util/html/markup/Markup.java deleted file mode 100644 index bf2712511..000000000 --- a/src/main/java/com/l2jserver/util/html/markup/Markup.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.util.html.markup; - -import org.htmlparser.nodes.TextNode; -import org.htmlparser.tags.HeadTag; -import org.htmlparser.tags.Html; -import org.htmlparser.tags.TitleTag; - -import com.l2jserver.util.html.L2HeadTag; -import com.l2jserver.util.html.L2HtmlTag; -import com.l2jserver.util.html.L2TitleTag; - -/** - * @author Rogiel - * - */ -public class Markup { - private final Builder builder; - private final String title; - - public Markup(String title, Builder builder) { - this.builder = builder; - this.title = title; - } - - public Html build() { - final Html html = new L2HtmlTag(); - final HeadTag head = new L2HeadTag(); - final TitleTag title = new L2TitleTag(); - - head.getChildren().add(head); - head.getChildren().add(title); - title.getChildren().add(new TextNode(this.title)); - - this.builder.build(new MarkupTag(html)); - return html; - } - - public interface Builder { - void build(MarkupTag body); - } -} diff --git a/src/main/java/com/l2jserver/util/html/markup/MarkupTag.java b/src/main/java/com/l2jserver/util/html/markup/MarkupTag.java index 47b1e85ae..2b4013196 100644 --- a/src/main/java/com/l2jserver/util/html/markup/MarkupTag.java +++ b/src/main/java/com/l2jserver/util/html/markup/MarkupTag.java @@ -28,32 +28,78 @@ import com.l2jserver.util.html.L2LinkTag; import com.l2jserver.util.html.L2NewLineTag; /** - * @author Rogiel + * This is an helper class that helps creating new tags in the HTML document. * + * @author Rogiel */ public class MarkupTag { + /** + * The current tag + */ private final Tag tag; + /** + * The parent {@link MarkupTag} + */ private final MarkupTag parent; + /** + * Creates a new instance with a parent + * + * @param tag + * the tag + * @param parent + * the parent + */ public MarkupTag(Tag tag, MarkupTag parent) { this.tag = tag; this.parent = parent; } + /** + * Creates a new instance without a parent + * + * @param tag + * the tag + */ public MarkupTag(Tag tag) { this(tag, null); } + /** + * Adds an attribute to the current tag + * + * @param name + * the attribute name + * @param value + * the attribute value + * @return this {@link MarkupTag} + */ public MarkupTag attr(String name, String value) { tag.setAttribute(name, value); return this; } + /** + * Adds a plain text to the tag. It will not use any formatting. + * + * @param text + * the text + * @return this {@link MarkupTag} + */ public MarkupTag text(String text) { tag.getChildren().add(new TextNode(text)); return this; } + /** + * Adds a plain text to the tag, use the color formatting. + * + * @param text + * the text + * @param color + * the text color + * @return this {@link MarkupTag} + */ public MarkupTag text(String text, String color) { final Tag font = new L2FontTag(); font.setAttribute("color", color); @@ -62,30 +108,61 @@ public class MarkupTag { return this; } + /** + * Creates a new DIV element + * + * @return this div {@link MarkupTag} + */ public MarkupTag div() { final Tag tag = new L2DivTag(); this.tag.getChildren().add(tag); return new MarkupTag(tag, this); } + /** + * Inserts a line break + * + * @return this {@link MarkupTag} + */ public MarkupTag br() { final Tag tag = new L2BrTag(); this.tag.getChildren().add(tag); return this; } + /** + * Inserts a new paragraph + * + * @return this {@link MarkupTag} + */ public MarkupTag p() { final Tag tag = new L2NewLineTag(); this.tag.getChildren().add(tag); return this; } + /** + * Creates a new CENTER element. Text inside this element will be centered. + * + * @return this CENTER {@link MarkupTag} + */ public MarkupTag center() { final Tag tag = new L2CenterTag(); this.tag.getChildren().add(tag); return new MarkupTag(this.tag, this); } + /** + * Adds an image + * + * @param src + * the image source + * @param height + * the height + * @param width + * the width + * @return this {@link MarkupTag} + */ public MarkupTag addImage(String src, int height, int width) { final Tag tag = new L2ImageTag(); this.tag.getChildren().add(tag); @@ -95,6 +172,15 @@ public class MarkupTag { return this; } + /** + * Adds a link + * + * @param text + * the link text + * @param action + * the link action (will automatically append "bypass -h") + * @return + */ public MarkupTag addLink(String text, String action) { final Tag tag = new L2LinkTag(); this.tag.getChildren().add(tag); @@ -103,6 +189,11 @@ public class MarkupTag { return this; } + /** + * Close this tag and return the parent element + * + * @return the parent element, if any. + */ public MarkupTag close() { return parent; } diff --git a/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java b/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java index f27d40e74..aa3fec3ab 100644 --- a/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java +++ b/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java @@ -39,9 +39,9 @@ import com.l2jserver.model.world.player.event.PlayerListener; import com.l2jserver.model.world.player.event.PlayerSpawnEvent; import com.l2jserver.service.ServiceManager; import com.l2jserver.service.ServiceStartException; +import com.l2jserver.service.game.world.WorldIDService; import com.l2jserver.service.game.world.WorldService; import com.l2jserver.service.game.world.event.WorldEventDispatcher; -import com.l2jserver.service.game.world.id.WorldIDService; public class WorldEventDispatcherImplTest { private WorldService world; diff --git a/src/tool/java/com/l2jserver/tool/conversor/npctemplate/NPCTemplateBase.txt b/src/tool/java/com/l2jserver/tool/conversor/npctemplate/NPCTemplateBase.txt new file mode 100644 index 000000000..b28412a03 --- /dev/null +++ b/src/tool/java/com/l2jserver/tool/conversor/npctemplate/NPCTemplateBase.txt @@ -0,0 +1,62 @@ +/* + * 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 script.template.actor.character; + +import com.google.inject.Inject; +import com.l2jserver.model.id.template.CharacterTemplateID; +import com.l2jserver.model.id.template.factory.CharacterTemplateIDFactory; +import com.l2jserver.model.world.L2Character; +import com.l2jserver.model.world.character.CharacterClass; +import com.l2jserver.util.dimensional.Point; + +public class ${javaClassName}Template extends ${parent}Template { + @Inject + public ${javaClassName}Template(CharacterTemplateIDFactory factory) { + super(factory.createID(${ClassId}.id), ${ClassId}, Point.fromXYZ(${x}, ${y}, ${z})); + // ATTRIBUTES + attributes.intelligence = ${_INT}; + attributes.strength = ${STR}; + attributes.concentration = ${CON}; + attributes.mentality = ${MEN}; + attributes.dexterity = ${DEX}; + attributes.witness = ${WIT}; + attributes.physicalAttack = ${P_ATK}; + attributes.magicalAttack = ${M_ATK}; + attributes.physicalDefense = ${P_DEF}; + attributes.magicalDefense = ${M_DEF}; + attributes.attackSpeed = ${P_SPD}; + attributes.castSpeed = ${M_SPD}; + attributes.accuracy = ${ACC}; + attributes.criticalChance = ${CRITICAL}; + attributes.evasionChance = ${EVASION}; + attributes.moveSpeed = ${MOVE_SPD}; + attributes.maxWeigth = ${_LOAD}; + attributes.craft = ${canCraft}; + } + + protected ${javaClassName}Template(CharacterTemplateID id, + CharacterClass characterClass, Point spawnLocation) { + super(id, characterClass, spawnLocation); + } + + @Override + public L2Character create() { + final L2Character character = super.create(); + // TODO register skills + return character; + } +} diff --git a/src/tool/java/com/l2jserver/tool/conversor/npctemplate/NPCTemplateConverter.java b/src/tool/java/com/l2jserver/tool/conversor/npctemplate/NPCTemplateConverter.java new file mode 100644 index 000000000..e19674292 --- /dev/null +++ b/src/tool/java/com/l2jserver/tool/conversor/npctemplate/NPCTemplateConverter.java @@ -0,0 +1,126 @@ +/* + * 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.tool.conversor.npctemplate; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.io.IOUtils; + +import com.l2jserver.model.world.AbstractActor.Race; +import com.l2jserver.model.world.character.CharacterClass; +import com.l2jserver.util.factory.CollectionFactory; + +public class NPCTemplateConverter { + private static final String JDBC_URL = "jdbc:mysql://localhost/l2j-old"; + private static final String JDBC_USERNAME = "l2j"; + private static final String JDBC_PASSWORD = "changeme"; + + private static String template; + + private static Map parents = CollectionFactory + .newMap(); + + public static void main(String[] args) throws SQLException, IOException, + ClassNotFoundException { + Class.forName("com.mysql.jdbc.Driver"); + + template = IOUtils.toString(NPCTemplateConverter.class + .getResourceAsStream("CharacterTemplateBase.txt")); + System.out.println("Generating template classes..."); + + final Connection conn = DriverManager.getConnection(JDBC_URL, + JDBC_USERNAME, JDBC_PASSWORD); + try { + final PreparedStatement st = conn + .prepareStatement("SELECT * FROM char_templates"); + try { + st.execute(); + final ResultSet rs = st.getResultSet(); + while (rs.next()) { + String[] result = generateJavaClass(rs); + IOUtils.write(result[0], new FileOutputStream( + "generated/template/character/" + result[1])); + } + } finally { + st.close(); + } + } finally { + conn.close(); + } + } + + private static String[] generateJavaClass(ResultSet rs) throws SQLException { + String name = ""; + String template = NPCTemplateConverter.template; + for (int i = 1; i < rs.getMetaData().getColumnCount() + 1; i++) { + template = replace(template, rs.getMetaData().getColumnName(i), + rs.getString(i)); + if (rs.getMetaData().getColumnName(i).equals("ClassId")) { + final CharacterClass c = CharacterClass.fromID(Integer + .parseInt(rs.getString(i))); + name = camelCase(c.name()) + "Template.java"; + } + } + return new String[] { template, name }; + } + + private static String replace(String template, String key, String value) { + if (key.equals("ClassId")) { + final CharacterClass c = CharacterClass.fromID(Integer + .parseInt(value)); + value = "CharacterClass." + c.name(); + String parent; + if (c.parent != null) { + parent = parents.get(c.parent); + } else { + parent = "Abstract" + camelCase(c.race.name()) + "Character"; + } + parents.put(c, camelCase(c.name())); + template = template.replaceAll("\\$\\{parent\\}", parent); + template = template.replaceAll("\\$\\{javaClassName\\}", + camelCase(c.name())); + } + if (key.equals("RaceId")) + value = Race.fromOption(Integer.parseInt(value)).name(); + if (key.equals("canCraft")) + value = (value.equals("1") ? "true" : "false"); + + return template.replaceAll("\\$\\{" + key + "\\}", value); + } + + private static String camelCase(String c) { + Pattern p = Pattern.compile("[a-zA-Z0-9]+"); + Matcher m = p.matcher(c.replaceAll("_", " ")); + StringBuffer result = new StringBuffer(); + String word; + while (m.find()) { + word = m.group(); + result.append(word.substring(0, 1).toUpperCase() + + word.substring(1).toLowerCase()); + } + return result.toString(); + } +}