1
0
mirror of https://github.com/Rogiel/l2jserver2 synced 2025-12-06 07:32:46 +00:00

Inventory open implementation, Html updates, Pathing generator,

Signed-off-by: Rogiel <rogiel@rogiel.com>
This commit is contained in:
2011-05-19 23:42:45 -03:00
parent 1de8662be6
commit 9b4fe02ee4
49 changed files with 908 additions and 166 deletions

2
data/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/cache
/pathing.db

View File

@@ -118,14 +118,7 @@
<artifactId>htmlparser</artifactId> <artifactId>htmlparser</artifactId>
<version>2.1</version> <version>2.1</version>
<type>jar</type> <type>jar</type>
<scope>compile</scope> <scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>sitecapturer</artifactId>
<version>2.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -33,11 +33,14 @@ import com.l2jserver.model.template.ItemTemplate;
import com.l2jserver.model.world.Item; import com.l2jserver.model.world.Item;
import com.l2jserver.model.world.L2Character; import com.l2jserver.model.world.L2Character;
import com.l2jserver.model.world.character.CharacterInventory; 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.DatabaseService;
import com.l2jserver.service.database.MySQLDatabaseService.CachedMapper; import com.l2jserver.service.database.MySQLDatabaseService.CachedMapper;
import com.l2jserver.service.database.MySQLDatabaseService.Mapper; import com.l2jserver.service.database.MySQLDatabaseService.Mapper;
import com.l2jserver.service.database.MySQLDatabaseService.SelectListQuery; import com.l2jserver.service.database.MySQLDatabaseService.SelectListQuery;
import com.l2jserver.service.database.MySQLDatabaseService.SelectSingleQuery; import com.l2jserver.service.database.MySQLDatabaseService.SelectSingleQuery;
import com.l2jserver.util.dimensional.Coordinate;
/** /**
* {@link ItemDAO} implementation for MySQL5 * {@link ItemDAO} implementation for MySQL5
@@ -67,6 +70,13 @@ public class MySQL5ItemDAO extends AbstractMySQL5DAO<Item> implements ItemDAO {
public static final String TEMPLATE_ID = "template_id"; public static final String TEMPLATE_ID = "template_id";
public static final String CHAR_ID = MySQL5CharacterDAO.CHAR_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 @Inject
public MySQL5ItemDAO(DatabaseService database, public MySQL5ItemDAO(DatabaseService database,
final ItemIDProvider idFactory, final ItemIDProvider idFactory,
@@ -95,7 +105,21 @@ public class MySQL5ItemDAO extends AbstractMySQL5DAO<Item> implements ItemDAO {
final Item item = template.create(); final Item item = template.create();
item.setID(id); 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; return item;
} }
@@ -107,7 +131,7 @@ public class MySQL5ItemDAO extends AbstractMySQL5DAO<Item> implements ItemDAO {
private final Mapper<ItemID> idMapper = new Mapper<ItemID>() { private final Mapper<ItemID> idMapper = new Mapper<ItemID>() {
@Override @Override
public ItemID map(ResultSet rs) throws SQLException { 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<Item> implements ItemDAO {
return database.query(new SelectListQuery<ItemID>() { return database.query(new SelectListQuery<ItemID>() {
@Override @Override
protected String query() { protected String query() {
return "SELECT `" + CHAR_ID + "` FROM `" + TABLE + "`"; return "SELECT `" + ITEM_ID + "` FROM `" + TABLE + "`";
} }
@Override @Override

View File

@@ -23,7 +23,7 @@ import com.l2jserver.game.ProtocolVersion;
* *
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2JConstants { public class L2JConstant {
/** /**
* Indicate the supported protocol for this compilation. * Indicate the supported protocol for this compilation.
* <p> * <p>

View File

@@ -17,19 +17,25 @@
package com.l2jserver; package com.l2jserver;
import com.google.inject.Injector; 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.NPCIDProvider;
import com.l2jserver.model.id.object.provider.ObjectIDResolver;
import com.l2jserver.model.id.template.NPCTemplateID; import com.l2jserver.model.id.template.NPCTemplateID;
import com.l2jserver.model.id.template.provider.NPCTemplateIDProvider; import com.l2jserver.model.id.template.provider.NPCTemplateIDProvider;
import com.l2jserver.model.world.L2Character;
import com.l2jserver.model.world.NPC; import com.l2jserver.model.world.NPC;
import com.l2jserver.service.ServiceManager; import com.l2jserver.service.ServiceManager;
import com.l2jserver.service.cache.CacheService; import com.l2jserver.service.cache.CacheService;
import com.l2jserver.service.configuration.ConfigurationService; import com.l2jserver.service.configuration.ConfigurationService;
import com.l2jserver.service.database.DatabaseService; import com.l2jserver.service.database.DatabaseService;
import com.l2jserver.service.game.CharacterService;
import com.l2jserver.service.game.SpawnService; import com.l2jserver.service.game.SpawnService;
import com.l2jserver.service.game.chat.ChatService; 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.scripting.ScriptingService;
import com.l2jserver.service.game.template.TemplateService; 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.NetworkService;
import com.l2jserver.service.network.keygen.BlowfishKeygenService; import com.l2jserver.service.network.keygen.BlowfishKeygenService;
import com.l2jserver.util.dimensional.Point; import com.l2jserver.util.dimensional.Point;
@@ -55,6 +61,9 @@ public class L2JGameServerMain {
serviceManager.start(ChatService.class); serviceManager.start(ChatService.class);
serviceManager.start(CharacterService.class);
serviceManager.start(PathingService.class);
serviceManager.start(BlowfishKeygenService.class); serviceManager.start(BlowfishKeygenService.class);
serviceManager.start(NetworkService.class); serviceManager.start(NetworkService.class);
@@ -86,5 +95,16 @@ public class L2JGameServerMain {
npc.setPoint(Point.fromXYZ(-71301, 258259, -3134)); npc.setPoint(Point.fromXYZ(-71301, 258259, -3134));
spawnService.spawn(npc, null); spawnService.spawn(npc, null);
final ObjectIDResolver resolver = injector
.getInstance(ObjectIDResolver.class);
final ObjectID<L2Character> 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());
} }
} }

View File

@@ -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.CharacterActionPacket;
import com.l2jserver.game.net.packet.client.CharacterChatMessagePacket; import com.l2jserver.game.net.packet.client.CharacterChatMessagePacket;
import com.l2jserver.game.net.packet.client.CharacterCreatePacket; 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.CharacterRequestMovePacket;
import com.l2jserver.game.net.packet.client.CharacterSelectPacket; import com.l2jserver.game.net.packet.client.CharacterSelectPacket;
import com.l2jserver.game.net.packet.client.CharacterValidatePositionPacket; import com.l2jserver.game.net.packet.client.CharacterValidatePositionPacket;
@@ -163,6 +164,8 @@ public class Lineage2PacketReader extends OneToOneDecoder {
return EnterWorld.class; return EnterWorld.class;
case CharacterActionPacket.OPCODE: case CharacterActionPacket.OPCODE:
return CharacterActionPacket.class; return CharacterActionPacket.class;
case CharacterRequestInventoryPacket.OPCODE:
return CharacterRequestInventoryPacket.class;
default: default:
logger.warn("Unknown opcode: 0x{}", Integer.toHexString(opcode)); logger.warn("Unknown opcode: 0x{}", Integer.toHexString(opcode));
break; break;

View File

@@ -17,8 +17,6 @@
package com.l2jserver.game.net.packet.client; package com.l2jserver.game.net.packet.client;
import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.l2jserver.game.net.Lineage2Connection; 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.NPCID;
import com.l2jserver.model.id.object.provider.ObjectIDResolver; import com.l2jserver.model.id.object.provider.ObjectIDResolver;
import com.l2jserver.model.world.NPC; import com.l2jserver.model.world.NPC;
import com.l2jserver.service.game.world.WorldService;
import com.l2jserver.util.dimensional.Coordinate; import com.l2jserver.util.dimensional.Coordinate;
/** /**
@@ -85,7 +82,6 @@ public class CharacterActionPacket extends AbstractClientPacket {
@Override @Override
public void process(final Lineage2Connection conn) { public void process(final Lineage2Connection conn) {
// since this is an erasure type, this is safe. // since this is an erasure type, this is safe.
System.out.println(objectId);
final ObjectID<NPC> id = idResolver.resolve(objectId); final ObjectID<NPC> id = idResolver.resolve(objectId);
if (!(id instanceof NPCID)) { if (!(id instanceof NPCID)) {
System.out.println("Incorrect type: " + id); System.out.println("Incorrect type: " + id);

View File

@@ -0,0 +1,47 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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 <a href="http://www.rogiel.com">Rogiel</a>
*/
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()));
}
}

