Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package net.zaros.util.task.impl;
- import java.util.Iterator;
- import net.zaros.GameEngine;
- import net.zaros.model.Entity;
- import net.zaros.model.Item;
- import net.zaros.model.Location;
- import net.zaros.model.UpdateFlags;
- import net.zaros.model.World;
- import net.zaros.model.UpdateFlags.UpdateFlag;
- import net.zaros.model.container.Container;
- import net.zaros.model.container.Equipment;
- import net.zaros.model.container.Equipment.EquipmentType;
- import net.zaros.model.player.Appearance;
- import net.zaros.model.player.ChatMessage;
- import net.zaros.model.player.Player;
- import net.zaros.net.packet.Packet;
- import net.zaros.net.packet.PacketBuilder;
- import net.zaros.net.packet.out.SendMapRegionPacket;
- import net.zaros.util.task.Task;
- /**
- * A task which creates and sends the player update block.
- *
- * @author Graham Edgecombe
- *
- */
- public class PlayerUpdateTask implements Task {
- /**
- * The player.
- */
- private Player player;
- /**
- * Creates an update task.
- *
- * @param player
- * The player.
- */
- public PlayerUpdateTask(Player player) {
- this.player = player;
- }
- @Override
- public void execute(GameEngine context) {
- // long startTime = System.currentTimeMillis();
- /*
- * If the map region changed send the new one. We do this immediately as
- * the client can begin loading it before the actual packet is received.
- */
- if (player.isMapRegionChanging()) {
- player.write(new SendMapRegionPacket());
- }
- /*
- * The update block packet holds update blocks and is send after the
- * main packet.
- */
- PacketBuilder updateBlock = new PacketBuilder();
- /*
- * The main packet is written in bits instead of bytes and holds
- * information about the local list, players to add and remove, movement
- * and which updates are required.
- */
- PacketBuilder packet = new PacketBuilder(81, Packet.Type.VARIABLE_SHORT);
- packet.startBitAccess();
- /*
- * Updates this player.
- */
- updateThisPlayerMovement(packet);
- updatePlayer(updateBlock, player, false, true);
- /*
- * Write the current size of the player list.
- */
- packet.putBits(8, player.getLocalPlayers().size());
- /*
- * Iterate through the local player list.
- */
- for (Iterator<Player> it$ = player.getLocalPlayers().iterator(); it$.hasNext();) {
- /*
- * Get the next player.
- */
- Player otherPlayer = it$.next();
- /*
- * If the player should still be in our list.
- */
- if (World.getWorld().getPlayers().contains(otherPlayer) && !otherPlayer.isTeleporting() && otherPlayer.getLocation().isWithinDistance(player.getLocation())) {
- /*
- * Update the movement.
- */
- updatePlayerMovement(packet, otherPlayer);
- /*
- * Check if an update is required, and if so, send the update.
- */
- if (otherPlayer.getUpdateFlags().isUpdateRequired()) {
- updatePlayer(updateBlock, otherPlayer, false, false);
- }
- } else {
- /*
- * Otherwise, remove the player from the list.
- */
- it$.remove();
- /*
- * Tell the client to remove the player from the list.
- */
- packet.putBits(1, 1);
- packet.putBits(2, 3);
- }
- }
- /*
- * Loop through every player.
- */
- for (Player otherPlayer : World.getWorld().getRegionManager().getLocalPlayers(player)) {
- /*
- * Check if there is room left in the local list.
- */
- if (player.getLocalPlayers().size() >= 255) {
- /*
- * There is no more room left in the local list. We cannot add
- * more players, so we just ignore the extra ones. They will be
- * added as other players get removed.
- */
- break;
- }
- /*
- * If they should not be added ignore them.
- */
- if (otherPlayer == player || player.getLocalPlayers().contains(otherPlayer)) {
- continue;
- }
- /*
- * Add the player to the local list if it is within distance.
- */
- player.getLocalPlayers().add(otherPlayer);
- /*
- * Add the player in the packet.
- */
- addNewPlayer(packet, otherPlayer);
- /*
- * Update the player, forcing the appearance flag.
- */
- updatePlayer(updateBlock, otherPlayer, true, false);
- }
- /*
- * Check if the update block is not empty.
- */
- if (!updateBlock.isEmpty()) {
- /*
- * Write a magic id indicating an update block follows.
- */
- packet.putBits(11, 2047);
- packet.finishBitAccess();
- /*
- * Add the update block at the end of this packet.
- */
- packet.put(updateBlock.toPacket().getPayload());
- } else {
- /*
- * Terminate the packet normally.
- */
- packet.finishBitAccess();
- }
- /*
- * Write the packet.
- */
- player.write(packet.toPacket());
- // long endTime = System.currentTimeMillis() - startTime;
- // System.out.println(endTime + " : " +
- // World.getWorld().getPlayers().size());
- }
- /**
- * Updates a non-this player's movement.
- *
- * @param packet
- * The packet.
- * @param otherPlayer
- * The player.
- */
- public void updatePlayerMovement(PacketBuilder packet, Player otherPlayer) {
- /*
- * Check which type of movement took place.
- */
- if (otherPlayer.getSprites().getPrimarySprite() == -1) {
- /*
- * If no movement did, check if an update is required.
- */
- if (otherPlayer.getUpdateFlags().isUpdateRequired()) {
- /*
- * Signify that an update happened.
- */
- packet.putBits(1, 1);
- /*
- * Signify that there was no movement.
- */
- packet.putBits(2, 0);
- } else {
- /*
- * Signify that nothing changed.
- */
- packet.putBits(1, 0);
- }
- } else if (otherPlayer.getSprites().getSecondarySprite() == -1) {
- /*
- * The player moved but didn't run. Signify that an update is
- * required.
- */
- packet.putBits(1, 1);
- /*
- * Signify we moved one tile.
- */
- packet.putBits(2, 1);
- /*
- * Write the primary sprite (i.e. walk direction).
- */
- packet.putBits(3, otherPlayer.getSprites().getPrimarySprite());
- /*
- * Write a flag indicating if a block update happened.
- */
- packet.putBits(1, otherPlayer.getUpdateFlags().isUpdateRequired() ? 1 : 0);
- } else {
- /*
- * The player ran. Signify that an update happened.
- */
- packet.putBits(1, 1);
- /*
- * Signify that we moved two tiles.
- */
- packet.putBits(2, 2);
- /*
- * Write the primary sprite (i.e. walk direction).
- */
- packet.putBits(3, otherPlayer.getSprites().getPrimarySprite());
- /*
- * Write the secondary sprite (i.e. run direction).
- */
- packet.putBits(3, otherPlayer.getSprites().getSecondarySprite());
- /*
- * Write a flag indicating if a block update happened.
- */
- packet.putBits(1, otherPlayer.getUpdateFlags().isUpdateRequired() ? 1 : 0);
- }
- }
- /**
- * Adds a new player.
- *
- * @param packet
- * The packet.
- * @param otherPlayer
- * The player.
- */
- public void addNewPlayer(PacketBuilder packet, Player otherPlayer) {
- /*
- * Write the player index.
- */
- packet.putBits(11, otherPlayer.getIndex());
- /*
- * Write two flags here: the first indicates an update is required (this
- * is always true as we add the appearance after adding a player) and
- * the second to indicate we should discard client-side walk queues.
- */
- packet.putBits(1, 1);
- packet.putBits(1, 1);
- /*
- * Calculate the x and y offsets.
- */
- int yPos = otherPlayer.getLocation().getY() - player.getLocation().getY();
- int xPos = otherPlayer.getLocation().getX() - player.getLocation().getX();
- /*
- * Write the x and y offsets.
- */
- packet.putBits(5, yPos);
- packet.putBits(5, xPos);
- }
- private static void appendHit2Update(final Player p, final PacketBuilder updateBlock) {
- updateBlock.put((byte) p.getUpdateFlags().getDamage2());
- updateBlock.putByteS((byte) p.getUpdateFlags().getHitType2());
- updateBlock.put((byte) p.getSkills().getLevel(3));
- updateBlock.putByteC(p.getSkills().getLevelForExperience(3));
- }
- private static void appendHitUpdate(final Player p, final PacketBuilder updateBlock) {
- updateBlock.put((byte) p.getUpdateFlags().getDamage1());
- updateBlock.putByteA(p.getUpdateFlags().getHitType1());
- updateBlock.putByteC(p.getSkills().getLevel(3));
- updateBlock.put((byte) p.getSkills().getLevelForExperience(3));
- }
- /**
- * Updates a player.
- *
- * @param packet
- * The packet.
- * @param otherPlayer
- * The other player.
- * @param forceAppearance
- * The force appearance flag.
- * @param noChat
- * Indicates chat should not be relayed to this player.
- */
- public void updatePlayer(PacketBuilder packet, Player otherPlayer, boolean forceAppearance, boolean noChat) {
- /*
- * If no update is required and we don't have to force an appearance
- * update, don't write anything.
- */
- if (!otherPlayer.getUpdateFlags().isUpdateRequired() && !forceAppearance) {
- return;
- }
- /*
- * We can used the cached update block!
- */
- synchronized (otherPlayer) {
- if (otherPlayer.hasCachedUpdateBlock() && otherPlayer != player && !forceAppearance && !noChat) {
- packet.put(otherPlayer.getCachedUpdateBlock().getPayload().flip());
- return;
- }
- /*
- * We have to construct and cache our own block.
- */
- PacketBuilder block = new PacketBuilder();
- /*
- * Calculate the bitmask.
- */
- int mask = 0;
- final UpdateFlags flags = otherPlayer.getUpdateFlags();
- // TODO mask 0x400
- if (flags.get(UpdateFlag.GRAPHICS)) {
- mask |= 0x100;
- }
- if (flags.get(UpdateFlag.ANIMATION)) {
- mask |= 0x8;
- }
- if (flags.get(UpdateFlag.FORCED_CHAT)) {
- mask |= 0x4;
- }
- if (flags.get(UpdateFlag.CHAT) && !noChat) {
- mask |= 0x80;
- }
- if (flags.get(UpdateFlag.FACE_ENTITY)) {
- mask |= 0x1;
- }
- if (flags.get(UpdateFlag.APPEARANCE) || forceAppearance) {
- mask |= 0x10;
- }
- if (flags.get(UpdateFlag.FACE_COORDINATE)) {
- mask |= 0x2;
- }
- if (flags.get(UpdateFlag.HIT)) {
- mask |= 0x20;
- }
- if (flags.get(UpdateFlag.HIT_2)) {
- mask |= 0x200;
- }
- /*
- * Check if the bitmask would overflow a byte.
- */
- if (mask >= 0x100) {
- /*
- * Write it as a short and indicate we have done so.
- */
- mask |= 0x40;
- block.put((byte) (mask & 0xFF));
- block.put((byte) (mask >> 8));
- } else {
- /*
- * Write it as a byte.
- */
- block.put((byte) (mask));
- }
- /*
- * Append the appropriate updates.
- */
- if (flags.get(UpdateFlag.GRAPHICS)) {
- appendGraphicsUpdate(block, otherPlayer);
- }
- if (flags.get(UpdateFlag.ANIMATION)) {
- appendAnimationUpdate(block, otherPlayer);
- }
- if (flags.get(UpdateFlag.FORCED_CHAT)) {
- packet.putRS2String(otherPlayer.getUpdateFlags().getForcedMessage());
- }
- if (flags.get(UpdateFlag.CHAT) && !noChat) {
- appendChatUpdate(block, otherPlayer);
- }
- if (flags.get(UpdateFlag.FACE_ENTITY)) {
- Entity entity = otherPlayer.getInteractingEntity();
- block.putLEShort(entity == null ? -1 : entity.getClientIndex());
- }
- if (flags.get(UpdateFlag.APPEARANCE) || forceAppearance) {
- appendPlayerAppearanceUpdate(block, otherPlayer);
- }
- if (flags.get(UpdateFlag.FACE_COORDINATE)) {
- Location loc = otherPlayer.getFaceLocation();
- if (loc == null) {
- block.putLEShortA(0);
- block.putLEShort(0);
- } else {
- block.putLEShortA(loc.getX() * 2 + 1);
- block.putLEShort(loc.getY() * 2 + 1);
- }
- }
- if (flags.get(UpdateFlag.HIT)) {
- appendHitUpdate(otherPlayer, block);
- }
- if (flags.get(UpdateFlag.HIT_2)) {
- appendHit2Update(otherPlayer, block);
- }
- /*
- * Convert the block builder to a packet.
- */
- Packet blockPacket = block.toPacket();
- /*
- * Now it is over, cache the block if we can.
- */
- if (otherPlayer != player && !forceAppearance && !noChat) {
- otherPlayer.setCachedUpdateBlock(blockPacket);
- }
- /*
- * And finally append the block at the end.
- */
- packet.put(blockPacket.getPayload());
- }
- }
- /**
- * Appends an animation update.
- *
- * @param block
- * The update block.
- * @param otherPlayer
- * The player.
- */
- private void appendAnimationUpdate(PacketBuilder block, Player otherPlayer) {
- block.putLEShort(otherPlayer.getCurrentAnimation().getId());
- block.putByteC(otherPlayer.getCurrentAnimation().getDelay());
- }
- /**
- * Appends a graphics update.
- *
- * @param block
- * The update block.
- * @param otherPlayer
- * The player.
- */
- private void appendGraphicsUpdate(PacketBuilder block, Player otherPlayer) {
- block.putLEShort(otherPlayer.getCurrentGraphic().getId());
- block.putInt(otherPlayer.getCurrentGraphic().getDelay() | otherPlayer.getCurrentGraphic().getHeight() << 16);
- }
- /**
- * Appends a chat text update.
- *
- * @param packet
- * The packet.
- * @param otherPlayer
- * The player.
- */
- private void appendChatUpdate(PacketBuilder packet, Player otherPlayer) {
- ChatMessage cm = otherPlayer.getCurrentChatMessage();
- byte[] bytes = cm.getText();
- packet.putLEShort(((cm.getColour() & 0xFF) << 8) | (cm.getEffects() & 0xFF));
- packet.put((byte) otherPlayer.getRights().toInteger());
- packet.putByteC(bytes.length);
- for (int ptr = bytes.length - 1; ptr >= 0; ptr--) {
- packet.put(bytes[ptr]);
- }
- }
- /**
- * Appends an appearance update.
- *
- * @param packet
- * The packet.
- * @param otherPlayer
- * The player.
- */
- private void appendPlayerAppearanceUpdate(PacketBuilder packet, Player otherPlayer) {
- Appearance app = otherPlayer.getAppearance();
- Container eq = otherPlayer.getEquipment();
- PacketBuilder playerProps = new PacketBuilder();
- playerProps.put((byte) app.getAppearance(Appearance.GENDER)); // gender
- playerProps.put((byte) otherPlayer.getPrayerIcon()); // prayer icon
- playerProps.put((byte) -1); // skull icon
- //playerProps.put((byte) -1); // hint icon
- for (int i = 0; i < 4; i++) {
- if (eq.isSlotUsed(i)) {
- playerProps.putShort((short) 0x200 + eq.get(i).getId());
- } else {
- playerProps.put((byte) 0);
- }
- }
- if (eq.isSlotUsed(Equipment.SLOT_CHEST)) {
- playerProps.putShort((short) 0x200 + eq.get(Equipment.SLOT_CHEST).getId());
- } else {
- playerProps.putShort((short) 0x100 + app.getAppearance(Appearance.TORSO)); // chest
- }
- if (eq.isSlotUsed(Equipment.SLOT_SHIELD)) {
- playerProps.putShort((short) 0x200 + eq.get(Equipment.SLOT_SHIELD).getId());
- } else {
- playerProps.put((byte) 0);
- }
- Item chest = eq.get(Equipment.SLOT_CHEST);
- if (chest != null) {
- if (!Equipment.is(EquipmentType.PLATEBODY, chest)) {
- playerProps.putShort((short) 0x100 + app.getAppearance(Appearance.ARMS));
- } else {
- playerProps.putShort((short) 0x200 + chest.getId());
- }
- } else {
- playerProps.putShort((short) 0x100 + app.getAppearance(Appearance.ARMS));
- }
- if (eq.isSlotUsed(Equipment.SLOT_BOTTOMS)) {
- playerProps.putShort((short) 0x200 + eq.get(Equipment.SLOT_BOTTOMS).getId());
- } else {
- playerProps.putShort((short) 0x100 + app.getAppearance(Appearance.LEGS));
- }
- Item helm = eq.get(Equipment.SLOT_HELM);
- if (helm != null) {
- if (!Equipment.is(EquipmentType.FULL_HELM, helm) && !Equipment.is(EquipmentType.FULL_MASK, helm)) {
- playerProps.putShort((short) 0x100 + app.getAppearance(Appearance.HEAD));
- } else {
- playerProps.put((byte) 0);
- }
- } else {
- playerProps.putShort((short) 0x100 + app.getAppearance(Appearance.HEAD));
- }
- if (eq.isSlotUsed(Equipment.SLOT_GLOVES)) {
- playerProps.putShort((short) 0x200 + eq.get(Equipment.SLOT_GLOVES).getId());
- } else {
- playerProps.putShort((short) 0x100 + app.getAppearance(Appearance.HANDS));
- }
- if (eq.isSlotUsed(Equipment.SLOT_BOOTS)) {
- playerProps.putShort((short) 0x200 + eq.get(Equipment.SLOT_BOOTS).getId());
- } else {
- playerProps.putShort((short) 0x100 + app.getAppearance(Appearance.FEET));
- }
- boolean fullHelm = false;
- if (helm != null) {
- fullHelm = !Equipment.is(EquipmentType.FULL_HELM, helm);
- }
- if (fullHelm || app.getAppearance(Appearance.GENDER) == 1) {
- playerProps.put((byte) 0);
- } else {
- playerProps.putShort((short) 0x100 + app.getAppearance(Appearance.JAW));
- }
- playerProps.put((byte) app.getAppearance(Appearance.HAIR_COLOR)); // hairc
- playerProps.put((byte) app.getAppearance(Appearance.TORSO_COLOR)); // torsoc
- playerProps.put((byte) app.getAppearance(Appearance.LEGS_COLOR)); // legc
- playerProps.put((byte) app.getAppearance(Appearance.FEET_COLOR)); // feetc
- playerProps.put((byte) app.getAppearance(Appearance.SKIN_COLOR)); // skinc
- playerProps.putShort(otherPlayer.getAnimations().getStandEmote()); // stand
- playerProps.putShort(otherPlayer.getAnimations().getStandTurnEmote()); // stand turn
- playerProps.putShort(otherPlayer.getAnimations().getWalkEmote()); // walk
- playerProps.putShort(otherPlayer.getAnimations().getTurn180Emote()); // turn 180
- playerProps.putShort(otherPlayer.getAnimations().getTurn90CWEmote()); // turn 90 cw
- playerProps.putShort(otherPlayer.getAnimations().getTurn90CCWEmote()); // turn 90 ccw
- playerProps.putShort(otherPlayer.getAnimations().getRunEmote()); // run
- playerProps.putLong(otherPlayer.getNameAsLong()); // player name
- playerProps.put((byte) otherPlayer.getSkills().getCombatLevel());
- playerProps.putShort(0);
- Packet propsPacket = playerProps.toPacket();
- packet.putByteC(propsPacket.getLength());
- packet.put(propsPacket.getPayload());
- }
- /**
- * Updates this player's movement.
- *
- * @param packet
- * The packet.
- */
- private void updateThisPlayerMovement(PacketBuilder packet) {
- /*
- * Check if the player is teleporting.
- */
- if (player.isTeleporting() || player.isMapRegionChanging()) {
- /*
- * They are, so an update is required.
- */
- packet.putBits(1, 1);
- /*
- * This value indicates the player teleported.
- */
- packet.putBits(2, 3);
- /*
- * This is the new player height.
- */
- packet.putBits(2, player.getLocation().getZ());
- /*
- * This indicates that the client should discard the walking queue.
- */
- packet.putBits(1, player.isTeleporting() ? 1 : 0);
- /*
- * This flag indicates if an update block is appended.
- */
- packet.putBits(1, player.getUpdateFlags().isUpdateRequired() ? 1 : 0);
- /*
- * These are the positions.
- */
- packet.putBits(7, player.getLocation().getLocalY(player.getLastKnownRegion()));
- packet.putBits(7, player.getLocation().getLocalX(player.getLastKnownRegion()));
- } else {
- /*
- * Otherwise, check if the player moved.
- */
- if (player.getSprites().getPrimarySprite() == -1) {
- /*
- * The player didn't move. Check if an update is required.
- */
- if (player.getUpdateFlags().isUpdateRequired()) {
- /*
- * Signifies an update is required.
- */
- packet.putBits(1, 1);
- /*
- * But signifies that we didn't move.
- */
- packet.putBits(2, 0);
- } else {
- /*
- * Signifies that nothing changed.
- */
- packet.putBits(1, 0);
- }
- } else {
- /*
- * Check if the player was running.
- */
- if (player.getSprites().getSecondarySprite() == -1) {
- /*
- * The player walked, an update is required.
- */
- packet.putBits(1, 1);
- /*
- * This indicates the player only walked.
- */
- packet.putBits(2, 1);
- /*
- * This is the player's walking direction.
- */
- packet.putBits(3, player.getSprites().getPrimarySprite());
- /*
- * This flag indicates an update block is appended.
- */
- packet.putBits(1, player.getUpdateFlags().isUpdateRequired() ? 1 : 0);
- } else {
- /*
- * The player ran, so an update is required.
- */
- packet.putBits(1, 1);
- /*
- * This indicates the player ran.
- */
- packet.putBits(2, 2);
- /*
- * This is the walking direction.
- */
- packet.putBits(3, player.getSprites().getPrimarySprite());
- /*
- * And this is the running direction.
- */
- packet.putBits(3, player.getSprites().getSecondarySprite());
- /*
- * And this flag indicates an update block is appended.
- */
- packet.putBits(1, player.getUpdateFlags().isUpdateRequired() ? 1 : 0);
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement