use of cn.nukkit.inventory.transaction.action.InventoryAction in project Nukkit by Nukkit.
the class Player method handleDataPacket.
public void handleDataPacket(DataPacket packet) {
if (!connected) {
return;
}
try (Timing timing = Timings.getReceiveDataPacketTiming(packet)) {
DataPacketReceiveEvent ev = new DataPacketReceiveEvent(this, packet);
this.server.getPluginManager().callEvent(ev);
if (ev.isCancelled()) {
timing.stopTiming();
return;
}
if (packet.pid() == ProtocolInfo.BATCH_PACKET) {
timing.stopTiming();
this.server.getNetwork().processBatch((BatchPacket) packet, this);
return;
}
packetswitch: switch(packet.pid()) {
case ProtocolInfo.LOGIN_PACKET:
if (this.loggedIn) {
break;
}
LoginPacket loginPacket = (LoginPacket) packet;
String message;
if (!ProtocolInfo.SUPPORTED_PROTOCOLS.contains(loginPacket.getProtocol())) {
if (loginPacket.getProtocol() < ProtocolInfo.CURRENT_PROTOCOL) {
message = "disconnectionScreen.outdatedClient";
this.sendPlayStatus(PlayStatusPacket.LOGIN_FAILED_CLIENT);
} else {
message = "disconnectionScreen.outdatedServer";
this.sendPlayStatus(PlayStatusPacket.LOGIN_FAILED_SERVER);
}
if (((LoginPacket) packet).protocol < 137) {
DisconnectPacket disconnectPacket = new DisconnectPacket();
disconnectPacket.message = message;
disconnectPacket.encode();
BatchPacket batch = new BatchPacket();
batch.payload = disconnectPacket.getBuffer();
this.directDataPacket(batch);
// Still want to run close() to allow the player to be removed properly
}
this.close("", message, false);
break;
}
this.username = TextFormat.clean(loginPacket.username);
this.displayName = this.username;
this.iusername = this.username.toLowerCase();
this.setDataProperty(new StringEntityData(DATA_NAMETAG, this.username), false);
this.loginChainData = ClientChainData.read(loginPacket);
if (!loginChainData.isXboxAuthed() && server.getPropertyBoolean("xbox-auth")) {
kick(PlayerKickEvent.Reason.UNKNOWN, "disconnectionScreen.notAuthenticated", false);
}
if (this.server.getOnlinePlayers().size() >= this.server.getMaxPlayers() && this.kick(PlayerKickEvent.Reason.SERVER_FULL, "disconnectionScreen.serverFull", false)) {
break;
}
this.randomClientId = loginPacket.clientId;
this.uuid = loginPacket.clientUUID;
this.rawUUID = Binary.writeUUID(this.uuid);
boolean valid = true;
int len = loginPacket.username.length();
if (len > 16 || len < 3) {
valid = false;
}
for (int i = 0; i < len && valid; i++) {
char c = loginPacket.username.charAt(i);
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == ' ') {
continue;
}
valid = false;
break;
}
if (!valid || Objects.equals(this.iusername, "rcon") || Objects.equals(this.iusername, "console")) {
this.close("", "disconnectionScreen.invalidName");
break;
}
if (!loginPacket.skin.isValid()) {
this.close("", "disconnectionScreen.invalidSkin");
break;
} else {
this.setSkin(loginPacket.getSkin());
}
PlayerPreLoginEvent playerPreLoginEvent;
this.server.getPluginManager().callEvent(playerPreLoginEvent = new PlayerPreLoginEvent(this, "Plugin reason"));
if (playerPreLoginEvent.isCancelled()) {
this.close("", playerPreLoginEvent.getKickMessage());
break;
}
this.processLogin();
break;
case ProtocolInfo.RESOURCE_PACK_CLIENT_RESPONSE_PACKET:
ResourcePackClientResponsePacket responsePacket = (ResourcePackClientResponsePacket) packet;
switch(responsePacket.responseStatus) {
case ResourcePackClientResponsePacket.STATUS_REFUSED:
this.close("", "disconnectionScreen.noReason");
break;
case ResourcePackClientResponsePacket.STATUS_SEND_PACKS:
for (String id : responsePacket.packIds) {
ResourcePack resourcePack = this.server.getResourcePackManager().getPackById(id);
if (resourcePack == null) {
this.close("", "disconnectionScreen.resourcePack");
break;
}
ResourcePackDataInfoPacket dataInfoPacket = new ResourcePackDataInfoPacket();
dataInfoPacket.packId = resourcePack.getPackId();
// megabyte
dataInfoPacket.maxChunkSize = 1048576;
dataInfoPacket.chunkCount = resourcePack.getPackSize() / dataInfoPacket.maxChunkSize;
dataInfoPacket.compressedPackSize = resourcePack.getPackSize();
dataInfoPacket.sha256 = resourcePack.getSha256();
this.dataPacket(dataInfoPacket);
}
break;
case ResourcePackClientResponsePacket.STATUS_HAVE_ALL_PACKS:
ResourcePackStackPacket stackPacket = new ResourcePackStackPacket();
stackPacket.mustAccept = this.server.getForceResources();
stackPacket.resourcePackStack = this.server.getResourcePackManager().getResourceStack();
this.dataPacket(stackPacket);
break;
case ResourcePackClientResponsePacket.STATUS_COMPLETED:
this.completeLoginSequence();
break;
}
break;
case ProtocolInfo.RESOURCE_PACK_CHUNK_REQUEST_PACKET:
ResourcePackChunkRequestPacket requestPacket = (ResourcePackChunkRequestPacket) packet;
ResourcePack resourcePack = this.server.getResourcePackManager().getPackById(requestPacket.packId);
if (resourcePack == null) {
this.close("", "disconnectionScreen.resourcePack");
break;
}
ResourcePackChunkDataPacket dataPacket = new ResourcePackChunkDataPacket();
dataPacket.packId = resourcePack.getPackId();
dataPacket.chunkIndex = requestPacket.chunkIndex;
dataPacket.data = resourcePack.getPackChunk(1048576 * requestPacket.chunkIndex, 1048576);
dataPacket.progress = 1048576 * requestPacket.chunkIndex;
this.dataPacket(dataPacket);
break;
case ProtocolInfo.PLAYER_INPUT_PACKET:
if (!this.isAlive() || !this.spawned) {
break;
}
PlayerInputPacket ipk = (PlayerInputPacket) packet;
if (riding instanceof EntityMinecartAbstract) {
((EntityMinecartEmpty) riding).setCurrentSpeed(ipk.motionY);
}
break;
case ProtocolInfo.MOVE_PLAYER_PACKET:
if (this.teleportPosition != null) {
break;
}
MovePlayerPacket movePlayerPacket = (MovePlayerPacket) packet;
Vector3 newPos = new Vector3(movePlayerPacket.x, movePlayerPacket.y - this.getEyeHeight(), movePlayerPacket.z);
if (newPos.distanceSquared(this) < 0.01 && movePlayerPacket.yaw % 360 == this.yaw && movePlayerPacket.pitch % 360 == this.pitch) {
break;
}
boolean revert = false;
if (!this.isAlive() || !this.spawned) {
revert = true;
this.forceMovement = new Vector3(this.x, this.y, this.z);
}
if (this.forceMovement != null && (newPos.distanceSquared(this.forceMovement) > 0.1 || revert)) {
this.sendPosition(this.forceMovement, movePlayerPacket.yaw, movePlayerPacket.pitch, MovePlayerPacket.MODE_RESET);
} else {
movePlayerPacket.yaw %= 360;
movePlayerPacket.pitch %= 360;
if (movePlayerPacket.yaw < 0) {
movePlayerPacket.yaw += 360;
}
this.setRotation(movePlayerPacket.yaw, movePlayerPacket.pitch);
this.newPosition = newPos;
this.forceMovement = null;
}
if (riding != null) {
if (riding instanceof EntityBoat) {
riding.setPositionAndRotation(this.temporalVector.setComponents(movePlayerPacket.x, movePlayerPacket.y - 1, movePlayerPacket.z), (movePlayerPacket.headYaw + 90) % 360, 0);
}
}
break;
case ProtocolInfo.ADVENTURE_SETTINGS_PACKET:
// TODO: player abilities, check for other changes
AdventureSettingsPacket adventureSettingsPacket = (AdventureSettingsPacket) packet;
if (adventureSettingsPacket.getFlag(AdventureSettingsPacket.ALLOW_FLIGHT) && !this.getAdventureSettings().get(Type.ALLOW_FLIGHT)) {
this.kick(PlayerKickEvent.Reason.FLYING_DISABLED, "Flying is not enabled on this server");
break;
}
PlayerToggleFlightEvent playerToggleFlightEvent = new PlayerToggleFlightEvent(this, adventureSettingsPacket.getFlag(AdventureSettingsPacket.ALLOW_FLIGHT));
this.server.getPluginManager().callEvent(playerToggleFlightEvent);
if (playerToggleFlightEvent.isCancelled()) {
this.getAdventureSettings().update();
} else {
this.getAdventureSettings().set(Type.FLYING, playerToggleFlightEvent.isFlying());
}
break;
case ProtocolInfo.MOB_EQUIPMENT_PACKET:
if (!this.spawned || !this.isAlive()) {
break;
}
MobEquipmentPacket mobEquipmentPacket = (MobEquipmentPacket) packet;
Item item = this.inventory.getItem(mobEquipmentPacket.hotbarSlot);
if (!item.equals(mobEquipmentPacket.item)) {
this.server.getLogger().debug("Tried to equip " + mobEquipmentPacket.item + " but have " + item + " in target slot");
this.inventory.sendContents(this);
return;
}
this.inventory.equipItem(mobEquipmentPacket.hotbarSlot);
this.setDataFlag(Player.DATA_FLAGS, Player.DATA_FLAG_ACTION, false);
break;
case ProtocolInfo.PLAYER_ACTION_PACKET:
PlayerActionPacket playerActionPacket = (PlayerActionPacket) packet;
if (!this.spawned || (!this.isAlive() && playerActionPacket.action != PlayerActionPacket.ACTION_RESPAWN && playerActionPacket.action != PlayerActionPacket.ACTION_DIMENSION_CHANGE_REQUEST)) {
break;
}
playerActionPacket.entityId = this.id;
Vector3 pos = new Vector3(playerActionPacket.x, playerActionPacket.y, playerActionPacket.z);
BlockFace face = BlockFace.fromIndex(playerActionPacket.face);
switch(playerActionPacket.action) {
case PlayerActionPacket.ACTION_START_BREAK:
if (this.lastBreak != Long.MAX_VALUE || pos.distanceSquared(this) > 100) {
break;
}
Block target = this.level.getBlock(pos);
PlayerInteractEvent playerInteractEvent = new PlayerInteractEvent(this, this.inventory.getItemInHand(), target, face, target.getId() == 0 ? Action.LEFT_CLICK_AIR : Action.LEFT_CLICK_BLOCK);
this.getServer().getPluginManager().callEvent(playerInteractEvent);
if (playerInteractEvent.isCancelled()) {
this.inventory.sendHeldItem(this);
break;
}
if (target.getId() == Block.NOTEBLOCK) {
((BlockNoteblock) target).emitSound();
break;
}
Block block = target.getSide(face);
if (block.getId() == Block.FIRE) {
this.level.setBlock(block, new BlockAir(), true);
break;
}
if (!this.isCreative()) {
// improved this to take stuff like swimming, ladders, enchanted tools into account, fix wrong tool break time calculations for bad tools (pmmp/PocketMine-MP#211)
// Done by lmlstarqaq
double breakTime = Math.ceil(target.getBreakTime(this.inventory.getItemInHand(), this) * 20);
if (breakTime > 0) {
LevelEventPacket pk = new LevelEventPacket();
pk.evid = LevelEventPacket.EVENT_BLOCK_START_BREAK;
pk.x = (float) pos.x;
pk.y = (float) pos.y;
pk.z = (float) pos.z;
pk.data = (int) (65535 / breakTime);
this.getLevel().addChunkPacket(pos.getFloorX() >> 4, pos.getFloorZ() >> 4, pk);
}
}
this.breakingBlock = target;
this.lastBreak = System.currentTimeMillis();
break;
case PlayerActionPacket.ACTION_ABORT_BREAK:
this.lastBreak = Long.MAX_VALUE;
this.breakingBlock = null;
case PlayerActionPacket.ACTION_STOP_BREAK:
LevelEventPacket pk = new LevelEventPacket();
pk.evid = LevelEventPacket.EVENT_BLOCK_STOP_BREAK;
pk.x = (float) pos.x;
pk.y = (float) pos.y;
pk.z = (float) pos.z;
pk.data = 0;
this.getLevel().addChunkPacket(pos.getFloorX() >> 4, pos.getFloorZ() >> 4, pk);
this.breakingBlock = null;
break;
case PlayerActionPacket.ACTION_GET_UPDATED_BLOCK:
// TODO
break;
case PlayerActionPacket.ACTION_DROP_ITEM:
// TODO
break;
case PlayerActionPacket.ACTION_STOP_SLEEPING:
this.stopSleep();
break;
case PlayerActionPacket.ACTION_RESPAWN:
if (!this.spawned || this.isAlive() || !this.isOnline()) {
break;
}
if (this.server.isHardcore()) {
this.setBanned(true);
break;
}
this.craftingType = CRAFTING_SMALL;
this.resetCraftingGridType();
PlayerRespawnEvent playerRespawnEvent = new PlayerRespawnEvent(this, this.getSpawn());
this.server.getPluginManager().callEvent(playerRespawnEvent);
Position respawnPos = playerRespawnEvent.getRespawnPosition();
this.teleport(respawnPos, null);
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.x = (float) respawnPos.x;
respawnPacket.y = (float) respawnPos.y;
respawnPacket.z = (float) respawnPos.z;
this.dataPacket(respawnPacket);
this.setSprinting(false, true);
this.setSneaking(false);
this.extinguish();
this.setDataProperty(new ShortEntityData(Player.DATA_AIR, 400), false);
this.deadTicks = 0;
this.noDamageTicks = 60;
this.removeAllEffects();
this.setHealth(this.getMaxHealth());
this.getFoodData().setLevel(20, 20);
this.sendData(this);
this.setMovementSpeed(DEFAULT_SPEED);
this.getAdventureSettings().update();
this.inventory.sendContents(this);
this.inventory.sendArmorContents(this);
this.spawnToAll();
this.scheduleUpdate();
break;
case PlayerActionPacket.ACTION_JUMP:
break packetswitch;
case PlayerActionPacket.ACTION_START_SPRINT:
PlayerToggleSprintEvent playerToggleSprintEvent = new PlayerToggleSprintEvent(this, true);
this.server.getPluginManager().callEvent(playerToggleSprintEvent);
if (playerToggleSprintEvent.isCancelled()) {
this.sendData(this);
} else {
this.setSprinting(true);
}
break packetswitch;
case PlayerActionPacket.ACTION_STOP_SPRINT:
playerToggleSprintEvent = new PlayerToggleSprintEvent(this, false);
this.server.getPluginManager().callEvent(playerToggleSprintEvent);
if (playerToggleSprintEvent.isCancelled()) {
this.sendData(this);
} else {
this.setSprinting(false);
}
break packetswitch;
case PlayerActionPacket.ACTION_START_SNEAK:
PlayerToggleSneakEvent playerToggleSneakEvent = new PlayerToggleSneakEvent(this, true);
this.server.getPluginManager().callEvent(playerToggleSneakEvent);
if (playerToggleSneakEvent.isCancelled()) {
this.sendData(this);
} else {
this.setSneaking(true);
}
break packetswitch;
case PlayerActionPacket.ACTION_STOP_SNEAK:
playerToggleSneakEvent = new PlayerToggleSneakEvent(this, false);
this.server.getPluginManager().callEvent(playerToggleSneakEvent);
if (playerToggleSneakEvent.isCancelled()) {
this.sendData(this);
} else {
this.setSneaking(false);
}
break packetswitch;
case PlayerActionPacket.ACTION_DIMENSION_CHANGE_ACK:
// TODO
break;
case PlayerActionPacket.ACTION_START_GLIDE:
PlayerToggleGlideEvent playerToggleGlideEvent = new PlayerToggleGlideEvent(this, true);
this.server.getPluginManager().callEvent(playerToggleGlideEvent);
if (playerToggleGlideEvent.isCancelled()) {
this.sendData(this);
} else {
this.setGliding(true);
}
break packetswitch;
case PlayerActionPacket.ACTION_STOP_GLIDE:
playerToggleGlideEvent = new PlayerToggleGlideEvent(this, false);
this.server.getPluginManager().callEvent(playerToggleGlideEvent);
if (playerToggleGlideEvent.isCancelled()) {
this.sendData(this);
} else {
this.setGliding(false);
}
break packetswitch;
case PlayerActionPacket.ACTION_CONTINUE_BREAK:
if (this.isBreakingBlock()) {
block = this.level.getBlock(pos);
this.level.addParticle(new PunchBlockParticle(pos, block, face));
}
break;
}
this.startAction = -1;
this.setDataFlag(Player.DATA_FLAGS, Player.DATA_FLAG_ACTION, false);
break;
case ProtocolInfo.MOB_ARMOR_EQUIPMENT_PACKET:
break;
case ProtocolInfo.MODAL_FORM_RESPONSE_PACKET:
if (!this.spawned || !this.isAlive()) {
break;
}
ModalFormResponsePacket modalFormPacket = (ModalFormResponsePacket) packet;
if (formWindows.containsKey(modalFormPacket.formId)) {
FormWindow window = formWindows.remove(modalFormPacket.formId);
window.setResponse(modalFormPacket.data.trim());
PlayerFormRespondedEvent event = new PlayerFormRespondedEvent(this, modalFormPacket.formId, window);
getServer().getPluginManager().callEvent(event);
} else if (serverSettings.containsKey(modalFormPacket.formId)) {
FormWindow window = serverSettings.get(modalFormPacket.formId);
window.setResponse(modalFormPacket.data.trim());
PlayerSettingsRespondedEvent event = new PlayerSettingsRespondedEvent(this, modalFormPacket.formId, window);
getServer().getPluginManager().callEvent(event);
// Set back new settings if not been cancelled
if (!event.isCancelled() && window instanceof FormWindowCustom)
((FormWindowCustom) window).setElementsFromResponse();
}
break;
case ProtocolInfo.INTERACT_PACKET:
if (!this.spawned || !this.isAlive()) {
break;
}
this.craftingType = CRAFTING_SMALL;
// this.resetCraftingGridType();
InteractPacket interactPacket = (InteractPacket) packet;
Entity targetEntity = this.level.getEntity(interactPacket.target);
if (targetEntity == null || !this.isAlive() || !targetEntity.isAlive()) {
break;
}
if (targetEntity instanceof EntityItem || targetEntity instanceof EntityArrow || targetEntity instanceof EntityXPOrb) {
this.kick(PlayerKickEvent.Reason.INVALID_PVE, "Attempting to interact with an invalid entity");
this.server.getLogger().warning(this.getServer().getLanguage().translateString("nukkit.player.invalidEntity", this.getName()));
break;
}
item = this.inventory.getItemInHand();
switch(interactPacket.action) {
case InteractPacket.ACTION_MOUSEOVER:
this.getServer().getPluginManager().callEvent(new PlayerMouseOverEntityEvent(this, targetEntity));
break;
case InteractPacket.ACTION_VEHICLE_EXIT:
if (!(targetEntity instanceof EntityRideable) || this.riding == null) {
break;
}
((EntityRideable) riding).mountEntity(this);
break;
}
break;
case ProtocolInfo.BLOCK_PICK_REQUEST_PACKET:
BlockPickRequestPacket pickRequestPacket = (BlockPickRequestPacket) packet;
Block block = this.level.getBlock(this.temporalVector.setComponents(pickRequestPacket.x, pickRequestPacket.y, pickRequestPacket.z));
item = block.toItem();
if (pickRequestPacket.addUserData) {
BlockEntity blockEntity = this.getLevel().getBlockEntity(new Vector3(pickRequestPacket.x, pickRequestPacket.y, pickRequestPacket.z));
if (blockEntity != null) {
CompoundTag nbt = blockEntity.getCleanedNBT();
if (nbt != null) {
Item item1 = this.getInventory().getItemInHand();
item1.setCustomBlockData(nbt);
item1.setLore("+(DATA)");
this.getInventory().setItemInHand(item1);
}
}
}
PlayerBlockPickEvent pickEvent = new PlayerBlockPickEvent(this, block, item);
if (!this.isCreative()) {
this.server.getLogger().debug("Got block-pick request from " + this.getName() + " when not in creative mode (gamemode " + this.getGamemode() + ")");
pickEvent.setCancelled();
}
this.server.getPluginManager().callEvent(pickEvent);
if (!pickEvent.isCancelled()) {
this.inventory.setItemInHand(pickEvent.getItem());
}
break;
case ProtocolInfo.ANIMATE_PACKET:
if (!this.spawned || !this.isAlive()) {
break;
}
PlayerAnimationEvent animationEvent = new PlayerAnimationEvent(this, ((AnimatePacket) packet).action);
this.server.getPluginManager().callEvent(animationEvent);
if (animationEvent.isCancelled()) {
break;
}
AnimatePacket animatePacket = new AnimatePacket();
animatePacket.eid = this.getId();
animatePacket.action = animationEvent.getAnimationType();
Server.broadcastPacket(this.getViewers().values(), animatePacket);
break;
case ProtocolInfo.SET_HEALTH_PACKET:
// use UpdateAttributePacket instead
break;
case ProtocolInfo.ENTITY_EVENT_PACKET:
if (!this.spawned || !this.isAlive()) {
break;
}
this.craftingType = CRAFTING_SMALL;
// this.resetCraftingGridType();
EntityEventPacket entityEventPacket = (EntityEventPacket) packet;
switch(entityEventPacket.event) {
case EntityEventPacket.EATING_ITEM:
if (entityEventPacket.data == 0) {
break;
}
/*this.dataPacket(packet); //bug?
Server.broadcastPacket(this.getViewers().values(), packet);*/
break;
}
break;
case ProtocolInfo.COMMAND_REQUEST_PACKET:
if (!this.spawned || !this.isAlive()) {
break;
}
this.craftingType = 0;
CommandRequestPacket commandRequestPacket = (CommandRequestPacket) packet;
PlayerCommandPreprocessEvent playerCommandPreprocessEvent = new PlayerCommandPreprocessEvent(this, commandRequestPacket.command);
this.server.getPluginManager().callEvent(playerCommandPreprocessEvent);
if (playerCommandPreprocessEvent.isCancelled()) {
break;
}
Timings.playerCommandTimer.startTiming();
this.server.dispatchCommand(playerCommandPreprocessEvent.getPlayer(), playerCommandPreprocessEvent.getMessage().substring(1));
Timings.playerCommandTimer.stopTiming();
break;
case ProtocolInfo.TEXT_PACKET:
if (!this.spawned || !this.isAlive()) {
break;
}
TextPacket textPacket = (TextPacket) packet;
if (textPacket.type == TextPacket.TYPE_CHAT) {
this.chat(textPacket.message);
}
break;
case ProtocolInfo.CONTAINER_CLOSE_PACKET:
ContainerClosePacket containerClosePacket = (ContainerClosePacket) packet;
if (!this.spawned || containerClosePacket.windowId == 0) {
break;
}
this.craftingType = CRAFTING_SMALL;
this.resetCraftingGridType();
if (this.windowIndex.containsKey(containerClosePacket.windowId)) {
this.server.getPluginManager().callEvent(new InventoryCloseEvent(this.windowIndex.get(containerClosePacket.windowId), this));
this.removeWindow(this.windowIndex.get(containerClosePacket.windowId));
} else {
this.windowIndex.remove(containerClosePacket.windowId);
}
break;
case ProtocolInfo.CRAFTING_EVENT_PACKET:
break;
case ProtocolInfo.BLOCK_ENTITY_DATA_PACKET:
if (!this.spawned || !this.isAlive()) {
break;
}
BlockEntityDataPacket blockEntityDataPacket = (BlockEntityDataPacket) packet;
this.craftingType = CRAFTING_SMALL;
this.resetCraftingGridType();
pos = new Vector3(blockEntityDataPacket.x, blockEntityDataPacket.y, blockEntityDataPacket.z);
if (pos.distanceSquared(this) > 10000) {
break;
}
BlockEntity t = this.level.getBlockEntity(pos);
if (t instanceof BlockEntitySpawnable) {
CompoundTag nbt;
try {
nbt = NBTIO.read(blockEntityDataPacket.namedTag, ByteOrder.LITTLE_ENDIAN, true);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (!((BlockEntitySpawnable) t).updateCompoundTag(nbt, this)) {
((BlockEntitySpawnable) t).spawnTo(this);
}
}
break;
case ProtocolInfo.REQUEST_CHUNK_RADIUS_PACKET:
RequestChunkRadiusPacket requestChunkRadiusPacket = (RequestChunkRadiusPacket) packet;
ChunkRadiusUpdatedPacket chunkRadiusUpdatePacket = new ChunkRadiusUpdatedPacket();
this.chunkRadius = Math.max(3, Math.min(requestChunkRadiusPacket.radius, this.viewDistance));
chunkRadiusUpdatePacket.radius = this.chunkRadius;
this.dataPacket(chunkRadiusUpdatePacket);
break;
case ProtocolInfo.SET_PLAYER_GAME_TYPE_PACKET:
SetPlayerGameTypePacket setPlayerGameTypePacket = (SetPlayerGameTypePacket) packet;
if (setPlayerGameTypePacket.gamemode != this.gamemode) {
if (!this.hasPermission("nukkit.command.gamemode")) {
SetPlayerGameTypePacket setPlayerGameTypePacket1 = new SetPlayerGameTypePacket();
setPlayerGameTypePacket1.gamemode = this.gamemode & 0x01;
this.dataPacket(setPlayerGameTypePacket1);
this.getAdventureSettings().update();
break;
}
this.setGamemode(setPlayerGameTypePacket.gamemode, true);
Command.broadcastCommandMessage(this, new TranslationContainer("commands.gamemode.success.self", Server.getGamemodeString(this.gamemode)));
}
break;
case ProtocolInfo.ITEM_FRAME_DROP_ITEM_PACKET:
ItemFrameDropItemPacket itemFrameDropItemPacket = (ItemFrameDropItemPacket) packet;
Vector3 vector3 = this.temporalVector.setComponents(itemFrameDropItemPacket.x, itemFrameDropItemPacket.y, itemFrameDropItemPacket.z);
BlockEntity blockEntityItemFrame = this.level.getBlockEntity(vector3);
BlockEntityItemFrame itemFrame = (BlockEntityItemFrame) blockEntityItemFrame;
if (itemFrame != null) {
block = itemFrame.getBlock();
Item itemDrop = itemFrame.getItem();
ItemFrameDropItemEvent itemFrameDropItemEvent = new ItemFrameDropItemEvent(this, block, itemFrame, itemDrop);
this.server.getPluginManager().callEvent(itemFrameDropItemEvent);
if (!itemFrameDropItemEvent.isCancelled()) {
if (itemDrop.getId() != Item.AIR) {
vector3 = this.temporalVector.setComponents(itemFrame.x + 0.5, itemFrame.y, itemFrame.z + 0.5);
this.level.dropItem(vector3, itemDrop);
itemFrame.setItem(new ItemBlock(new BlockAir()));
itemFrame.setItemRotation(0);
this.getLevel().addSound(this, Sound.BLOCK_ITEMFRAME_REMOVE_ITEM);
}
} else {
itemFrame.spawnTo(this);
}
}
break;
case ProtocolInfo.MAP_INFO_REQUEST_PACKET:
MapInfoRequestPacket pk = (MapInfoRequestPacket) packet;
Item mapItem = null;
for (Item item1 : this.inventory.getContents().values()) {
if (item1 instanceof ItemMap && ((ItemMap) item1).getMapId() == pk.mapId) {
mapItem = item1;
}
}
if (mapItem == null) {
for (BlockEntity be : this.level.getBlockEntities().values()) {
if (be instanceof BlockEntityItemFrame) {
BlockEntityItemFrame itemFrame1 = (BlockEntityItemFrame) be;
if (itemFrame1.getItem() instanceof ItemMap && ((ItemMap) itemFrame1.getItem()).getMapId() == pk.mapId) {
((ItemMap) itemFrame1.getItem()).sendImage(this);
break;
}
}
}
}
if (mapItem != null) {
PlayerMapInfoRequestEvent event;
getServer().getPluginManager().callEvent(event = new PlayerMapInfoRequestEvent(this, mapItem));
if (!event.isCancelled()) {
((ItemMap) mapItem).sendImage(this);
}
}
break;
case ProtocolInfo.LEVEL_SOUND_EVENT_PACKET:
// LevelSoundEventPacket levelSoundEventPacket = (LevelSoundEventPacket) packet;
// We just need to broadcast this packet to all viewers.
this.level.addChunkPacket(this.getFloorX() >> 4, this.getFloorZ() >> 4, packet);
break;
case ProtocolInfo.INVENTORY_TRANSACTION_PACKET:
if (this.isSpectator()) {
this.sendAllInventories();
break;
}
InventoryTransactionPacket transactionPacket = (InventoryTransactionPacket) packet;
List<InventoryAction> actions = new ArrayList<>();
for (NetworkInventoryAction networkInventoryAction : transactionPacket.actions) {
InventoryAction a = networkInventoryAction.createInventoryAction(this);
if (a == null) {
this.getServer().getLogger().debug("Unmatched inventory action from " + this.getName() + ": " + networkInventoryAction);
this.sendAllInventories();
break packetswitch;
}
actions.add(a);
}
if (transactionPacket.isCraftingPart) {
if (this.craftingTransaction == null) {
this.craftingTransaction = new CraftingTransaction(this, actions);
} else {
for (InventoryAction action : actions) {
this.craftingTransaction.addAction(action);
}
}
if (this.craftingTransaction.getPrimaryOutput() != null) {
// we get the actions for this in several packets, so we can't execute it until we get the result
this.craftingTransaction.execute();
this.craftingTransaction = null;
}
return;
} else if (this.craftingTransaction != null) {
this.server.getLogger().debug("Got unexpected normal inventory action with incomplete crafting transaction from " + this.getName() + ", refusing to execute crafting");
this.craftingTransaction = null;
}
switch(transactionPacket.transactionType) {
case InventoryTransactionPacket.TYPE_NORMAL:
InventoryTransaction transaction = new InventoryTransaction(this, actions);
if (!transaction.execute()) {
this.server.getLogger().debug("Failed to execute inventory transaction from " + this.getName() + " with actions: " + Arrays.toString(transactionPacket.actions));
// oops!
break packetswitch;
}
break packetswitch;
case InventoryTransactionPacket.TYPE_MISMATCH:
if (transactionPacket.actions.length > 0) {
this.server.getLogger().debug("Expected 0 actions for mismatch, got " + transactionPacket.actions.length + ", " + Arrays.toString(transactionPacket.actions));
}
this.sendAllInventories();
break packetswitch;
case InventoryTransactionPacket.TYPE_USE_ITEM:
UseItemData useItemData = (UseItemData) transactionPacket.transactionData;
BlockVector3 blockVector = useItemData.blockPos;
face = useItemData.face;
int type = useItemData.actionType;
switch(type) {
case InventoryTransactionPacket.USE_ITEM_ACTION_CLICK_BLOCK:
this.setDataFlag(DATA_FLAGS, DATA_FLAG_ACTION, false);
if (this.canInteract(blockVector.add(0.5, 0.5, 0.5), this.isCreative() ? 13 : 7)) {
if (this.isCreative()) {
Item i = inventory.getItemInHand();
if (this.level.useItemOn(blockVector.asVector3(), i, face, useItemData.clickPos.x, useItemData.clickPos.y, useItemData.clickPos.z, this) != null) {
break packetswitch;
}
} else if (inventory.getItemInHand().equals(useItemData.itemInHand)) {
Item i = inventory.getItemInHand();
Item oldItem = i.clone();
// TODO: Implement adventure mode checks
if ((i = this.level.useItemOn(blockVector.asVector3(), i, face, useItemData.clickPos.x, useItemData.clickPos.y, useItemData.clickPos.z, this)) != null) {
if (!i.equals(oldItem) || i.getCount() != oldItem.getCount()) {
inventory.setItemInHand(i);
inventory.sendHeldItem(this.getViewers().values());
}
break packetswitch;
}
}
}
inventory.sendHeldItem(this);
if (blockVector.distanceSquared(this) > 10000) {
break packetswitch;
}
Block target = this.level.getBlock(blockVector.asVector3());
block = target.getSide(face);
this.level.sendBlocks(new Player[] { this }, new Block[] { target, block }, UpdateBlockPacket.FLAG_ALL_PRIORITY);
if (target instanceof BlockDoor) {
BlockDoor door = (BlockDoor) target;
Block part;
if ((door.getDamage() & 0x08) > 0) {
// up
part = target.down();
if (part.getId() == target.getId()) {
target = part;
this.level.sendBlocks(new Player[] { this }, new Block[] { target }, UpdateBlockPacket.FLAG_ALL_PRIORITY);
}
}
}
break packetswitch;
case InventoryTransactionPacket.USE_ITEM_ACTION_BREAK_BLOCK:
if (!this.spawned || !this.isAlive()) {
break packetswitch;
}
this.resetCraftingGridType();
Item i = this.getInventory().getItemInHand();
Item oldItem = i.clone();
if (this.canInteract(blockVector.add(0.5, 0.5, 0.5), this.isCreative() ? 13 : 7) && (i = this.level.useBreakOn(blockVector.asVector3(), i, this, true)) != null) {
if (this.isSurvival()) {
this.getFoodData().updateFoodExpLevel(0.025);
if (!i.equals(oldItem) || i.getCount() != oldItem.getCount()) {
inventory.setItemInHand(i);
inventory.sendHeldItem(this.getViewers().values());
}
}
break packetswitch;
}
inventory.sendContents(this);
target = this.level.getBlock(blockVector.asVector3());
BlockEntity blockEntity = this.level.getBlockEntity(blockVector.asVector3());
this.level.sendBlocks(new Player[] { this }, new Block[] { target }, UpdateBlockPacket.FLAG_ALL_PRIORITY);
inventory.sendHeldItem(this);
if (blockEntity instanceof BlockEntitySpawnable) {
((BlockEntitySpawnable) blockEntity).spawnTo(this);
}
break packetswitch;
case InventoryTransactionPacket.USE_ITEM_ACTION_CLICK_AIR:
Vector3 directionVector = this.getDirectionVector();
if (this.isCreative()) {
item = this.inventory.getItemInHand();
} else if (!this.inventory.getItemInHand().equals(useItemData.itemInHand)) {
this.inventory.sendHeldItem(this);
break packetswitch;
} else {
item = this.inventory.getItemInHand();
}
PlayerInteractEvent interactEvent = new PlayerInteractEvent(this, item, directionVector, face, Action.RIGHT_CLICK_AIR);
this.server.getPluginManager().callEvent(interactEvent);
if (interactEvent.isCancelled()) {
this.inventory.sendHeldItem(this);
break packetswitch;
}
if (item.onClickAir(this, directionVector) && this.isSurvival()) {
this.inventory.setItemInHand(item);
}
this.setDataFlag(DATA_FLAGS, DATA_FLAG_ACTION, true);
this.startAction = this.server.getTick();
break packetswitch;
default:
// unknown
break;
}
break;
case InventoryTransactionPacket.TYPE_USE_ITEM_ON_ENTITY:
UseItemOnEntityData useItemOnEntityData = (UseItemOnEntityData) transactionPacket.transactionData;
Entity target = this.level.getEntity(useItemOnEntityData.entityRuntimeId);
if (target == null) {
return;
}
type = useItemOnEntityData.actionType;
if (!useItemOnEntityData.itemInHand.equalsExact(this.inventory.getItemInHand())) {
this.inventory.sendHeldItem(this);
}
item = this.inventory.getItemInHand();
switch(type) {
case InventoryTransactionPacket.USE_ITEM_ON_ENTITY_ACTION_INTERACT:
PlayerInteractEntityEvent playerInteractEntityEvent = new PlayerInteractEntityEvent(this, target, item);
if (this.isSpectator())
playerInteractEntityEvent.setCancelled();
getServer().getPluginManager().callEvent(playerInteractEntityEvent);
if (playerInteractEntityEvent.isCancelled()) {
break;
}
if (target.onInteract(this, item) && this.isSurvival()) {
if (item.isTool()) {
if (item.useOn(target) && item.getDamage() >= item.getMaxDurability()) {
item = new ItemBlock(new BlockAir());
}
} else {
if (item.count > 1) {
item.count--;
} else {
item = new ItemBlock(new BlockAir());
}
}
this.inventory.setItemInHand(item);
}
break;
case InventoryTransactionPacket.USE_ITEM_ON_ENTITY_ACTION_ATTACK:
float itemDamage = item.getAttackDamage();
for (Enchantment enchantment : item.getEnchantments()) {
itemDamage += enchantment.getDamageBonus(target);
}
Map<DamageModifier, Float> damage = new EnumMap<>(DamageModifier.class);
damage.put(DamageModifier.BASE, itemDamage);
if (!this.canInteract(target, isCreative() ? 8 : 5)) {
break;
} else if (target instanceof Player) {
if ((((Player) target).getGamemode() & 0x01) > 0) {
break;
} else if (!this.server.getPropertyBoolean("pvp") || this.server.getDifficulty() == 0) {
break;
}
}
EntityDamageByEntityEvent entityDamageByEntityEvent = new EntityDamageByEntityEvent(this, target, DamageCause.ENTITY_ATTACK, damage);
if (this.isSpectator())
entityDamageByEntityEvent.setCancelled();
if ((target instanceof Player) && !this.level.getGameRules().getBoolean(GameRule.PVP)) {
entityDamageByEntityEvent.setCancelled();
}
if (!target.attack(entityDamageByEntityEvent)) {
if (item.isTool() && this.isSurvival()) {
this.inventory.sendContents(this);
}
break;
}
for (Enchantment enchantment : item.getEnchantments()) {
enchantment.doPostAttack(this, target);
}
if (item.isTool() && this.isSurvival()) {
if (item.useOn(target) && item.getDamage() >= item.getMaxDurability()) {
this.inventory.setItemInHand(new ItemBlock(new BlockAir()));
} else {
this.inventory.setItemInHand(item);
}
}
return;
default:
// unknown
break;
}
break;
case InventoryTransactionPacket.TYPE_RELEASE_ITEM:
if (this.isSpectator()) {
this.sendAllInventories();
break packetswitch;
}
ReleaseItemData releaseItemData = (ReleaseItemData) transactionPacket.transactionData;
try {
type = releaseItemData.actionType;
switch(type) {
case InventoryTransactionPacket.RELEASE_ITEM_ACTION_RELEASE:
if (this.isUsingItem()) {
item = this.inventory.getItemInHand();
if (item.onReleaseUsing(this)) {
this.inventory.setItemInHand(item);
}
} else {
this.inventory.sendContents(this);
}
return;
case InventoryTransactionPacket.RELEASE_ITEM_ACTION_CONSUME:
Item itemInHand = this.inventory.getItemInHand();
PlayerItemConsumeEvent consumeEvent = new PlayerItemConsumeEvent(this, itemInHand);
if (itemInHand.getId() == Item.POTION) {
this.server.getPluginManager().callEvent(consumeEvent);
if (consumeEvent.isCancelled()) {
this.inventory.sendContents(this);
break;
}
Potion potion = Potion.getPotion(itemInHand.getDamage()).setSplash(false);
if (this.getGamemode() == SURVIVAL) {
--itemInHand.count;
this.inventory.setItemInHand(itemInHand);
this.inventory.addItem(new ItemGlassBottle());
}
if (potion != null) {
potion.applyPotion(this);
}
} else if (itemInHand.getId() == Item.BUCKET && itemInHand.getDamage() == 1) {
// milk
this.server.getPluginManager().callEvent(consumeEvent);
if (consumeEvent.isCancelled()) {
this.inventory.sendContents(this);
break;
}
EntityEventPacket eventPacket = new EntityEventPacket();
eventPacket.eid = this.getId();
eventPacket.event = EntityEventPacket.USE_ITEM;
this.dataPacket(eventPacket);
Server.broadcastPacket(this.getViewers().values(), eventPacket);
if (this.isSurvival()) {
itemInHand.count--;
this.inventory.setItemInHand(itemInHand);
this.inventory.addItem(new ItemBucket());
}
this.removeAllEffects();
} else {
this.server.getPluginManager().callEvent(consumeEvent);
if (consumeEvent.isCancelled()) {
this.inventory.sendContents(this);
break;
}
Food food = Food.getByRelative(itemInHand);
if (food != null && food.eatenBy(this))
--itemInHand.count;
this.inventory.setItemInHand(itemInHand);
}
return;
default:
break;
}
} finally {
this.setUsingItem(false);
}
break;
default:
this.inventory.sendContents(this);
break;
}
break;
case ProtocolInfo.PLAYER_HOTBAR_PACKET:
PlayerHotbarPacket hotbarPacket = (PlayerHotbarPacket) packet;
if (hotbarPacket.windowId != ContainerIds.INVENTORY) {
// In PE this should never happen
return;
}
this.inventory.equipItem(hotbarPacket.selectedHotbarSlot);
break;
case ProtocolInfo.SERVER_SETTINGS_REQUEST_PACKET:
PlayerServerSettingsRequestEvent settingsRequestEvent = new PlayerServerSettingsRequestEvent(this, new HashMap<>(this.serverSettings));
this.getServer().getPluginManager().callEvent(settingsRequestEvent);
if (!settingsRequestEvent.isCancelled()) {
settingsRequestEvent.getSettings().forEach((id, window) -> {
ServerSettingsResponsePacket re = new ServerSettingsResponsePacket();
re.formId = id;
re.data = window.getJSONData();
this.dataPacket(re);
});
}
break;
default:
break;
}
}
}
use of cn.nukkit.inventory.transaction.action.InventoryAction in project Nukkit by Nukkit.
the class InventoryTransaction method callExecuteEvent.
protected boolean callExecuteEvent() {
InventoryTransactionEvent ev = new InventoryTransactionEvent(this);
this.source.getServer().getPluginManager().callEvent(ev);
SlotChangeAction from = null;
SlotChangeAction to = null;
Player who = null;
for (InventoryAction action : this.actions) {
if (!(action instanceof SlotChangeAction)) {
continue;
}
SlotChangeAction slotChange = (SlotChangeAction) action;
if (slotChange.getInventory() instanceof PlayerInventory) {
who = (Player) slotChange.getInventory().getHolder();
}
if (from == null) {
from = slotChange;
} else {
to = slotChange;
}
}
if (who != null && to != null) {
if (from.getTargetItem().getCount() > from.getSourceItem().getCount()) {
from = to;
}
InventoryClickEvent ev2 = new InventoryClickEvent(who, from.getInventory(), from.getSlot(), from.getSourceItem(), from.getTargetItem());
this.source.getServer().getPluginManager().callEvent(ev2);
if (ev2.isCancelled()) {
return false;
}
}
return !ev.isCancelled();
}
use of cn.nukkit.inventory.transaction.action.InventoryAction in project Nukkit by Nukkit.
the class InventoryTransaction method squashDuplicateSlotChanges.
/**
* Iterates over SlotChangeActions in this transaction and compacts any which refer to the same inventorySlot in the same
* inventory so they can be correctly handled.
* <p>
* Under normal circumstances, the same inventorySlot would never be changed more than once in a single transaction. However,
* due to the way things like the crafting grid are "implemented" in MCPE 1.2 (a.k.a. hacked-in), we may get
* multiple inventorySlot changes referring to the same inventorySlot in a single transaction. These multiples are not even guaranteed
* to be in the correct order (inventorySlot splitting in the crafting grid for example, causes the actions to be sent in the
* wrong order), so this method also tries to chain them into order.
*
* @return bool
*/
protected boolean squashDuplicateSlotChanges() {
Map<Integer, List<SlotChangeAction>> slotChanges = new HashMap<>();
for (InventoryAction action : this.actions) {
if (action instanceof SlotChangeAction) {
int hash = Objects.hash(((SlotChangeAction) action).getInventory(), ((SlotChangeAction) action).getSlot());
List<SlotChangeAction> list = slotChanges.get(hash);
if (list == null) {
list = new ArrayList<>();
}
list.add((SlotChangeAction) action);
slotChanges.put(hash, list);
}
}
for (Entry<Integer, List<SlotChangeAction>> entry : new ArrayList<>(slotChanges.entrySet())) {
int hash = entry.getKey();
List<SlotChangeAction> list = entry.getValue();
if (list.size() == 1) {
// No need to compact inventorySlot changes if there is only one on this inventorySlot
slotChanges.remove(hash);
continue;
}
List<SlotChangeAction> originalList = new ArrayList<>(list);
SlotChangeAction originalAction = null;
Item lastTargetItem = null;
for (int i = 0; i < list.size(); i++) {
SlotChangeAction action = list.get(i);
if (action.isValid(this.source)) {
originalAction = action;
lastTargetItem = action.getTargetItem();
list.remove(i);
break;
}
}
if (originalAction == null) {
// Couldn't find any actions that had a source-item matching the current inventory inventorySlot
return false;
}
int sortedThisLoop;
do {
sortedThisLoop = 0;
for (int i = 0; i < list.size(); i++) {
SlotChangeAction action = list.get(i);
Item actionSource = action.getSourceItem();
if (actionSource.equalsExact(lastTargetItem)) {
lastTargetItem = action.getTargetItem();
list.remove(i);
sortedThisLoop++;
} else if (actionSource.equals(lastTargetItem)) {
lastTargetItem.count -= actionSource.count;
list.remove(i);
if (lastTargetItem.count == 0)
sortedThisLoop++;
}
}
} while (sortedThisLoop > 0);
if (list.size() > 0) {
// couldn't chain all the actions together
MainLogger.getLogger().debug("Failed to compact " + originalList.size() + " actions for " + this.source.getName());
return false;
}
for (SlotChangeAction action : originalList) {
this.actions.remove(action);
}
this.addAction(new SlotChangeAction(originalAction.getInventory(), originalAction.getSlot(), originalAction.getSourceItem(), lastTargetItem));
MainLogger.getLogger().debug("Successfully compacted " + originalList.size() + " actions for " + this.source.getName());
}
return true;
}
use of cn.nukkit.inventory.transaction.action.InventoryAction in project Nukkit by Nukkit.
the class InventoryTransaction method init.
protected void init(Player source, List<InventoryAction> actions) {
creationTime = System.currentTimeMillis();
this.source = source;
for (InventoryAction action : actions) {
this.addAction(action);
}
}
use of cn.nukkit.inventory.transaction.action.InventoryAction in project Nukkit by Nukkit.
the class InventoryTransaction method matchItems.
protected boolean matchItems(List<Item> needItems, List<Item> haveItems) {
for (InventoryAction action : this.actions) {
if (action.getTargetItem().getId() != Item.AIR) {
needItems.add(action.getTargetItem());
}
if (!action.isValid(this.source)) {
return false;
}
if (action.getSourceItem().getId() != Item.AIR) {
haveItems.add(action.getSourceItem());
}
}
for (Item needItem : new ArrayList<>(needItems)) {
for (Item haveItem : new ArrayList<>(haveItems)) {
if (needItem.equals(haveItem)) {
int amount = Math.min(haveItem.getCount(), needItem.getCount());
needItem.setCount(needItem.getCount() - amount);
haveItem.setCount(haveItem.getCount() - amount);
if (haveItem.getCount() == 0) {
haveItems.remove(haveItem);
}
if (needItem.getCount() == 0) {
needItems.remove(needItem);
break;
}
}
}
}
return haveItems.isEmpty() && needItems.isEmpty();
}
Aggregations