View File

@@ -21,8 +21,7 @@ import org.jboss.netty.buffer.ChannelBuffer;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.packet.AbstractClientPacket; import com.l2jserver.game.net.packet.AbstractClientPacket;
import com.l2jserver.model.world.character.event.CharacterMoveEvent; import com.l2jserver.service.game.CharacterService;
import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.util.dimensional.Point; import com.l2jserver.util.dimensional.Point;
/** /**
@@ -37,16 +36,16 @@ public class CharacterValidatePositionPacket extends AbstractClientPacket {
public static final int OPCODE = 0x59; 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 Point point;
private int extra; // vehicle id private int extra; // vehicle id
@Inject @Inject
public CharacterValidatePositionPacket(WorldEventDispatcher eventDispatcher) { public CharacterValidatePositionPacket(CharacterService charService) {
this.eventDispatcher = eventDispatcher; this.charService = charService;
} }
@Override @Override
@@ -58,8 +57,6 @@ public class CharacterValidatePositionPacket extends AbstractClientPacket {
@Override @Override
public void process(final Lineage2Connection conn) { public void process(final Lineage2Connection conn) {
conn.getCharacter().setPoint(point); charService.receivedValidation(conn.getCharacter(), point);
eventDispatcher.dispatch(new CharacterMoveEvent(conn.getCharacter(),
point));
} }
} }

View File

@@ -23,7 +23,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.l2jserver.L2JConstants; import com.l2jserver.L2JConstant;
import com.l2jserver.game.ProtocolVersion; import com.l2jserver.game.ProtocolVersion;
import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.Lineage2CryptographyKey; import com.l2jserver.game.net.Lineage2CryptographyKey;
@@ -87,9 +87,9 @@ public class ProtocolVersionPacket extends AbstractClientPacket {
log.debug("Client protocol version: {}", version); log.debug("Client protocol version: {}", version);
conn.setVersion(version); conn.setVersion(version);
if (L2JConstants.SUPPORTED_PROTOCOL != version) { if (L2JConstant.SUPPORTED_PROTOCOL != version) {
log.info("Incorrect protocol version: {0}. Only {1} is supported.", log.info("Incorrect protocol version: {0}. Only {1} is supported.",
version, L2JConstants.SUPPORTED_PROTOCOL); version, L2JConstant.SUPPORTED_PROTOCOL);
// notify wrong protocol and close connection // notify wrong protocol and close connection
conn.write(new KeyPacket(inKey, false)).addListener( conn.write(new KeyPacket(inKey, false)).addListener(
new ChannelFutureListener() { new ChannelFutureListener() {

View File

@@ -42,26 +42,28 @@ public class ActorMovementPacket extends AbstractServerPacket {
*/ */
private final Actor actor; 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); super(OPCODE);
this.actor = actor; this.actor = actor;
this.source = source; this.target = target;
} }
@Override @Override
public void write(Lineage2Connection conn, ChannelBuffer buffer) { public void write(Lineage2Connection conn, ChannelBuffer buffer) {
buffer.writeInt(actor.getID().getID()); 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().getX());
buffer.writeInt(actor.getPoint().getY()); buffer.writeInt(actor.getPoint().getY());
buffer.writeInt(actor.getPoint().getZ()); buffer.writeInt(actor.getPoint().getZ());
buffer.writeInt(source.getX());
buffer.writeInt(source.getY());
buffer.writeInt(source.getZ());
} }
} }

