diff --git a/data/script/template/script/template/actor/monster/WolfMonsterTemplate.java b/data/script/template/script/template/actor/monster/WolfMonsterTemplate.java index 6046e36b9..2c6205749 100644 --- a/data/script/template/script/template/actor/monster/WolfMonsterTemplate.java +++ b/data/script/template/script/template/actor/monster/WolfMonsterTemplate.java @@ -36,4 +36,6 @@ public class WolfMonsterTemplate extends MonsterNPCTemplate { this.collisionRadius = 13.00; this.collisionHeight = 9.00; } + + } diff --git a/data/script/template/script/template/actor/npc/RoxxyGatekeeperTemplate.java b/data/script/template/script/template/actor/npc/RoxxyGatekeeperTemplate.java index 8dc2cd586..cd5622324 100644 --- a/data/script/template/script/template/actor/npc/RoxxyGatekeeperTemplate.java +++ b/data/script/template/script/template/actor/npc/RoxxyGatekeeperTemplate.java @@ -19,6 +19,9 @@ package script.template.actor.npc; import com.google.inject.Inject; import com.l2jserver.model.id.template.provider.NPCTemplateIDProvider; import com.l2jserver.model.template.npc.TeleporterNPCTemplate; +import com.l2jserver.util.exception.L2Exception; +import com.l2jserver.util.html.markup.HtmlTemplate; +import com.l2jserver.util.html.markup.MarkupTag; /** * @author Rogiel @@ -48,6 +51,57 @@ public class RoxxyGatekeeperTemplate extends TeleporterNPCTemplate { addLocation("Talking Island, Northern Territor", TALKING_ISLAND_NORTHERN_TERRITORY, 1000); addLocation("Obelisk of Victory", OBELISK_OF_VICTORY, 470); + } + @Override + protected HtmlTemplate getChat(String name) throws L2Exception { + if (name.equals("")) { + return new HtmlTemplate() { + @Override + protected void build(MarkupTag body) { + body.text( + "Welcome! I am Gatekeeper Roxxy, dispatched from the Ivory Tower. " + + "I'm very happy to return to my hometown. Have you perhaps been to " + + "Einhovant's School of Magic? Grand Magister Gallint was my old " + + "teacher. Now then, how can I help you?") + .br(); + body.addLink("Ask about the airship wharf.", + "npc_${npcid}_Chat airship").br(); + body.addLink("Ask about the Ivory Tower.", + "npc_${npcid}_Chat ivory").br(); + body.addLink("Teleport", "npc_${npcid}_Chat teleport").br(); + body.addLink("Exchange Dimension Diamonds. (TODO)", + "npc_${npcid}_multisell 002").br(); + body.addLink("Noblesse Exclusive Teleport", + "npc_${npcid}_Quest 2000_NoblesseTeleport").br(); + body.addLink("Receive your Birthday Gift! (TODO)", + "npc_${npcid}_Quest CharacterBirthday").br(); + body.addLink("Quest", "npc_${npcid}_Quest").br(); + } + }; + } else if (name.equals("airship")) { + return new HtmlTemplate() { + @Override + protected void build(MarkupTag body) { + body.text("This text is not yet implemented."); + } + }; + } else if (name.equals("ivory")) { + return new HtmlTemplate() { + @Override + protected void build(MarkupTag body) { + body.text( + "The Ivory Tower is the foremost temple of all Mystics. It has been " + + "well known as such ever since the age of Elmoreden. I was born here, and " + + "graduated from Einhovant's School of Wizardry. And now, I am working as a " + + "gatekeeper by the order of the Ivory Tower. If you happen to go to the Ivory " + + "Tower later on, please give my best regards to Grand Magister Valerie. She " + + "is my teacher and a wonderful, caring person.") + .br(); + body.addLink("Back", "npc_${npcid}"); + } + }; + } + return super.getChat(name); } } diff --git a/data/script/template/script/template/item/AdenaItemTemplate.java b/data/script/template/script/template/item/AdenaItemTemplate.java index de3a80acc..a369e5493 100644 --- a/data/script/template/script/template/item/AdenaItemTemplate.java +++ b/data/script/template/script/template/item/AdenaItemTemplate.java @@ -18,19 +18,18 @@ package script.template.item; import com.google.inject.Inject; import com.l2jserver.model.id.template.provider.ItemTemplateIDProvider; -import com.l2jserver.model.template.ItemTemplate; import com.l2jserver.model.template.capability.Stackable; +import com.l2jserver.model.template.item.EtcItemTemplate; import com.l2jserver.model.world.Item; -public class AdenaItemTemplate extends ItemTemplate implements Stackable { +public class AdenaItemTemplate extends EtcItemTemplate implements + Stackable { public static final int ID = 57; @Inject public AdenaItemTemplate(ItemTemplateIDProvider factory) { - super(factory.createID(ID)); - this.icon = "icon.etc_adena_i00"; + super(factory.createID(ID), "icon.etc_adena_i00", ItemMaterial.GOLD); this.immediateEffect = true; - this.material = ItemMaterial.GOLD; this.price = 1; } } diff --git a/data/script/template/script/template/item/LargaFireworkItemTemplate.java b/data/script/template/script/template/item/LargaFireworkItemTemplate.java new file mode 100644 index 000000000..03dd43f8e --- /dev/null +++ b/data/script/template/script/template/item/LargaFireworkItemTemplate.java @@ -0,0 +1,39 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package script.template.item; + +import com.google.inject.Inject; +import com.l2jserver.model.id.template.provider.ItemTemplateIDProvider; +import com.l2jserver.model.id.template.provider.SkillTemplateIDProvider; +import com.l2jserver.model.template.capability.Stackable; +import com.l2jserver.model.template.item.SkillEtcItemTemplate; +import com.l2jserver.model.world.Item; + +public class LargaFireworkItemTemplate extends SkillEtcItemTemplate implements + Stackable { + public static final int ID = 6407; + + @Inject + public LargaFireworkItemTemplate(ItemTemplateIDProvider provider, + SkillTemplateIDProvider skillProvider) { + // TODO set skill id + super(provider.createID(ID), "icon.etc_ultra_bomb_i00", + ItemMaterial.STEEL, skillProvider.createID(0)); + this.immediateEffect = true; + this.price = 1; + } +} diff --git a/data/script/template/script/template/item/armor/Dummy2ArmorTemplate.java b/data/script/template/script/template/item/armor/Dummy2ArmorTemplate.java index 74d9b9b59..37d82bce2 100644 --- a/data/script/template/script/template/item/armor/Dummy2ArmorTemplate.java +++ b/data/script/template/script/template/item/armor/Dummy2ArmorTemplate.java @@ -20,7 +20,6 @@ import com.google.inject.Inject; import com.l2jserver.model.id.template.provider.ItemTemplateIDProvider; import com.l2jserver.model.world.capability.Attackable; import com.l2jserver.model.world.capability.Attacker; -import com.l2jserver.model.world.capability.Damagable; import com.l2jserver.model.world.capability.Enchantable; public class Dummy2ArmorTemplate extends AbstractGradeAArmorTemplate { @@ -39,10 +38,6 @@ public class Dummy2ArmorTemplate extends AbstractGradeAArmorTemplate { public void defend(Attacker source, Attackable target) { } - @Override - public void interceptIncomingDamage(Damagable target) { - } - @Override public void enchant(Enchantable target) { if (target.getEnchantLevel() >= MAX_ENCHANT) diff --git a/data/script/template/script/template/item/armor/DummyArmorTemplate.java b/data/script/template/script/template/item/armor/DummyArmorTemplate.java index 442522ea8..c0633df7f 100644 --- a/data/script/template/script/template/item/armor/DummyArmorTemplate.java +++ b/data/script/template/script/template/item/armor/DummyArmorTemplate.java @@ -20,7 +20,6 @@ import com.google.inject.Inject; import com.l2jserver.model.id.template.provider.ItemTemplateIDProvider; import com.l2jserver.model.world.capability.Attackable; import com.l2jserver.model.world.capability.Attacker; -import com.l2jserver.model.world.capability.Damagable; public class DummyArmorTemplate extends AbstractNoGradeArmorTemplate { public static final int ID = 20; @@ -37,10 +36,6 @@ public class DummyArmorTemplate extends AbstractNoGradeArmorTemplate { public void defend(Attacker source, Attackable target) { } - @Override - public void interceptIncomingDamage(Damagable target) { - } - @Override public int getPhysicalDefense() { return REDUCED_DAMAGE_PHYSICAL; 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 780944def..715711d36 100644 --- a/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketReader.java +++ b/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketReader.java @@ -37,6 +37,7 @@ import com.l2jserver.game.net.packet.client.CharacterRequestActionUse; import com.l2jserver.game.net.packet.client.CharacterRequestBypass; import com.l2jserver.game.net.packet.client.CharacterRequestInventoryPacket; import com.l2jserver.game.net.packet.client.CharacterRequestMovePacket; +import com.l2jserver.game.net.packet.client.CharacterRequestOpenMap; import com.l2jserver.game.net.packet.client.CharacterSelectPacket; import com.l2jserver.game.net.packet.client.CharacterValidatePositionPacket; import com.l2jserver.game.net.packet.client.EnterWorld; @@ -178,6 +179,8 @@ public class Lineage2PacketReader extends OneToOneDecoder { return CharacterAppearingPacket.class; case CharacterRequestActionUse.OPCODE: return CharacterRequestActionUse.class; + case CharacterRequestOpenMap.OPCODE: + return CharacterRequestOpenMap.class; default: logger.warn("Unknown opcode: 0x{}", Integer.toHexString(opcode)); break; diff --git a/src/main/java/com/l2jserver/game/net/packet/client/CharacterAttackRequestPacket.java b/src/main/java/com/l2jserver/game/net/packet/client/CharacterAttackRequestPacket.java index d2e428c78..9d4c6bc70 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/CharacterAttackRequestPacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/CharacterAttackRequestPacket.java @@ -29,6 +29,7 @@ import com.l2jserver.model.id.object.ActorID; import com.l2jserver.model.id.object.provider.ObjectIDResolver; import com.l2jserver.model.world.L2Character; import com.l2jserver.model.world.capability.Actor; +import com.l2jserver.service.game.character.ActorIsNotAttackableServiceException; import com.l2jserver.service.game.character.CannotSetTargetServiceException; import com.l2jserver.service.game.character.CharacterService; import com.l2jserver.util.dimensional.Coordinate; @@ -129,6 +130,8 @@ public class CharacterAttackRequestPacket extends AbstractClientPacket { charService.attack(character, actor); } catch (CannotSetTargetServiceException e) { conn.sendActionFailed(); + } catch (ActorIsNotAttackableServiceException e) { + conn.sendActionFailed(); } } } diff --git a/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestActionUse.java b/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestActionUse.java index 0df4a62c5..79e5ad3b0 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestActionUse.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestActionUse.java @@ -23,6 +23,8 @@ import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.packet.AbstractClientPacket; import com.l2jserver.model.world.L2Character; import com.l2jserver.model.world.L2Character.CharacterMoveType; +import com.l2jserver.service.game.character.CharacterAlreadyRunningServiceException; +import com.l2jserver.service.game.character.CharacterAlreadyWalkingServiceException; import com.l2jserver.service.game.character.CharacterService; /** @@ -101,10 +103,16 @@ public class CharacterRequestActionUse extends AbstractClientPacket { // TODO break; case WALK_RUN: - if (character.getMoveType() == CharacterMoveType.WALK) { - charService.run(character); - } else { - charService.walk(character); + try { + if (character.getMoveType() == CharacterMoveType.WALK) { + charService.run(character); + } else { + charService.walk(character); + } + } catch (CharacterAlreadyWalkingServiceException e) { + conn.sendActionFailed(); + } catch (CharacterAlreadyRunningServiceException e) { + conn.sendActionFailed(); } break; } diff --git a/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestMovePacket.java b/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestMovePacket.java index 5491db4dd..d27a1e3ea 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestMovePacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestMovePacket.java @@ -49,7 +49,26 @@ public class CharacterRequestMovePacket extends AbstractClientPacket { // packet private Coordinate target; private Coordinate origin; - private int moveMovement; + @SuppressWarnings("unused") + private MovementType type; + + public enum MovementType { + MOUSE(0x01), KEYBOARD(0x00); + + public final int id; + + MovementType(int id) { + this.id = id; + } + + public static MovementType fromID(int id) { + for (final MovementType type : values()) { + if (type.id == id) + return type; + } + return null; + } + } @Inject public CharacterRequestMovePacket(CharacterService charService) { @@ -65,7 +84,7 @@ public class CharacterRequestMovePacket extends AbstractClientPacket { // seems that L2Walker does not send this if (buffer.readableBytes() >= 4) { // 0 keyboard, 1 mouse - this.moveMovement = buffer.readInt(); + this.type = MovementType.fromID(buffer.readInt()); } } diff --git a/src/main/java/com/l2jserver/model/template/capability/OutgoingDamageIntercept.java b/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestOpenMap.java similarity index 55% rename from src/main/java/com/l2jserver/model/template/capability/OutgoingDamageIntercept.java rename to src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestOpenMap.java index 7ed678b11..7c00bc9eb 100644 --- a/src/main/java/com/l2jserver/model/template/capability/OutgoingDamageIntercept.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/CharacterRequestOpenMap.java @@ -14,15 +14,31 @@ * You should have received a copy of the GNU General Public License * along with l2jserver. If not, see . */ -package com.l2jserver.model.template.capability; +package com.l2jserver.game.net.packet.client; -import com.l2jserver.model.world.capability.Damagable; +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.CharacterOpenMap; /** - * Indicates that an template has the ability to intercept outgoing damage. + * Executes an bypass command * * @author Rogiel */ -public interface OutgoingDamageIntercept extends TemplateCapability { - void interceptOutgoingDamage(Damagable target); +public class CharacterRequestOpenMap extends AbstractClientPacket { + /** + * The packet OPCODE + */ + public static final int OPCODE = 0x6c; + + @Override + public void read(Lineage2Connection conn, ChannelBuffer buffer) { + } + + @Override + public void process(final Lineage2Connection conn) { + conn.write(new CharacterOpenMap(1665)); + } } diff --git a/src/main/java/com/l2jserver/game/net/packet/server/ActorChatMessagePacket.java b/src/main/java/com/l2jserver/game/net/packet/server/ActorChatMessagePacket.java index 9fb5a3aa9..644c25ffd 100644 --- a/src/main/java/com/l2jserver/game/net/packet/server/ActorChatMessagePacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/server/ActorChatMessagePacket.java @@ -22,6 +22,7 @@ import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.packet.AbstractServerPacket; import com.l2jserver.game.net.packet.server.CharacterCreateFailPacket.Reason; import com.l2jserver.model.world.L2Character; +import com.l2jserver.model.world.capability.Actor; import com.l2jserver.service.game.chat.ChatMessageDestination; import com.l2jserver.util.BufferUtils; @@ -39,27 +40,51 @@ public class ActorChatMessagePacket extends AbstractServerPacket { public static final int OPCODE = 0x4a; /** - * The selected character + * The sending actor + */ + private final Actor actor; + /** + * The message destination */ - private final L2Character character; private ChatMessageDestination destination; + /** + * The message + */ private String message = null; + /** + * The message ID + */ private int messageID = 0; - public ActorChatMessagePacket(L2Character character, + public ActorChatMessagePacket(Actor character, ChatMessageDestination destination, String message) { super(OPCODE); - this.character = character; + this.actor = character; this.destination = destination; this.message = message; } + public ActorChatMessagePacket(Actor actor, + ChatMessageDestination destination, int messageID) { + super(OPCODE); + this.actor = actor; + this.destination = destination; + this.messageID = messageID; + } + @Override public void write(Lineage2Connection conn, ChannelBuffer buffer) { - buffer.writeInt(character.getID().getID()); + buffer.writeInt(actor.getID().getID()); buffer.writeInt(destination.id); - BufferUtils.writeString(buffer, character.getName()); // TODO can be - // char id! - BufferUtils.writeString(buffer, message); // TODO can be msg id + if (actor instanceof L2Character) { + BufferUtils.writeString(buffer, ((L2Character) actor).getName()); + } else { + buffer.writeInt(actor.getID().getID()); + } + if (message != null) { + BufferUtils.writeString(buffer, message); + } else { + buffer.writeInt(messageID); + } } } diff --git a/src/main/java/com/l2jserver/game/net/packet/server/CharacterOpenMap.java b/src/main/java/com/l2jserver/game/net/packet/server/CharacterOpenMap.java new file mode 100644 index 000000000..22ab00bd3 --- /dev/null +++ b/src/main/java/com/l2jserver/game/net/packet/server/CharacterOpenMap.java @@ -0,0 +1,50 @@ +/* + * 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.server; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.l2jserver.game.net.Lineage2Connection; +import com.l2jserver.game.net.packet.AbstractServerPacket; + +/** + * An packet informing that the character was created with success. + * + * @author Rogiel + */ +public class CharacterOpenMap extends AbstractServerPacket { + /** + * The packet OPCODE + */ + public static final int OPCODE = 0xa3; + + /** + * The map ID + */ + private final int mapID; + + public CharacterOpenMap(int mapID) { + super(OPCODE); + this.mapID = mapID; + } + + @Override + public void write(Lineage2Connection conn, ChannelBuffer buffer) { + buffer.writeInt(mapID); + buffer.writeByte(0x00); // seven signs period + } +} diff --git a/src/main/java/com/l2jserver/model/template/ItemTemplate.java b/src/main/java/com/l2jserver/model/template/ItemTemplate.java index 4b962cd4a..3a5dfbf05 100644 --- a/src/main/java/com/l2jserver/model/template/ItemTemplate.java +++ b/src/main/java/com/l2jserver/model/template/ItemTemplate.java @@ -19,6 +19,9 @@ package com.l2jserver.model.template; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.inject.Inject; +import com.l2jserver.game.net.Lineage2Connection; +import com.l2jserver.model.id.object.CharacterID; import com.l2jserver.model.id.template.ItemTemplateID; import com.l2jserver.model.template.capability.Depositable; import com.l2jserver.model.template.capability.Dropable; @@ -27,6 +30,8 @@ import com.l2jserver.model.template.capability.Sellable; import com.l2jserver.model.template.capability.Tradable; import com.l2jserver.model.template.capability.Usable; import com.l2jserver.model.world.Item; +import com.l2jserver.model.world.L2Character; +import com.l2jserver.service.network.NetworkService; /** * Template for an {@link Item} @@ -40,6 +45,9 @@ public abstract class ItemTemplate extends AbstractTemplate { private static final Logger log = LoggerFactory .getLogger(ItemTemplate.class); + @Inject + protected NetworkService networkService; + protected int weight = 0; protected int price = 0; protected String icon; @@ -68,6 +76,16 @@ public abstract class ItemTemplate extends AbstractTemplate { return new Item(this.getID()); } + public final void use(Item item, L2Character character) { + final CharacterID id = character.getID(); + final Lineage2Connection conn = networkService.discover(id); + this.use(item, character, conn); + } + + protected void use(Item item, L2Character character, Lineage2Connection conn) { + conn.sendActionFailed(); + } + public void stack(Item... object) { } diff --git a/src/main/java/com/l2jserver/model/template/NPCTemplate.java b/src/main/java/com/l2jserver/model/template/NPCTemplate.java index fd94853de..9debcfae5 100644 --- a/src/main/java/com/l2jserver/model/template/NPCTemplate.java +++ b/src/main/java/com/l2jserver/model/template/NPCTemplate.java @@ -16,6 +16,7 @@ */ package com.l2jserver.model.template; +import com.google.common.base.Preconditions; import com.google.inject.Inject; import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.packet.server.NPCHtmlMessagePacket; @@ -32,7 +33,6 @@ import com.l2jserver.service.network.NetworkService; import com.l2jserver.util.calculator.Calculator; import com.l2jserver.util.exception.L2Exception; import com.l2jserver.util.html.markup.HtmlTemplate; -import com.l2jserver.util.html.markup.MarkupTag; /** * Template for {@link NPC} @@ -106,6 +106,10 @@ public abstract class NPCTemplate extends ActorTemplate { */ public void action(NPC npc, L2Character character, String... args) throws L2Exception { + Preconditions.checkNotNull(npc, "npc"); + Preconditions.checkNotNull(character, "character"); + Preconditions.checkNotNull(args, "args"); + final Lineage2Connection conn = networkService.discover(character .getID()); if (conn == null) @@ -119,17 +123,40 @@ public abstract class NPCTemplate extends ActorTemplate { return; } - // generate not implemented message - final HtmlTemplate template = new HtmlTemplate(name) { - @Override - public void build(MarkupTag body) { - body.text("The NPC ${name} is not yet implemented!", "ff0000") - .p().p(); - body.addLink("Click me!", "test"); + if (args.length == 0 || args[0].equals("Chat")) + talk(npc, character, conn, args); + } + + /** + * Talks with this NPC + * + * @param npc + * the npc + * @param character + * the character + * @param conn + * the lineage 2 connection + * @param args + * the action arguments + * @throws L2Exception + */ + public void talk(NPC npc, L2Character character, Lineage2Connection conn, + String... args) throws L2Exception { + if (args.length == 0 || (args.length >= 1 && args[0].equals("Chat"))) { + String name = ""; + if (args.length == 2) + name = args[1]; + final HtmlTemplate template = getChat(name); + if (template != null) { + template.register("npcid", npc.getID().getID()); + conn.write(new NPCHtmlMessagePacket(npc, template)); } - }; - template.register("name", name); - conn.write(new NPCHtmlMessagePacket(npc, template)); + } + conn.sendActionFailed(); + } + + protected HtmlTemplate getChat(String name) throws L2Exception { + return null; } /** diff --git a/src/main/java/com/l2jserver/model/template/item/ArmorTemplate.java b/src/main/java/com/l2jserver/model/template/item/ArmorTemplate.java index 1bc2c29c4..141a8ef20 100644 --- a/src/main/java/com/l2jserver/model/template/item/ArmorTemplate.java +++ b/src/main/java/com/l2jserver/model/template/item/ArmorTemplate.java @@ -19,7 +19,6 @@ package com.l2jserver.model.template.item; import com.l2jserver.model.id.template.ItemTemplateID; import com.l2jserver.model.template.ItemTemplate; import com.l2jserver.model.template.capability.Defendable; -import com.l2jserver.model.template.capability.IncomingDamageIntercept; import com.l2jserver.model.world.Item; /** @@ -27,8 +26,7 @@ import com.l2jserver.model.world.Item; * * @author Rogiel */ -public abstract class ArmorTemplate extends ItemTemplate implements Defendable, - IncomingDamageIntercept { +public abstract class ArmorTemplate extends ItemTemplate implements Defendable { public ArmorTemplate(ItemTemplateID id) { super(id); } diff --git a/src/main/java/com/l2jserver/model/template/capability/IncomingDamageIntercept.java b/src/main/java/com/l2jserver/model/template/item/EtcItemTemplate.java similarity index 65% rename from src/main/java/com/l2jserver/model/template/capability/IncomingDamageIntercept.java rename to src/main/java/com/l2jserver/model/template/item/EtcItemTemplate.java index 3edd38acd..7773fb62a 100644 --- a/src/main/java/com/l2jserver/model/template/capability/IncomingDamageIntercept.java +++ b/src/main/java/com/l2jserver/model/template/item/EtcItemTemplate.java @@ -14,16 +14,19 @@ * You should have received a copy of the GNU General Public License * along with l2jserver. If not, see . */ -package com.l2jserver.model.template.capability; +package com.l2jserver.model.template.item; -import com.l2jserver.model.world.capability.Damagable; +import com.l2jserver.model.id.template.ItemTemplateID; +import com.l2jserver.model.template.ItemTemplate; +import com.l2jserver.model.world.Item; /** - * Indicates that an template has the ability to intercept incoming damage. + * Template for general items {@link Item} * * @author Rogiel - * */ -public interface IncomingDamageIntercept extends TemplateCapability { - void interceptIncomingDamage(Damagable target); +public abstract class EtcItemTemplate extends ItemTemplate { + public EtcItemTemplate(ItemTemplateID id, String icon, ItemMaterial material) { + super(id, icon, material); + } } diff --git a/src/main/java/com/l2jserver/model/template/item/SkillEtcItemTemplate.java b/src/main/java/com/l2jserver/model/template/item/SkillEtcItemTemplate.java new file mode 100644 index 000000000..48e3c52d6 --- /dev/null +++ b/src/main/java/com/l2jserver/model/template/item/SkillEtcItemTemplate.java @@ -0,0 +1,51 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.model.template.item; + +import com.l2jserver.game.net.Lineage2Connection; +import com.l2jserver.model.id.template.ItemTemplateID; +import com.l2jserver.model.id.template.SkillTemplateID; +import com.l2jserver.model.template.ItemTemplate; +import com.l2jserver.model.world.Item; +import com.l2jserver.model.world.L2Character; + +/** + * Template for general items {@link Item} + * + * @author Rogiel + */ +public abstract class SkillEtcItemTemplate extends ItemTemplate { + protected SkillTemplateID skill; + + public SkillEtcItemTemplate(ItemTemplateID id, String icon, + ItemMaterial material, SkillTemplateID skill) { + super(id, icon, material); + } + + @Override + protected void use(Item item, L2Character character, Lineage2Connection conn) { + + super.use(item, character, conn); + } + + /** + * @return the skill + */ + public SkillTemplateID getSkill() { + return skill; + } +} diff --git a/src/main/java/com/l2jserver/model/template/npc/MonsterNPCTemplate.java b/src/main/java/com/l2jserver/model/template/npc/MonsterNPCTemplate.java index 0ee11feec..66391d433 100644 --- a/src/main/java/com/l2jserver/model/template/npc/MonsterNPCTemplate.java +++ b/src/main/java/com/l2jserver/model/template/npc/MonsterNPCTemplate.java @@ -18,6 +18,9 @@ package com.l2jserver.model.template.npc; import com.l2jserver.model.id.template.NPCTemplateID; import com.l2jserver.model.template.NPCTemplate; +import com.l2jserver.util.exception.L2Exception; +import com.l2jserver.util.html.markup.HtmlTemplate; +import com.l2jserver.util.html.markup.MarkupTag; /** * @author Rogiel @@ -35,4 +38,14 @@ public class MonsterNPCTemplate extends NPCTemplate { protected MonsterNPCTemplate(NPCTemplateID id) { super(id); } + + @Override + protected HtmlTemplate getChat(String name) throws L2Exception { + return new HtmlTemplate() { + @Override + protected void build(MarkupTag body) { + body.text("Sorry, but you can't interact with me yet."); + } + }; + } } diff --git a/src/main/java/com/l2jserver/model/template/npc/TeleporterNPCTemplate.java b/src/main/java/com/l2jserver/model/template/npc/TeleporterNPCTemplate.java index 65d1f3cd2..85d14229b 100644 --- a/src/main/java/com/l2jserver/model/template/npc/TeleporterNPCTemplate.java +++ b/src/main/java/com/l2jserver/model/template/npc/TeleporterNPCTemplate.java @@ -20,7 +20,6 @@ import java.util.List; import com.google.inject.Inject; import com.l2jserver.game.net.Lineage2Connection; -import com.l2jserver.game.net.packet.server.NPCHtmlMessagePacket; import com.l2jserver.model.id.template.NPCTemplateID; import com.l2jserver.model.template.NPCTemplate; import com.l2jserver.model.world.L2Character; @@ -100,40 +99,44 @@ public class TeleporterNPCTemplate extends NPCTemplate { @Override public void action(NPC npc, L2Character character, String... args) throws L2Exception { - talk(npc, character, args); - } - - public void talk(NPC npc, L2Character character, String... args) - throws NotSpawnedServiceException { final Lineage2Connection conn = networkService.discover(character .getID()); - if (args.length == 0) { - final HtmlTemplate template = new HtmlTemplate() { + if (args.length >= 2 && args[0].equals("goto")) { + teleport(npc, character, conn, args[1]); + } + super.action(npc, character, args); + } + + @Override + protected HtmlTemplate getChat(String name) throws L2Exception { + if (name.equals("") || name.equals("teleport")) { + return new HtmlTemplate() { @Override protected void build(MarkupTag body) { body.textcode(556).br().br(); - // TODO this should not be hard coded! int i = 0; for (final TeleportationMetadata location : locations) { body.addLink( location.name + " - " + location.price - + " Adena", - "npc_${npcid}_teleport " + i++).br(); + + " Adena", "npc_${npcid}_goto " + i++) + .br(); } } }; - template.register("npcid", String.valueOf(npc.getID().getID())); - conn.write(new NPCHtmlMessagePacket(npc, template)); - } else if (args[0].equals("teleport")) { - final int location = Integer.parseInt(args[1]); - final TeleportationMetadata metadata = locations.get(location); - if (metadata == null) { - conn.sendActionFailed(); - return; - } - spawnService.teleport(character, metadata.point); } - conn.sendActionFailed(); + return super.getChat(name); + } + + protected void teleport(NPC npc, L2Character character, + Lineage2Connection conn, String name) + throws NotSpawnedServiceException { + final int location = Integer.parseInt(name); + final TeleportationMetadata metadata = locations.get(location); + if (metadata == null) { + conn.sendActionFailed(); + return; + } + spawnService.teleport(character, metadata.point); } protected void addLocation(String name, Coordinate coordinate, int price) { diff --git a/src/main/java/com/l2jserver/model/world/L2Character.java b/src/main/java/com/l2jserver/model/world/L2Character.java index 21866314d..cdce67e9b 100644 --- a/src/main/java/com/l2jserver/model/world/L2Character.java +++ b/src/main/java/com/l2jserver/model/world/L2Character.java @@ -125,12 +125,12 @@ public class L2Character extends Player { */ private ActorID targetID; /** - * State if the player is being teleported + * State of the character. Will be null if it is idle */ private CharacterState state; public enum CharacterState { - TELEPORTING; + TELEPORTING, CASTING, ATTACKING, MOVING; } /** diff --git a/src/main/java/com/l2jserver/model/world/character/event/CharacterRunningEvent.java b/src/main/java/com/l2jserver/model/world/character/event/CharacterRunningEvent.java new file mode 100644 index 000000000..f0939d70d --- /dev/null +++ b/src/main/java/com/l2jserver/model/world/character/event/CharacterRunningEvent.java @@ -0,0 +1,70 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.model.world.character.event; + +import com.l2jserver.model.id.ObjectID; +import com.l2jserver.model.world.L2Character; +import com.l2jserver.model.world.Player; +import com.l2jserver.model.world.WorldObject; +import com.l2jserver.model.world.capability.Actor; + +/** + * Event triggered once a character starts running + * + * @author Rogiel + */ +public class CharacterRunningEvent implements CharacterEvent { + /** + * The character that is logging in + */ + private final L2Character character; + + /** + * Creates a new instance + * + * @param character + * the character + */ + public CharacterRunningEvent(L2Character character) { + this.character = character; + } + + @Override + public Player getPlayer() { + return character; + } + + @Override + public Actor getActor() { + return character; + } + + @Override + public WorldObject getObject() { + return character; + } + + @Override + public L2Character getCharacter() { + return character; + } + + @Override + public ObjectID[] getDispatchableObjects() { + return new ObjectID[] { character.getID() }; + } +} diff --git a/src/main/java/com/l2jserver/model/world/character/event/CharacterWalkingEvent.java b/src/main/java/com/l2jserver/model/world/character/event/CharacterWalkingEvent.java new file mode 100644 index 000000000..18cdd349b --- /dev/null +++ b/src/main/java/com/l2jserver/model/world/character/event/CharacterWalkingEvent.java @@ -0,0 +1,70 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.model.world.character.event; + +import com.l2jserver.model.id.ObjectID; +import com.l2jserver.model.world.L2Character; +import com.l2jserver.model.world.Player; +import com.l2jserver.model.world.WorldObject; +import com.l2jserver.model.world.capability.Actor; + +/** + * Event triggered once a character starts walking + * + * @author Rogiel + */ +public class CharacterWalkingEvent implements CharacterEvent { + /** + * The character that is logging in + */ + private final L2Character character; + + /** + * Creates a new instance + * + * @param character + * the character + */ + public CharacterWalkingEvent(L2Character character) { + this.character = character; + } + + @Override + public Player getPlayer() { + return character; + } + + @Override + public Actor getActor() { + return character; + } + + @Override + public WorldObject getObject() { + return character; + } + + @Override + public L2Character getCharacter() { + return character; + } + + @Override + public ObjectID[] getDispatchableObjects() { + return new ObjectID[] { character.getID() }; + } +} diff --git a/src/main/java/com/l2jserver/service/ServiceException.java b/src/main/java/com/l2jserver/service/ServiceException.java index e7cc38b24..646e1abd9 100644 --- a/src/main/java/com/l2jserver/service/ServiceException.java +++ b/src/main/java/com/l2jserver/service/ServiceException.java @@ -23,7 +23,7 @@ import com.l2jserver.util.exception.L2Exception; * * @author Rogiel */ -public class ServiceException extends L2Exception { +public abstract class ServiceException extends L2Exception { private static final long serialVersionUID = 1L; public ServiceException() { diff --git a/src/main/java/com/l2jserver/service/game/character/ActorIsNotAttackableServiceException.java b/src/main/java/com/l2jserver/service/game/character/ActorIsNotAttackableServiceException.java new file mode 100644 index 000000000..6a670e86b --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/character/ActorIsNotAttackableServiceException.java @@ -0,0 +1,14 @@ +package com.l2jserver.service.game.character; + +import com.l2jserver.model.world.capability.Actor; + +/** + * Exception thrown when the character is trying to attack an {@link Actor} that + * is not attackable + * + * @author Rogiel + */ +public class ActorIsNotAttackableServiceException extends + CharacterServiceException { + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/l2jserver/service/game/character/CharacterAlreadyRunningServiceException.java b/src/main/java/com/l2jserver/service/game/character/CharacterAlreadyRunningServiceException.java new file mode 100644 index 000000000..488941761 --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/character/CharacterAlreadyRunningServiceException.java @@ -0,0 +1,11 @@ +package com.l2jserver.service.game.character; + +/** + * Exception thrown when the character is already running + * + * @author Rogiel + */ +public class CharacterAlreadyRunningServiceException extends + CharacterServiceException { + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/l2jserver/service/game/character/CharacterAlreadyWalkingServiceException.java b/src/main/java/com/l2jserver/service/game/character/CharacterAlreadyWalkingServiceException.java new file mode 100644 index 000000000..e3e3adb0f --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/character/CharacterAlreadyWalkingServiceException.java @@ -0,0 +1,11 @@ +package com.l2jserver.service.game.character; + +/** + * Exception thrown when the character is already walking + * + * @author Rogiel + */ +public class CharacterAlreadyWalkingServiceException extends + CharacterServiceException { + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/l2jserver/service/game/character/CharacterService.java b/src/main/java/com/l2jserver/service/game/character/CharacterService.java index 2efb439c1..b76055c87 100644 --- a/src/main/java/com/l2jserver/service/game/character/CharacterService.java +++ b/src/main/java/com/l2jserver/service/game/character/CharacterService.java @@ -77,9 +77,12 @@ public interface CharacterService extends Service { * the target * @throws CannotSetTargetServiceException * if target cannot be set + * @throws ActorIsNotAttackableServiceException + * if the target is not attackable */ void attack(L2Character character, Actor target) - throws CannotSetTargetServiceException; + throws CannotSetTargetServiceException, + ActorIsNotAttackableServiceException; /** * Informs that an given character is appearing in the world. @@ -152,14 +155,20 @@ public interface CharacterService extends Service { * * @param character * the character + * @throws CharacterAlreadyWalkingServiceException + * if the character is already walking */ - void walk(L2Character character); + void walk(L2Character character) + throws CharacterAlreadyWalkingServiceException; /** * Set the character to run mode * * @param character * the character + * @throws CharacterAlreadyRunningServiceException + * if the character is already running */ - void run(L2Character character); + void run(L2Character character) + throws CharacterAlreadyRunningServiceException; } diff --git a/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java b/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java index 04a9824ba..fd1d0b5d1 100644 --- a/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java +++ b/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java @@ -21,7 +21,6 @@ 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; import com.l2jserver.game.net.packet.server.ActorChatMessagePacket; import com.l2jserver.game.net.packet.server.ActorMovementPacket; import com.l2jserver.game.net.packet.server.CharacterInformationExtraPacket; @@ -35,6 +34,7 @@ import com.l2jserver.model.id.object.CharacterID; import com.l2jserver.model.template.NPCTemplate; import com.l2jserver.model.world.L2Character; import com.l2jserver.model.world.L2Character.CharacterMoveType; +import com.l2jserver.model.world.L2Character.CharacterState; import com.l2jserver.model.world.NPC; import com.l2jserver.model.world.WorldObject; import com.l2jserver.model.world.capability.Actor; @@ -44,8 +44,10 @@ import com.l2jserver.model.world.character.event.CharacterEvent; import com.l2jserver.model.world.character.event.CharacterLeaveWorldEvent; import com.l2jserver.model.world.character.event.CharacterListener; import com.l2jserver.model.world.character.event.CharacterMoveEvent; +import com.l2jserver.model.world.character.event.CharacterRunningEvent; import com.l2jserver.model.world.character.event.CharacterTargetDeselectedEvent; import com.l2jserver.model.world.character.event.CharacterTargetSelectedEvent; +import com.l2jserver.model.world.character.event.CharacterWalkingEvent; import com.l2jserver.model.world.npc.event.NPCSpawnEvent; import com.l2jserver.model.world.player.event.PlayerTeleportedEvent; import com.l2jserver.service.AbstractService; @@ -162,26 +164,25 @@ public class CharacterServiceImpl extends AbstractService implements protected boolean dispatch(WorldEvent e, Positionable object) { if (e instanceof NPCSpawnEvent) { conn.write(new NPCInformationPacket((NPC) object)); - } else if (e instanceof CharacterEnterWorldEvent) { - // conn.write(packet) - // TODO char broadcast } else if (e instanceof CharacterMoveEvent) { final CharacterMoveEvent evt = (CharacterMoveEvent) e; if (object.equals(character)) return true; conn.write(new ActorMovementPacket((L2Character) object, evt.getPoint().getCoordinate())); - } else if (e instanceof PlayerTeleportedEvent) { + } else if (e instanceof PlayerTeleportedEvent + || e instanceof CharacterEnterWorldEvent) { // TODO this should not be here! - System.out.println(((PlayerTeleportedEvent) e).getPoint() - .getCoordinate()); - System.out.println(character.getPosition()); for (final WorldObject o : worldService .iterable(new KnownListFilter(character))) { if (o instanceof NPC) { conn.write(new NPCInformationPacket((NPC) o)); } } + } else if (e instanceof CharacterWalkingEvent + || e instanceof CharacterRunningEvent) { + conn.write(new CharacterMovementTypePacket( + ((CharacterWalkingEvent) e).getCharacter())); } // keep listener alive return true; @@ -227,7 +228,11 @@ public class CharacterServiceImpl extends AbstractService implements conn.sendMessage("Please note that many of the features are not yet implemented."); // characters start in run mode - run(character); + try { + run(character); + } catch (CharacterAlreadyRunningServiceException e1) { + // we can ignore this one + } // broadcast knownlist -- trashy implementation // TODO should be moved to world service or a newly created broadcast @@ -295,7 +300,7 @@ public class CharacterServiceImpl extends AbstractService implements @Override public void attack(L2Character character, Actor target) - throws CannotSetTargetServiceException { + throws CannotSetTargetServiceException, ActorIsNotAttackableServiceException { Preconditions.checkNotNull(character, "character"); Preconditions.checkNotNull(target, "target"); final CharacterID id = character.getID(); @@ -305,8 +310,7 @@ public class CharacterServiceImpl extends AbstractService implements final NPC npc = (NPC) target; final NPCTemplate template = npc.getTemplate(); if (!template.isAttackable()) { - conn.write(ActionFailedPacket.SHARED_INSTANCE); - return; + throw new ActorIsNotAttackableServiceException(); } // first try to target this, if it is not already target(character, target); @@ -356,6 +360,8 @@ public class CharacterServiceImpl extends AbstractService implements // we don't set the character coordinate here, this will be done by // validation packets, sent by client + character.setState(CharacterState.MOVING); + // for now, let's just write the packet, we don't have much validation // to be done yet. With character validation packet, another packet of // these will be broadcasted. @@ -380,36 +386,39 @@ public class CharacterServiceImpl extends AbstractService implements // validation just before teleport packet return; character.setPoint(point); + character.setState(CharacterState.MOVING); eventDispatcher.dispatch(new CharacterMoveEvent(character, point)); } @Override - public void walk(L2Character character) { + public void walk(L2Character character) + throws CharacterAlreadyWalkingServiceException { Preconditions.checkNotNull(character, "character"); final CharacterID id = character.getID(); final Lineage2Connection conn = networkService.discover(id); // test if character is running - if (character.getMoveType() == CharacterMoveType.RUN) { - // if running set mode to walk and broadcast packet - character.setMoveType(CharacterMoveType.WALK); - conn.broadcast(new CharacterMovementTypePacket(character)); - // TODO dispatch move change type event - } - // TODO we need to throw an exception if character is not running + if (character.getMoveType() == CharacterMoveType.WALK) + throw new CharacterAlreadyWalkingServiceException(); + // if running set mode to walk and broadcast packet + character.setMoveType(CharacterMoveType.WALK); + + eventDispatcher.dispatch(new CharacterWalkingEvent(character)); + conn.write(new CharacterMovementTypePacket(character)); } @Override - public void run(L2Character character) { + public void run(L2Character character) + throws CharacterAlreadyRunningServiceException { Preconditions.checkNotNull(character, "character"); final CharacterID id = character.getID(); final Lineage2Connection conn = networkService.discover(id); // test if character is walking - if (character.getMoveType() == CharacterMoveType.WALK) { - // if running walking mode to run and broadcast packet - character.setMoveType(CharacterMoveType.RUN); - conn.broadcast(new CharacterMovementTypePacket(character)); - // TODO dispatch move change type event - } - // TODO we need to throw an exception if character is not walking + if (character.getMoveType() == CharacterMoveType.RUN) + throw new CharacterAlreadyRunningServiceException(); + // if running walking mode to run and broadcast packet + character.setMoveType(CharacterMoveType.RUN); + + eventDispatcher.dispatch(new CharacterRunningEvent(character)); + conn.write(new CharacterMovementTypePacket(character)); } } diff --git a/src/main/java/com/l2jserver/util/exception/L2Exception.java b/src/main/java/com/l2jserver/util/exception/L2Exception.java index b841c826f..f1d8e6b02 100644 --- a/src/main/java/com/l2jserver/util/exception/L2Exception.java +++ b/src/main/java/com/l2jserver/util/exception/L2Exception.java @@ -21,7 +21,7 @@ package com.l2jserver.util.exception; * * @author Rogiel */ -public class L2Exception extends Exception { +public abstract class L2Exception extends Exception { /** * Default Serial Version UID */ @@ -54,4 +54,15 @@ public class L2Exception extends Exception { public L2Exception(Throwable cause) { super(cause); } + + // /** + // * Each {@link L2Exception} has an {@link SystemMessage} attacked to it. + // It + // * is an recommendation of which message should be sent to + // the + // * client in case the exception is thrown. + // * + // * @return the recommended system message + // */ + // public abstract SystemMessage getSystemMessage(); } diff --git a/src/main/java/com/l2jserver/util/html/markup/HtmlTemplate.java b/src/main/java/com/l2jserver/util/html/markup/HtmlTemplate.java index 78270872c..523b7d069 100644 --- a/src/main/java/com/l2jserver/util/html/markup/HtmlTemplate.java +++ b/src/main/java/com/l2jserver/util/html/markup/HtmlTemplate.java @@ -116,6 +116,18 @@ public abstract class HtmlTemplate { public void register(String name, String value) { variables.put(name, value); } + + /** + * Register an variable for this template + * + * @param name + * the name + * @param value + * the value + */ + public void register(String name, int value) { + variables.put(name, Integer.toString(value)); + } /** * Creates a new {@link Html} object using the {@link HtmlTemplate} provided