package net.scapeemulator.game.update;
import java.util.HashMap;
import java.util.Map;
import net.scapeemulator.game.model.mob.Direction;
import net.scapeemulator.game.model.npc.NPC;
import net.scapeemulator.game.msg.impl.NpcUpdateMessage;
import net.scapeemulator.game.net.game.DataOrder;
import net.scapeemulator.game.net.game.DataType;
import net.scapeemulator.game.net.game.GameFrameBuilder;
public abstract class NpcDescriptor {
public static NpcDescriptor create(NPC npc) {
Direction firstDirection = npc.getFirstDirection();
Direction secondDirection = npc.getSecondDirection();
if (firstDirection == Direction.NONE)
return new IdleNpcDescriptor(npc);
else if (secondDirection == Direction.NONE)
return new WalkNpcDescriptor(npc);
else
return new RunNpcDescriptor(npc);
}
private final Map<Class<? extends NpcBlock>, NpcBlock> blocks = new HashMap<>();
public NpcDescriptor(NPC npc) {
if (npc.isHitOneUpdated())
addBlock(new HitOneNpcBlock(npc));
if (npc.isHitTwoUpdated())
addBlock(new HitTwoNpcBlock(npc));
if (npc.isAnimationUpdated())
addBlock(new AnimationNpcBlock(npc));
if (npc.isTurnToTargetUpdated())
addBlock(new TurnToMobNpcBlock(npc));
if (npc.isSpotAnimationUpdated())
addBlock(new SpotAnimationNpcBlock(npc));
if (npc.isChangingType())
addBlock(new ChangeTypeNpcBlock(npc));
if (npc.isChatForced())
addBlock(new ForceChatNpcBlock(npc));
if (npc.isTurnToPositionUpdated())
addBlock(new TurnToPositionNpcBlock(npc));
}
private void addBlock(NpcBlock block) {
blocks.put(block.getClass(), block);
}
public boolean isBlockUpdatedRequired() {
return !blocks.isEmpty();
}
public void encode(NpcUpdateMessage message, GameFrameBuilder builder, GameFrameBuilder blockBuilder) {
encodeDescriptor(message, builder, blockBuilder);
if (isBlockUpdatedRequired()) {
int flags = 0;
for (NpcBlock block : blocks.values())
flags |= block.getFlag();
if (flags > 0xFF) {
flags |= 0x8;
blockBuilder.put(DataType.SHORT, DataOrder.LITTLE, flags);
} else {
blockBuilder.put(DataType.BYTE, flags);
}
encodeBlock(message, blockBuilder, HitOneNpcBlock.class);
encodeBlock(message, blockBuilder, HitTwoNpcBlock.class);
encodeBlock(message, blockBuilder, AnimationNpcBlock.class);
encodeBlock(message, blockBuilder, TurnToMobNpcBlock.class);
encodeBlock(message, blockBuilder, SpotAnimationNpcBlock.class);
encodeBlock(message, blockBuilder, ChangeTypeNpcBlock.class);
encodeBlock(message, blockBuilder, ForceChatNpcBlock.class);
// encodeBlock(message, blockBuilder, ?????.class); // 0x100
encodeBlock(message, blockBuilder, TurnToPositionNpcBlock.class);
}
}
private void encodeBlock(NpcUpdateMessage message, GameFrameBuilder builder, Class<? extends NpcBlock> type) {
NpcBlock block = blocks.get(type);
if (block != null)
block.encode(message, builder);
}
public abstract void encodeDescriptor(NpcUpdateMessage message, GameFrameBuilder builder, GameFrameBuilder blockBuilder);
}