View File

@@ -281,7 +281,7 @@ public class CharacterInformationPacket extends AbstractServerPacket {
buffer.writeInt(0x01); // special effects? circles around player... buffer.writeInt(0x01); // special effects? circles around player...
buffer.writeInt(200); // max cp buffer.writeInt(200); // max cp
buffer.writeInt(200); // cur 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) // enchant effect (minimum 127)
buffer.writeByte(0x00);// team, 1=blue,2 red,0 is unknown buffer.writeByte(0x00);// team, 1=blue,2 red,0 is unknown

View File

@@ -51,26 +51,29 @@ public class CharacterInventoryPacket extends AbstractServerPacket {
@Override @Override
public void write(Lineage2Connection conn, ChannelBuffer buffer) { public void write(Lineage2Connection conn, ChannelBuffer buffer) {
buffer.writeByte((showWindow ? 0x01 : 0x00)); buffer.writeShort((showWindow ? 0x01 : 0x00));
buffer.writeInt(inventory.getItemCount()); // item count // 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) { for (Item item : inventory) {
if (item.getLocation() == InventoryLocation.WAREHOUSE
|| item.getLocation() == null) {
continue;
}
buffer.writeInt(item.getID().getID()); // obj id buffer.writeInt(item.getID().getID()); // obj id
buffer.writeInt(item.getTemplateID().getID()); // item id buffer.writeInt(item.getTemplateID().getID()); // item id
if (item.getLocation() == InventoryLocation.PAPERDOLL) { buffer.writeInt(slot); // loc slot
buffer.writeInt(item.getPaperdoll().id); // loc slot
} else {
buffer.writeInt(0x00); // loc slot
}
buffer.writeLong(item.getCount()); // count buffer.writeLong(item.getCount()); // count
buffer.writeShort(0x00); // item type2 buffer.writeShort(0x00); // item type2
buffer.writeShort(0x00); // item type3 buffer.writeShort(0x00); // item type3
if (item.getLocation() == InventoryLocation.PAPERDOLL) { buffer.writeShort((item.getLocation() == InventoryLocation.PAPERDOLL ? 0x01
buffer.writeShort(0x01); // equiped? : 0x00)); // equiped?
} else { buffer.writeInt((item.getPaperdoll() != null ? item.getPaperdoll().id
buffer.writeShort(0x00); // equiped? : 0)); // body part
} buffer.writeShort(127); // enchant level
buffer.writeInt(0x00); // body part
buffer.writeShort(0x00); // enchant level
// race tickets // race tickets
buffer.writeShort(0x00); // item type4 (custom type 2) buffer.writeShort(0x00); // item type4 (custom type 2)
buffer.writeInt(0x00); // augument buffer.writeInt(0x00); // augument
@@ -85,6 +88,8 @@ public class CharacterInventoryPacket extends AbstractServerPacket {
buffer.writeShort(0x00); buffer.writeShort(0x00);
buffer.writeShort(0x00); buffer.writeShort(0x00);
buffer.writeShort(0x00); buffer.writeShort(0x00);
slot++;
} }
// TODO inventory block // TODO inventory block
// buffer.writeShort(_inventory.getBlockItems().length); // buffer.writeShort(_inventory.getBlockItems().length);

View File

@@ -23,6 +23,7 @@ import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.packet.AbstractServerPacket; import com.l2jserver.game.net.packet.AbstractServerPacket;
import com.l2jserver.model.world.NPC; import com.l2jserver.model.world.NPC;
import com.l2jserver.util.BufferUtils; import com.l2jserver.util.BufferUtils;
import com.l2jserver.util.html.markup.HtmlTemplate;
/** /**
* This packet sends an HTML message to be displayed in the client. * 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; public static final int OPCODE = 0x19;
private final NPC npc; private final NPC npc;
private final Html html; private final String html;
public NPCHtmlMessagePacket(NPC npc, Html html) { public NPCHtmlMessagePacket(NPC npc, Html html) {
super(OPCODE); super(OPCODE);
this.npc = npc; 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 @Override
public void write(Lineage2Connection conn, ChannelBuffer buffer) { public void write(Lineage2Connection conn, ChannelBuffer buffer) {
buffer.writeInt(npc.getID().getID()); buffer.writeInt(npc.getID().getID());
BufferUtils.writeString(buffer, html.toHtml()); BufferUtils.writeString(buffer, html);
buffer.writeInt(0x00); // item id buffer.writeInt(0x00); // item id
} }
} }

View File

@@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted;
import com.l2jserver.model.id.object.CharacterID; import com.l2jserver.model.id.object.CharacterID;
import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.object.allocator.IDAllocator;
import com.l2jserver.model.id.provider.IDProvider; 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}. * {@link IDProvider} for {@link CharacterID}.

View File

@@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted;
import com.l2jserver.model.id.object.ClanID; import com.l2jserver.model.id.object.ClanID;
import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.object.allocator.IDAllocator;
import com.l2jserver.model.id.provider.IDProvider; 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}. * {@link IDProvider} for {@link ClanID}.

View File

@@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted;
import com.l2jserver.model.id.object.ItemID; import com.l2jserver.model.id.object.ItemID;
import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.object.allocator.IDAllocator;
import com.l2jserver.model.id.provider.IDProvider; 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}. * {@link IDProvider} for {@link ItemID}.

View File

@@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted;
import com.l2jserver.model.id.object.NPCID; import com.l2jserver.model.id.object.NPCID;
import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.object.allocator.IDAllocator;
import com.l2jserver.model.id.provider.IDProvider; 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}. * {@link IDProvider} for {@link NPCID}.

View File

@@ -18,7 +18,7 @@ package com.l2jserver.model.id.object.provider;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.l2jserver.model.id.ObjectID; import com.l2jserver.model.id.ObjectID;
import com.l2jserver.service.game.world.id.WorldIDService; import com.l2jserver.service.game.world.WorldIDService;
/** /**
* <h1>THIS PROVIDER IS READ ONLY!</h1> * <h1>THIS PROVIDER IS READ ONLY!</h1>

View File

@@ -21,7 +21,7 @@ import com.google.inject.assistedinject.Assisted;
import com.l2jserver.model.id.object.PetID; import com.l2jserver.model.id.object.PetID;
import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.object.allocator.IDAllocator;
import com.l2jserver.model.id.provider.IDProvider; 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}. * {@link IDProvider} for {@link PetID}.

View File

@@ -30,8 +30,7 @@ import com.l2jserver.model.world.capability.Actor;
import com.l2jserver.service.game.CharacterService; import com.l2jserver.service.game.CharacterService;
import com.l2jserver.service.network.NetworkService; import com.l2jserver.service.network.NetworkService;
import com.l2jserver.util.calculator.Calculator; import com.l2jserver.util.calculator.Calculator;
import com.l2jserver.util.html.markup.Markup; import com.l2jserver.util.html.markup.HtmlTemplate;
import com.l2jserver.util.html.markup.Markup.Builder;
import com.l2jserver.util.html.markup.MarkupTag; import com.l2jserver.util.html.markup.MarkupTag;
/** /**
@@ -110,16 +109,18 @@ public abstract class NPCTemplate extends ActorTemplate<NPC> {
// target this npc // target this npc
charService.target(character, npc); charService.target(character, npc);
// generate not implemented message // generate not implemented message
final Markup markup = new Markup(name + " - Notice", new Builder() { final HtmlTemplate template = new HtmlTemplate(name) {
@Override @Override
public void build(MarkupTag body) { 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"); body.addLink("Click me!", "test");
} }
}); };
conn.write(new NPCHtmlMessagePacket(npc, markup.build())); template.register("name", name);
conn.write(new NPCHtmlMessagePacket(npc, template));
} }
/** /**

View File

@@ -73,7 +73,8 @@ public class CharacterInventory implements Iterable<Item> {
* the items to be added * the items to be added
*/ */
public void load(List<Item> items) { public void load(List<Item> items) {
items.addAll(items); this.items.clear();
this.items.addAll(items);
} }
/** /**

View File

@@ -31,16 +31,18 @@ import com.l2jserver.service.game.SpawnService;
import com.l2jserver.service.game.SpawnServiceImpl; import com.l2jserver.service.game.SpawnServiceImpl;
import com.l2jserver.service.game.chat.ChatService; import com.l2jserver.service.game.chat.ChatService;
import com.l2jserver.service.game.chat.SimpleChatService; 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.ScriptingService;
import com.l2jserver.service.game.scripting.ScriptingServiceImpl; import com.l2jserver.service.game.scripting.ScriptingServiceImpl;
import com.l2jserver.service.game.template.ScriptTemplateService; import com.l2jserver.service.game.template.ScriptTemplateService;
import com.l2jserver.service.game.template.TemplateService; 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.WorldService;
import com.l2jserver.service.game.world.WorldServiceImpl; import com.l2jserver.service.game.world.WorldServiceImpl;
import com.l2jserver.service.game.world.event.WorldEventDispatcher; import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.service.game.world.event.WorldEventDispatcherImpl; 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.Log4JLoggingService;
import com.l2jserver.service.logging.LoggingService; import com.l2jserver.service.logging.LoggingService;
import com.l2jserver.service.network.NettyNetworkService; import com.l2jserver.service.network.NettyNetworkService;
@@ -67,6 +69,9 @@ public class ServiceModule extends AbstractModule {
bind(WorldIDService.class).to(CachedWorldIDService.class).in( bind(WorldIDService.class).to(CachedWorldIDService.class).in(
Scopes.SINGLETON); Scopes.SINGLETON);
bind(PathingService.class).to(MapperPathingService.class).in(
Scopes.SINGLETON);
bind(BlowfishKeygenService.class).to(SecureBlowfishKeygenService.class) bind(BlowfishKeygenService.class).to(SecureBlowfishKeygenService.class)
.in(Scopes.SINGLETON); .in(Scopes.SINGLETON);
bind(NetworkService.class).to(NettyNetworkService.class).in( bind(NetworkService.class).to(NettyNetworkService.class).in(

View File

@@ -25,6 +25,8 @@ import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager; import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element; import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration; 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 net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import com.l2jserver.service.AbstractService; import com.l2jserver.service.AbstractService;
@@ -48,7 +50,8 @@ public class EhCacheService extends AbstractService implements CacheService {
@Override @Override
protected void doStart() throws ServiceStartException { 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"); interfaceCache = createCache("interface-cache");
} }

View File

@@ -122,8 +122,7 @@ public class MySQLDatabaseService extends AbstractService implements
objectCache = new Cache(new CacheConfiguration("database-service", objectCache = new Cache(new CacheConfiguration("database-service",
IDAllocator.ALLOCABLE_IDS) IDAllocator.ALLOCABLE_IDS)
.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU) .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(false).timeToLiveSeconds(60) .overflowToDisk(true).eternal(true).diskPersistent(false)
.timeToIdleSeconds(30).diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0)); .diskExpiryThreadIntervalSeconds(0));
cacheService.register(objectCache); cacheService.register(objectCache);
} }

View File

@@ -20,6 +20,7 @@ import com.l2jserver.model.world.L2Character;
import com.l2jserver.model.world.capability.Actor; import com.l2jserver.model.world.capability.Actor;
import com.l2jserver.service.Service; import com.l2jserver.service.Service;
import com.l2jserver.util.dimensional.Coordinate; import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
/** /**
* This service manages {@link L2Character} instances * This service manages {@link L2Character} instances
@@ -73,6 +74,26 @@ public interface CharacterService extends Service {
*/ */
void move(L2Character character, Coordinate coordinate); 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 * Set the character to walking mode
* *

View File

@@ -17,6 +17,7 @@
package com.l2jserver.service.game; package com.l2jserver.service.game;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.l2jserver.db.dao.ItemDAO;
import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.SystemMessage; import com.l2jserver.game.net.SystemMessage;
import com.l2jserver.game.net.packet.server.ActionFailedPacket; 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.model.world.npc.event.NPCSpawnEvent;
import com.l2jserver.service.AbstractService; import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractService.Depends; 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.ChatMessageDestination;
import com.l2jserver.service.game.chat.ChatService; import com.l2jserver.service.game.chat.ChatService;
import com.l2jserver.service.game.chat.channel.ChatChannel; 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.game.world.filter.impl.KnownListFilter;
import com.l2jserver.service.network.NetworkService; import com.l2jserver.service.network.NetworkService;
import com.l2jserver.util.dimensional.Coordinate; import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
/** /**
* Default implementation for {@link CharacterService}. * Default implementation for {@link CharacterService}.
@@ -65,7 +66,7 @@ import com.l2jserver.util.dimensional.Coordinate;
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
@Depends({ WorldService.class, ChatService.class, NetworkService.class, @Depends({ WorldService.class, ChatService.class, NetworkService.class,
SpawnService.class, AIService.class }) SpawnService.class })
public class CharacterServiceImpl extends AbstractService implements public class CharacterServiceImpl extends AbstractService implements
CharacterService { CharacterService {
/** /**
@@ -88,6 +89,10 @@ public class CharacterServiceImpl extends AbstractService implements
* The {@link SpawnService} * The {@link SpawnService}
*/ */
private final SpawnService spawnService; private final SpawnService spawnService;
/**
* The {@link ItemDAO}
*/
private final ItemDAO itemDao;
// /** // /**
// * The {@link AIService} // * The {@link AIService}
@@ -97,12 +102,14 @@ public class CharacterServiceImpl extends AbstractService implements
@Inject @Inject
public CharacterServiceImpl(WorldService worldService, public CharacterServiceImpl(WorldService worldService,
WorldEventDispatcher eventDispatcher, ChatService chatService, WorldEventDispatcher eventDispatcher, ChatService chatService,
NetworkService networkService, SpawnService spawnService) { NetworkService networkService, SpawnService spawnService,
ItemDAO itemDao) {
this.worldService = worldService; this.worldService = worldService;
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
this.chatService = chatService; this.chatService = chatService;
this.networkService = networkService; this.networkService = networkService;
this.spawnService = spawnService; this.spawnService = spawnService;
this.itemDao = itemDao;
} }
@Override @Override
@@ -114,6 +121,8 @@ public class CharacterServiceImpl extends AbstractService implements
if (!worldService.add(character)) if (!worldService.add(character))
// character is already in the world! // character is already in the world!
return; return;
itemDao.loadInventory(character);
// chat listener // chat listener
final ChatChannelListener globalChatListener = new ChatChannelListener() { final ChatChannelListener globalChatListener = new ChatChannelListener() {
@@ -221,10 +230,11 @@ public class CharacterServiceImpl extends AbstractService implements
// aiService.walk(character, coordinate); // aiService.walk(character, coordinate);
final Coordinate source = character.getPosition(); final Coordinate source = character.getPosition();
character.setPosition(coordinate); // we don't set the character coordinate yet, this will be done by
conn.write(new ActorMovementPacket(character, source)); // validate coordinate
conn.write(new ActorMovementPacket(character, coordinate));
// we don't dispatch events here, they will be dispatched by // we don't dispatch events here, they will be dispatched by
// CharacterValidatePositionPacket packets at fixed time intervals. // receivedValidation at fixed time intervals.
} }
@Override @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 @Override
public void walk(L2Character character) { public void walk(L2Character character) {
final CharacterID id = character.getID(); final CharacterID id = character.getID();

View File

@@ -0,0 +1,144 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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;
/**
* <h1>This implementation does not validate pathing!</h1>
* <p>
* 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 <a href="http://www.rogiel.com">Rogiel</a>
*/
@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>(
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 <a href="http://www.rogiel.com">Rogiel</a>
*/
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;
}
}
}

View File

@@ -0,0 +1,28 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.game.pathing;
import com.l2jserver.service.Service;
/**
* This service handles the pathing.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface PathingService extends Service {
}

View File

@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>. * along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.l2jserver.service.game.world.id; package com.l2jserver.service.game.world;
import java.util.Collection; import java.util.Collection;
@@ -25,6 +25,7 @@ import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.l2jserver.db.dao.CharacterDAO; import com.l2jserver.db.dao.CharacterDAO;
import com.l2jserver.db.dao.ItemDAO;
import com.l2jserver.model.id.ID; import com.l2jserver.model.id.ID;
import com.l2jserver.model.id.ObjectID; import com.l2jserver.model.id.ObjectID;
import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.object.allocator.IDAllocator;
@@ -58,18 +59,28 @@ public class CachedWorldIDService extends AbstractService implements
* The {@link CharacterDAO} * The {@link CharacterDAO}
*/ */
private final CharacterDAO characterDao; private final CharacterDAO characterDao;
/**
* The {@link ItemDAO}
*/
private final ItemDAO itemDao;
/** /**
* The ID cache * The ID cache
*/ */
private Cache cache; private Cache cache;
/**
* The loaded state
*/
private boolean loaded = false;
@Inject @Inject
public CachedWorldIDService(CacheService cacheService, public CachedWorldIDService(CacheService cacheService,
IDAllocator allocator, CharacterDAO characterDao) { IDAllocator allocator, CharacterDAO characterDao, ItemDAO itemDao) {
this.cacheService = cacheService; this.cacheService = cacheService;
this.allocator = allocator; this.allocator = allocator;
this.characterDao = characterDao; this.characterDao = characterDao;
this.itemDao = itemDao;
} }
@Override @Override
@@ -82,9 +93,13 @@ public class CachedWorldIDService extends AbstractService implements
.timeToIdleSeconds(30).diskPersistent(false) .timeToIdleSeconds(30).diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0)); .diskExpiryThreadIntervalSeconds(0));
cacheService.register(cache); cacheService.register(cache);
}
// load all ids @Override
public void load() {
load(characterDao.listIDs()); load(characterDao.listIDs());
load(itemDao.listIDs());
loaded = true;
} }
/** /**
@@ -103,6 +118,11 @@ public class CachedWorldIDService extends AbstractService implements
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <I extends ObjectID<?>> I resolve(int id) { public <I extends ObjectID<?>> I resolve(int id) {
if (!loaded) {
// ignore resolving before all IDs are loaded
return null;
}
final Element element = cache.get(id); final Element element = cache.get(id);
if (element == null) if (element == null)
return null; return null;
@@ -111,9 +131,8 @@ public class CachedWorldIDService extends AbstractService implements
@Override @Override
public <I extends ObjectID<?>> void add(I id) { public <I extends ObjectID<?>> void add(I id) {
if(id == null) if (id == null)
return; return;
System.out.println("Registering ID: "+id);
cache.put(new Element(id.getID(), id)); cache.put(new Element(id.getID(), id));
} }

View File

@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>. * along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.l2jserver.service.game.world.id; package com.l2jserver.service.game.world;
import com.l2jserver.model.id.ObjectID; import com.l2jserver.model.id.ObjectID;
import com.l2jserver.model.id.object.allocator.IDAllocator; import com.l2jserver.model.id.object.allocator.IDAllocator;
@@ -30,6 +30,11 @@ import com.l2jserver.service.database.DatabaseService;
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public interface WorldIDService extends Service { public interface WorldIDService extends Service {
/**
* Load all {@link ObjectID} from the database
*/
void load();
/** /**
* Tries to resolve an ID based on its raw value * Tries to resolve an ID based on its raw value
* *
@@ -43,7 +48,23 @@ public interface WorldIDService extends Service {
*/ */
<I extends ObjectID<?>> I resolve(int id); <I extends ObjectID<?>> I resolve(int id);
/**
* Adds a new ID to be managed by this service
*
* @param <I>
* the ID type
* @param id
* the id
*/
<I extends ObjectID<?>> void add(I id); <I extends ObjectID<?>> void add(I id);
/**
* Decouples an ID from this service
*
* @param <I>
* the ID type
* @param id
* the id
*/
<I extends ObjectID<?>> void remove(I id); <I extends ObjectID<?>> void remove(I id);
} }

