/** * Updates this player's movement. * * @param packet The packet. */ private void updateThisPlayerMovement(final PacketBuilder packet) { if (player.isTeleporting() || player.isMapRegionChanging()) { packet.putBits(1, 1); packet.putBits(2, 3); packet.putBits(7, player.getLocation().getLocalX(player.getLastKnownRegion())); packet.putBits(1, 1); packet.putBits(2, player.getLocation().getZ()); packet.putBits(1, player.getUpdateFlags().isUpdateRequired() ? 1 : 0); packet.putBits(7, player.getLocation().getLocalY(player.getLastKnownRegion())); } else { if (player.getSprites().getPrimarySprite() == -1) { packet.putBits(1, player.getUpdateFlags().isUpdateRequired() ? 1 : 0); if (player.getUpdateFlags().isUpdateRequired()) { packet.putBits(2, 0); } } else { if (player.getSprites().getSecondarySprite() != -1) { packet.putBits(1, 1); packet.putBits(2, 2); packet.putBits(3, player.getSprites().getPrimarySprite()); packet.putBits(3, player.getSprites().getSecondarySprite()); packet.putBits(1, player.getUpdateFlags().isUpdateRequired() ? 1 : 0); } else { packet.putBits(1, 1); packet.putBits(2, 1); packet.putBits(3, player.getSprites().getPrimarySprite()); packet.putBits(1, player.getUpdateFlags().isUpdateRequired() ? 1 : 0); } } } }
/** * Updates a non-this player's movement. * * @param packet The packet. * @param otherPlayer The player. */ public void updatePlayerMovement(PacketBuilder packet, Player otherPlayer) { if (otherPlayer.getSprites().getPrimarySprite() == -1) { if (otherPlayer.getUpdateFlags().isUpdateRequired()) { packet.putBits(1, 1); packet.putBits(2, 0); } else { packet.putBits(1, 0); } } else if (otherPlayer.getSprites().getSecondarySprite() == -1) { packet.putBits(1, 1); packet.putBits(2, 1); packet.putBits(3, otherPlayer.getSprites().getPrimarySprite()); packet.putBits(1, otherPlayer.getUpdateFlags().isUpdateRequired() ? 1 : 0); } else { packet.putBits(1, 1); packet.putBits(2, 2); packet.putBits(3, otherPlayer.getSprites().getPrimarySprite()); packet.putBits(3, otherPlayer.getSprites().getSecondarySprite()); packet.putBits(1, otherPlayer.getUpdateFlags().isUpdateRequired() ? 1 : 0); } }
@Override public void execute(GameEngine context) { final Queue<ChatMessage> messages = player.getChatMessageQueue(); if (messages.size() > 0) { player.getUpdateFlags().flag(UpdateFlag.CHAT); final ChatMessage message = player.getChatMessageQueue().poll(); player.setCurrentChatMessage(message); } else { player.setCurrentChatMessage(null); } player.getWalkingQueue().processNextMovement(); }
@Override public void execute(GameEngine context) { /* * 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.getActionSender().sendMapRegion(); } /* * The update block packet holds update blocks and is send after the * main packet. */ final 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. */ final PacketBuilder updatePacket = new PacketBuilder(216, Packet.Type.VARIABLE_SHORT); updatePacket.startBitAccess(); /* * Updates this player. */ updateThisPlayerMovement(updatePacket); updatePlayer(updateBlock, player, false); /* * Write the current size of the player list. */ updatePacket.putBits(8, player.getLocalPlayers().size()); /* * Iterate through the local player list. */ for (final Iterator<Player> it$ = player.getLocalPlayers().iterator(); it$.hasNext(); ) { /* * Get the next player. */ final 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(), 16)) { /* * Update the movement. */ updatePlayerMovement(updatePacket, otherPlayer); /* * Check if an update is required, and if so, send the update. */ if (otherPlayer.getUpdateFlags().isUpdateRequired()) { updatePlayer(updateBlock, otherPlayer, false); } } else { /* * Otherwise, remove the player from the list. */ it$.remove(); /* * Tell the client to remove the player from the list. */ updatePacket.putBits(1, 1); updatePacket.putBits(2, 3); } } /* * Loop through every player. */ for (final 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(updatePacket, otherPlayer); /* * Update the player, forcing the appearance flag. */ updatePlayer(updateBlock, otherPlayer, true); } /* * Check if the update block is not empty. */ if (!updateBlock.isEmpty()) { /* * Write a magic id indicating an update block follows. */ updatePacket.putBits(11, 2047); updatePacket.finishBitAccess(); /* * Add the update block at the end of this packet. */ updatePacket.put(updateBlock.toPacket().getPayload()); } else { /* * Terminate the packet normally. */ updatePacket.finishBitAccess(); } /* * Write the packet. */ player.write(updatePacket.toPacket()); }
/** * Updates a player. * * @param packet The packet. * @param otherPlayer The other player. * @param forceAppearance The force appearance flag. */ public void updatePlayer(PacketBuilder packet, Player otherPlayer, boolean forceAppearance) { /* * 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) { 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 = 0x0; final UpdateFlags flags = otherPlayer.getUpdateFlags(); if (flags.get(UpdateFlag.FACE_ENTITY)) { mask |= 0x20; } if (flags.get(UpdateFlag.GRAPHICS)) { mask |= 0x400; } if (flags.get(UpdateFlag.CHAT)) { mask |= 0x8; } if (flags.get(UpdateFlag.ANIMATION)) { mask |= 0x1; } if (flags.get(UpdateFlag.APPEARANCE) || forceAppearance) { mask |= 0x80; } if (flags.get(UpdateFlag.HIT)) { mask |= 0x2; } if (flags.get(UpdateFlag.HIT_2)) { mask |= 0x200; } /* if (flags.get(UpdateFlag.FACE_COORDINATE)) { mask |= 0x40; }*/ /* * Check if the bitmask would overflow a byte. */ if (mask >= 0x100) { /* * Write it as a short and indicate we have done so. */ mask |= 0x10; 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.FACE_ENTITY)) { Entity entity = otherPlayer.getInteractingEntity(); block.putShort(entity == null ? -1 : entity.getClientIndex()); } if (flags.get(UpdateFlag.GRAPHICS)) { appendGraphicsUpdate(block, otherPlayer); } if (flags.get(UpdateFlag.CHAT)) { appendChatUpdate(block, otherPlayer); } if (flags.get(UpdateFlag.ANIMATION)) { appendAnimationUpdate(block, otherPlayer); } if (flags.get(UpdateFlag.APPEARANCE) || forceAppearance) { appendPlayerAppearanceUpdate(block, otherPlayer); } if (flags.get(UpdateFlag.HIT)) { appendHitUpdate(otherPlayer, block); } if (flags.get(UpdateFlag.HIT_2)) { appendHit2Update(otherPlayer, block); } /* if (flags.get(UpdateFlag.FACE_COORDINATE)) { appendFaceCoordinateUpdate(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) { otherPlayer.setCachedUpdateBlock(blockPacket); } /* * And finally append the block at the end. */ packet.put(blockPacket.getPayload()); } }