View File

@@ -50,7 +50,7 @@ import com.l2jserver.util.factory.CollectionFactory;
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
@Depends({ LoggingService.class, TemplateService.class, ScriptingService.class, @Depends({ LoggingService.class, TemplateService.class, ScriptingService.class,
DatabaseService.class }) DatabaseService.class, WorldIDService.class })
public class WorldServiceImpl extends AbstractService implements WorldService { public class WorldServiceImpl extends AbstractService implements WorldService {
/** /**
* The logger * The logger
@@ -66,15 +66,22 @@ public class WorldServiceImpl extends AbstractService implements WorldService {
* The world event dispatcher * The world event dispatcher
*/ */
private final WorldEventDispatcherImpl dispatcher; private final WorldEventDispatcherImpl dispatcher;
/**
* The {@link WorldIDService}
*/
private final WorldIDService idService;
@Inject @Inject
public WorldServiceImpl(WorldEventDispatcher dispatcher) { public WorldServiceImpl(WorldEventDispatcher dispatcher,
WorldIDService idService) {
this.dispatcher = (WorldEventDispatcherImpl) dispatcher; this.dispatcher = (WorldEventDispatcherImpl) dispatcher;
this.idService = idService;
} }
@Override @Override
protected void doStart() throws ServiceStartException { protected void doStart() throws ServiceStartException {
objects.clear(); objects.clear();
idService.load();
} }
@Override @Override

View File

@@ -22,8 +22,9 @@ import org.htmlparser.tags.BodyTag;
import org.htmlparser.util.NodeList; import org.htmlparser.util.NodeList;
/** /**
* @author <a href="http://www.rogiel.com">Rogiel</a> * Lineage 2 {@link Tag}: <tt>body</tt>
* *
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2BodyTag extends BodyTag { public class L2BodyTag extends BodyTag {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -17,21 +17,17 @@
package com.l2jserver.util.html; package com.l2jserver.util.html;
import org.htmlparser.Tag; import org.htmlparser.Tag;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.tags.Span; import org.htmlparser.tags.Span;
/** /**
* @author <a href="http://www.rogiel.com">Rogiel</a> * Lineage 2 {@link Tag}: <tt>br</tt>
* *
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2BrTag extends Span { public class L2BrTag extends Span {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public L2BrTag() { public L2BrTag() {
super.setTagName("br"); super.setTagName("br");
Tag end = new TagNode();
end.setTagName("/br");
super.setEndTag(end);
super.setEmptyXmlTag(true);
} }
} }

View File

@@ -21,8 +21,9 @@ import org.htmlparser.nodes.TagNode;
import org.htmlparser.tags.Span; import org.htmlparser.tags.Span;
/** /**
* @author <a href="http://www.rogiel.com">Rogiel</a> * Lineage 2 {@link Tag}: <tt>center</tt>
* *
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2CenterTag extends Span { public class L2CenterTag extends Span {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -22,8 +22,9 @@ import org.htmlparser.tags.Div;
import org.htmlparser.util.NodeList; import org.htmlparser.util.NodeList;
/** /**
* @author <a href="http://www.rogiel.com">Rogiel</a> * Lineage 2 {@link Tag}: <tt>div</tt>
* *
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2DivTag extends Div { public class L2DivTag extends Div {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -22,8 +22,9 @@ import org.htmlparser.tags.Span;
import org.htmlparser.util.NodeList; import org.htmlparser.util.NodeList;
/** /**
* @author <a href="http://www.rogiel.com">Rogiel</a> * Lineage 2 {@link Tag}: <tt>font</tt>
* *
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2FontTag extends Span { public class L2FontTag extends Span {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -22,6 +22,8 @@ import org.htmlparser.tags.HeadTag;
import org.htmlparser.util.NodeList; import org.htmlparser.util.NodeList;
/** /**
* Lineage 2 {@link Tag}: <tt>head</tt>
*
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2HeadTag extends HeadTag { public class L2HeadTag extends HeadTag {

View File

@@ -22,8 +22,9 @@ import org.htmlparser.tags.Html;
import org.htmlparser.util.NodeList; import org.htmlparser.util.NodeList;
/** /**
* @author <a href="http://www.rogiel.com">Rogiel</a> * Lineage 2 {@link Tag}: <tt>html</tt>
* *
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2HtmlTag extends Html { public class L2HtmlTag extends Html {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -21,6 +21,8 @@ import org.htmlparser.nodes.TagNode;
import org.htmlparser.tags.ImageTag; import org.htmlparser.tags.ImageTag;
/** /**
* Lineage 2 {@link Tag}: <tt>img</tt>
*
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2ImageTag extends ImageTag { public class L2ImageTag extends ImageTag {
@@ -31,6 +33,5 @@ public class L2ImageTag extends ImageTag {
Tag end = new TagNode(); Tag end = new TagNode();
end.setTagName("/img"); end.setTagName("/img");
super.setEndTag(end); super.setEndTag(end);
super.setEmptyXmlTag(true);
} }
} }

View File

@@ -22,6 +22,8 @@ import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList; import org.htmlparser.util.NodeList;
/** /**
* Lineage 2 {@link Tag}: <tt>a</tt>
*
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2LinkTag extends LinkTag { public class L2LinkTag extends LinkTag {
@@ -33,6 +35,5 @@ public class L2LinkTag extends LinkTag {
end.setTagName("/a"); end.setTagName("/a");
super.setEndTag(end); super.setEndTag(end);
super.setChildren(new NodeList()); super.setChildren(new NodeList());
super.setEmptyXmlTag(true);
} }
} }

View File

@@ -17,21 +17,17 @@
package com.l2jserver.util.html; package com.l2jserver.util.html;
import org.htmlparser.Tag; import org.htmlparser.Tag;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.tags.Span; import org.htmlparser.tags.Span;
/** /**
* @author <a href="http://www.rogiel.com">Rogiel</a> * Lineage 2 {@link Tag}: <tt>p</tt>
* *
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2NewLineTag extends Span { public class L2NewLineTag extends Span {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public L2NewLineTag() { public L2NewLineTag() {
super.setTagName("p"); super.setTagName("p");
Tag end = new TagNode();
end.setTagName("/pp");
super.setEndTag(end);
super.setEmptyXmlTag(true);
} }
} }

View File

@@ -22,6 +22,8 @@ import org.htmlparser.tags.TitleTag;
import org.htmlparser.util.NodeList; import org.htmlparser.util.NodeList;
/** /**
* Lineage 2 {@link Tag}: <tt>title</tt>
*
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class L2TitleTag extends TitleTag { public class L2TitleTag extends TitleTag {

View File

@@ -0,0 +1,151 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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:
*
* <pre>
* final HtmlTemplate template = new HtmlTemplate(&quot;Template implementation sample&quot;) {
* &#064;Override
* public void build(MarkupTag body) {
* body.text(&quot;Hello world!&quot;).br().text(&quot;New line!&quot;);
* }
* };
* final String html = template.toHtmlString();
* </pre>
*
* Using the {@link Html} object (from {@link #build()}) you can obtain the HTML
* code using {@link Html#toHtml()}.
* <p>
* The generated code will be the smaller possible because the client has packet
* size limitations, it will not contain any formatting.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public abstract class HtmlTemplate {
/**
* The template title (will be displayed in the game window)
*/
private final String title;
/**
* The template variables
*/
private Map<String, String> 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<String, String> 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());
}
}

View File

@@ -1,57 +0,0 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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 <a href="http://www.rogiel.com">Rogiel</a>
*
*/
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);
}
}

View File

@@ -28,32 +28,78 @@ import com.l2jserver.util.html.L2LinkTag;
import com.l2jserver.util.html.L2NewLineTag; import com.l2jserver.util.html.L2NewLineTag;
/** /**
* @author <a href="http://www.rogiel.com">Rogiel</a> * This is an helper class that helps creating new tags in the HTML document.
* *
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class MarkupTag { public class MarkupTag {
/**
* The current tag
*/
private final Tag tag; private final Tag tag;
/**
* The parent {@link MarkupTag}
*/
private final MarkupTag parent; 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) { public MarkupTag(Tag tag, MarkupTag parent) {
this.tag = tag; this.tag = tag;
this.parent = parent; this.parent = parent;
} }
/**
* Creates a new instance without a parent
*
* @param tag
* the tag
*/
public MarkupTag(Tag tag) { public MarkupTag(Tag tag) {
this(tag, null); 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) { public MarkupTag attr(String name, String value) {
tag.setAttribute(name, value); tag.setAttribute(name, value);
return this; 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) { public MarkupTag text(String text) {
tag.getChildren().add(new TextNode(text)); tag.getChildren().add(new TextNode(text));
return this; 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) { public MarkupTag text(String text, String color) {
final Tag font = new L2FontTag(); final Tag font = new L2FontTag();
font.setAttribute("color", color); font.setAttribute("color", color);
@@ -62,30 +108,61 @@ public class MarkupTag {
return this; return this;
} }
/**
* Creates a new DIV element
*
* @return this div {@link MarkupTag}
*/
public MarkupTag div() { public MarkupTag div() {
final Tag tag = new L2DivTag(); final Tag tag = new L2DivTag();
this.tag.getChildren().add(tag); this.tag.getChildren().add(tag);
return new MarkupTag(tag, this); return new MarkupTag(tag, this);
} }
/**
* Inserts a line break
*
* @return this {@link MarkupTag}
*/
public MarkupTag br() { public MarkupTag br() {
final Tag tag = new L2BrTag(); final Tag tag = new L2BrTag();
this.tag.getChildren().add(tag); this.tag.getChildren().add(tag);
return this; return this;
} }
/**
* Inserts a new paragraph
*
* @return this {@link MarkupTag}
*/
public MarkupTag p() { public MarkupTag p() {
final Tag tag = new L2NewLineTag(); final Tag tag = new L2NewLineTag();
this.tag.getChildren().add(tag); this.tag.getChildren().add(tag);
return this; return this;
} }
/**
* Creates a new CENTER element. Text inside this element will be centered.
*
* @return this CENTER {@link MarkupTag}
*/
public MarkupTag center() { public MarkupTag center() {
final Tag tag = new L2CenterTag(); final Tag tag = new L2CenterTag();
this.tag.getChildren().add(tag); this.tag.getChildren().add(tag);
return new MarkupTag(this.tag, this); 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) { public MarkupTag addImage(String src, int height, int width) {
final Tag tag = new L2ImageTag(); final Tag tag = new L2ImageTag();
this.tag.getChildren().add(tag); this.tag.getChildren().add(tag);
@@ -95,6 +172,15 @@ public class MarkupTag {
return this; 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) { public MarkupTag addLink(String text, String action) {
final Tag tag = new L2LinkTag(); final Tag tag = new L2LinkTag();
this.tag.getChildren().add(tag); this.tag.getChildren().add(tag);
@@ -103,6 +189,11 @@ public class MarkupTag {
return this; return this;
} }
/**
* Close this tag and return the parent element
*
* @return the parent element, if any.
*/
public MarkupTag close() { public MarkupTag close() {
return parent; return parent;
} }

View File

@@ -39,9 +39,9 @@ import com.l2jserver.model.world.player.event.PlayerListener;
import com.l2jserver.model.world.player.event.PlayerSpawnEvent; import com.l2jserver.model.world.player.event.PlayerSpawnEvent;
import com.l2jserver.service.ServiceManager; import com.l2jserver.service.ServiceManager;
import com.l2jserver.service.ServiceStartException; 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.WorldService;
import com.l2jserver.service.game.world.event.WorldEventDispatcher; import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.service.game.world.id.WorldIDService;
public class WorldEventDispatcherImplTest { public class WorldEventDispatcherImplTest {
private WorldService world; private WorldService world;

View File

@@ -0,0 +1,62 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@@ -0,0 +1,126 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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<CharacterClass, String> 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();
}
}