forked from BLOCKFANTASY/LOOHP-Limbo
Inventories!
This commit is contained in:
parent
949d2f34d7
commit
35c6b748c9
|
|
@ -27,6 +27,7 @@ import com.loohp.limbo.commands.DefaultCommands;
|
|||
import com.loohp.limbo.consolegui.GUI;
|
||||
import com.loohp.limbo.events.EventsManager;
|
||||
import com.loohp.limbo.file.ServerProperties;
|
||||
import com.loohp.limbo.inventory.AnvilInventory;
|
||||
import com.loohp.limbo.inventory.CustomInventory;
|
||||
import com.loohp.limbo.inventory.Inventory;
|
||||
import com.loohp.limbo.inventory.InventoryHolder;
|
||||
|
|
@ -626,7 +627,15 @@ public final class Limbo {
|
|||
}
|
||||
|
||||
public Inventory createInventory(Component title, InventoryType type, InventoryHolder holder) {
|
||||
throw new UnsupportedOperationException("This function has not been implemented yet.");
|
||||
if (!type.isCreatable()) {
|
||||
throw new UnsupportedOperationException("This InventoryType cannot be created.");
|
||||
}
|
||||
switch (type) {
|
||||
case ANVIL:
|
||||
return new AnvilInventory(title, holder);
|
||||
default:
|
||||
throw new UnsupportedOperationException("This InventoryType has not been implemented yet.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* This file is part of Limbo.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.loohp.limbo.events.inventory;
|
||||
|
||||
import com.loohp.limbo.events.Cancellable;
|
||||
import com.loohp.limbo.inventory.InventoryView;
|
||||
|
||||
public class AnvilRenameInputEvent extends InventoryEvent implements Cancellable {
|
||||
|
||||
private boolean cancelled;
|
||||
private String input;
|
||||
|
||||
public AnvilRenameInputEvent(InventoryView inventoryView, String input) {
|
||||
super(inventoryView, inventoryView.getTopInventory());
|
||||
this.input = input;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public void setInput(String input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public String getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,16 +20,86 @@
|
|||
package com.loohp.limbo.events.inventory;
|
||||
|
||||
import com.loohp.limbo.events.Cancellable;
|
||||
import com.loohp.limbo.inventory.Inventory;
|
||||
import com.loohp.limbo.inventory.ClickType;
|
||||
import com.loohp.limbo.inventory.InventoryAction;
|
||||
import com.loohp.limbo.inventory.InventoryType;
|
||||
import com.loohp.limbo.inventory.InventoryView;
|
||||
import com.loohp.limbo.player.Player;
|
||||
import com.loohp.limbo.inventory.ItemStack;
|
||||
|
||||
public class InventoryClickEvent extends InventoryEvent implements Cancellable {
|
||||
|
||||
private boolean cancelled;
|
||||
private final ClickType click;
|
||||
private final InventoryAction action;
|
||||
private InventoryType.SlotType type;
|
||||
private int whichSlot;
|
||||
private int rawSlot;
|
||||
private ItemStack current;
|
||||
private int hotbarKey;
|
||||
|
||||
public InventoryClickEvent(Player player, InventoryView inventoryView, Inventory clickedInventory) {
|
||||
super(player, inventoryView, clickedInventory);
|
||||
public InventoryClickEvent(InventoryView view, InventoryType.SlotType type, int rawSlot, ClickType click, InventoryAction action) {
|
||||
super(view, view.getInventory(rawSlot));
|
||||
this.type = type;
|
||||
this.rawSlot = rawSlot;
|
||||
this.whichSlot = view.convertSlot(rawSlot);
|
||||
this.click = click;
|
||||
this.action = action;
|
||||
this.current = null;
|
||||
this.hotbarKey = -1;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public InventoryClickEvent(InventoryView view, InventoryType.SlotType type, int rawSlot, ClickType click, InventoryAction action, int hotbarKey) {
|
||||
this(view, type, rawSlot, click, action);
|
||||
this.hotbarKey = hotbarKey;
|
||||
}
|
||||
|
||||
public ClickType getClick() {
|
||||
return click;
|
||||
}
|
||||
|
||||
public InventoryAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public InventoryType.SlotType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getWhichSlot() {
|
||||
return whichSlot;
|
||||
}
|
||||
|
||||
public int getRawSlot() {
|
||||
return rawSlot;
|
||||
}
|
||||
|
||||
public int getHotbarKey() {
|
||||
return hotbarKey;
|
||||
}
|
||||
|
||||
public ItemStack getCarriedItem() {
|
||||
return getView().getCarriedItem();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setCarriedItem(ItemStack stack) {
|
||||
getView().setCarriedItem(stack);
|
||||
}
|
||||
|
||||
public ItemStack getCurrentItem() {
|
||||
if (type == InventoryType.SlotType.OUTSIDE) {
|
||||
return current;
|
||||
}
|
||||
return getView().getItem(rawSlot);
|
||||
}
|
||||
|
||||
public void setCurrentItem(ItemStack stack) {
|
||||
if (type == InventoryType.SlotType.OUTSIDE) {
|
||||
current = stack;
|
||||
} else {
|
||||
getView().setItem(rawSlot, stack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -20,12 +20,11 @@
|
|||
package com.loohp.limbo.events.inventory;
|
||||
|
||||
import com.loohp.limbo.inventory.InventoryView;
|
||||
import com.loohp.limbo.player.Player;
|
||||
|
||||
public class InventoryCloseEvent extends InventoryEvent {
|
||||
|
||||
public InventoryCloseEvent(Player player, InventoryView inventoryView) {
|
||||
super(player, inventoryView, inventoryView.getTopInventory());
|
||||
public InventoryCloseEvent(InventoryView inventoryView) {
|
||||
super(inventoryView, inventoryView.getTopInventory());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ package com.loohp.limbo.events.inventory;
|
|||
import com.loohp.limbo.events.Cancellable;
|
||||
import com.loohp.limbo.inventory.InventoryView;
|
||||
import com.loohp.limbo.inventory.ItemStack;
|
||||
import com.loohp.limbo.player.Player;
|
||||
import com.loohp.limbo.player.PlayerInventory;
|
||||
|
||||
public class InventoryCreativeEvent extends InventoryEvent implements Cancellable {
|
||||
|
||||
|
|
@ -31,8 +29,8 @@ public class InventoryCreativeEvent extends InventoryEvent implements Cancellabl
|
|||
private final int slot;
|
||||
private ItemStack newItem;
|
||||
|
||||
public InventoryCreativeEvent(Player player, InventoryView inventoryView, PlayerInventory playerInventory, int slot, ItemStack newItem) {
|
||||
super(player, inventoryView, playerInventory);
|
||||
public InventoryCreativeEvent(InventoryView inventoryView, int slot, ItemStack newItem) {
|
||||
super(inventoryView, inventoryView.getBottomInventory());
|
||||
this.slot = slot;
|
||||
this.newItem = newItem;
|
||||
this.cancelled = false;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* This file is part of Limbo.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.loohp.limbo.events.inventory;
|
||||
|
||||
import com.loohp.limbo.events.Cancellable;
|
||||
import com.loohp.limbo.inventory.DragType;
|
||||
import com.loohp.limbo.inventory.InventoryView;
|
||||
import com.loohp.limbo.inventory.ItemStack;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class InventoryDragEvent extends InventoryEvent implements Cancellable {
|
||||
|
||||
private boolean cancelled;
|
||||
private final DragType type;
|
||||
private final Map<Integer, ItemStack> addedItems;
|
||||
private final Set<Integer> containerSlots;
|
||||
private final ItemStack oldCarried;
|
||||
private ItemStack newCarried;
|
||||
|
||||
public InventoryDragEvent(InventoryView view, ItemStack newCarried, ItemStack oldCarried, boolean right, Map<Integer, ItemStack> slots) {
|
||||
super(view, view.getInventory(view.convertSlot(slots.keySet().iterator().next())));
|
||||
this.type = right ? DragType.SINGLE : DragType.EVEN;
|
||||
this.newCarried = newCarried;
|
||||
this.oldCarried = oldCarried;
|
||||
this.addedItems = Collections.unmodifiableMap(slots);
|
||||
Set<Integer> containerSlots = new HashSet<>();
|
||||
for (Integer slot : slots.keySet()) {
|
||||
containerSlots.add(view.convertSlot(slot));
|
||||
}
|
||||
this.containerSlots = Collections.unmodifiableSet(containerSlots);
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public Map<Integer, ItemStack> getNewItems() {
|
||||
return addedItems;
|
||||
}
|
||||
|
||||
public Set<Integer> getRawSlots() {
|
||||
return addedItems.keySet();
|
||||
}
|
||||
|
||||
public Set<Integer> getInventorySlots() {
|
||||
return containerSlots;
|
||||
}
|
||||
|
||||
public ItemStack get() {
|
||||
return newCarried;
|
||||
}
|
||||
|
||||
public ItemStack getCarriedItem() {
|
||||
return newCarried;
|
||||
}
|
||||
|
||||
public void setCarriedItem(ItemStack newCursor) {
|
||||
this.newCarried = newCursor;
|
||||
}
|
||||
|
||||
public ItemStack getOldCarriedItem() {
|
||||
return oldCarried.clone();
|
||||
}
|
||||
|
||||
public DragType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -25,22 +25,20 @@ import com.loohp.limbo.inventory.InventoryView;
|
|||
import com.loohp.limbo.player.Player;
|
||||
|
||||
public class InventoryEvent extends Event {
|
||||
|
||||
private final Player player;
|
||||
|
||||
private final InventoryView inventoryView;
|
||||
private final Inventory clickedInventory;
|
||||
|
||||
public InventoryEvent(Player player, InventoryView inventoryView, Inventory clickedInventory) {
|
||||
this.player = player;
|
||||
public InventoryEvent(InventoryView inventoryView, Inventory clickedInventory) {
|
||||
this.inventoryView = inventoryView;
|
||||
this.clickedInventory = clickedInventory;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
return inventoryView.getPlayer();
|
||||
}
|
||||
|
||||
public InventoryView getInventoryView() {
|
||||
public InventoryView getView() {
|
||||
return inventoryView;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,14 +21,13 @@ package com.loohp.limbo.events.inventory;
|
|||
|
||||
import com.loohp.limbo.events.Cancellable;
|
||||
import com.loohp.limbo.inventory.InventoryView;
|
||||
import com.loohp.limbo.player.Player;
|
||||
|
||||
public class InventoryOpenEvent extends InventoryEvent implements Cancellable {
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
public InventoryOpenEvent(Player player, InventoryView inventoryView) {
|
||||
super(player, inventoryView, inventoryView.getTopInventory());
|
||||
public InventoryOpenEvent(InventoryView inventoryView) {
|
||||
super(inventoryView, inventoryView.getTopInventory());
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,22 +24,23 @@ import com.loohp.limbo.player.Player;
|
|||
|
||||
public class PlayerSelectedSlotChangeEvent extends PlayerEvent implements Cancellable {
|
||||
|
||||
private boolean cancel = false;
|
||||
private boolean cancelled;
|
||||
private byte slot;
|
||||
|
||||
public PlayerSelectedSlotChangeEvent(Player player, byte slot) {
|
||||
super(player);
|
||||
this.slot = slot;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancel = cancelled;
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
public byte getSlot() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* This file is part of Limbo.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.loohp.limbo.events.player;
|
||||
|
||||
import com.loohp.limbo.events.Cancellable;
|
||||
import com.loohp.limbo.inventory.ItemStack;
|
||||
import com.loohp.limbo.player.Player;
|
||||
|
||||
public class PlayerSwapHandItemsEvent extends PlayerEvent implements Cancellable {
|
||||
|
||||
private boolean cancelled;
|
||||
private ItemStack mainHandItem;
|
||||
private ItemStack offHandItem;
|
||||
|
||||
public PlayerSwapHandItemsEvent(Player player, ItemStack mainHandItem, ItemStack offHandItem) {
|
||||
super(player);
|
||||
this.mainHandItem = mainHandItem;
|
||||
this.offHandItem = offHandItem;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public ItemStack getMainHandItem() {
|
||||
return mainHandItem;
|
||||
}
|
||||
|
||||
public void setMainHandItem(ItemStack mainHandItem) {
|
||||
this.mainHandItem = mainHandItem;
|
||||
}
|
||||
|
||||
public ItemStack getOffHandItem() {
|
||||
return offHandItem;
|
||||
}
|
||||
|
||||
public void setOffHandItem(ItemStack offHandItem) {
|
||||
this.offHandItem = offHandItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package com.loohp.limbo.inventory;
|
||||
|
||||
import com.loohp.limbo.location.Location;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutSetSlot;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutWindowItems;
|
||||
import com.loohp.limbo.player.Player;
|
||||
|
|
@ -109,6 +110,11 @@ public abstract class AbstractInventory implements Inventory {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return inventoryHolder == null ? null : inventoryHolder.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return inventory.length();
|
||||
|
|
@ -311,7 +317,7 @@ public abstract class AbstractInventory implements Inventory {
|
|||
public boolean contains(ItemStack item) {
|
||||
for (int i = 0; i < inventory.length(); i++) {
|
||||
ItemStack itemStack = getItem(i);
|
||||
if (itemStack.equals(item)) {
|
||||
if (Objects.equals(itemStack, item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -525,6 +531,9 @@ public abstract class AbstractInventory implements Inventory {
|
|||
|
||||
@Deprecated
|
||||
public void a(int index, ItemStack itemStack) {
|
||||
if (itemStack != null && itemStack.type().equals(ItemStack.AIR.type())) {
|
||||
itemStack = null;
|
||||
}
|
||||
inventory.inventory.set(index, itemStack);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* This file is part of Limbo.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.loohp.limbo.inventory;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class AnvilInventory extends AbstractInventory implements TitledInventory {
|
||||
|
||||
public static final Component DEFAULT_TITLE = Component.translatable("container.repair");
|
||||
|
||||
private Component title;
|
||||
|
||||
public AnvilInventory(Component title, InventoryHolder inventoryHolder) {
|
||||
super(InventoryType.ANVIL.getDefaultSize(), inventoryHolder, InventoryType.ANVIL, null, null);
|
||||
this.title = title == null ? DEFAULT_TITLE : title;
|
||||
}
|
||||
|
||||
public void setTitle(Component title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTitle() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package com.loohp.limbo.inventory;
|
||||
|
||||
/**
|
||||
* What the client did to trigger this action (not the result).
|
||||
*/
|
||||
public enum ClickType {
|
||||
|
||||
/**
|
||||
* The left (or primary) mouse button.
|
||||
*/
|
||||
LEFT,
|
||||
/**
|
||||
* Holding shift while pressing the left mouse button.
|
||||
*/
|
||||
SHIFT_LEFT,
|
||||
/**
|
||||
* The right mouse button.
|
||||
*/
|
||||
RIGHT,
|
||||
/**
|
||||
* Holding shift while pressing the right mouse button.
|
||||
*/
|
||||
SHIFT_RIGHT,
|
||||
/**
|
||||
* Clicking the left mouse button on the grey area around the inventory.
|
||||
*/
|
||||
WINDOW_BORDER_LEFT,
|
||||
/**
|
||||
* Clicking the right mouse button on the grey area around the inventory.
|
||||
*/
|
||||
WINDOW_BORDER_RIGHT,
|
||||
/**
|
||||
* The middle mouse button, or a "scrollwheel click".
|
||||
*/
|
||||
MIDDLE,
|
||||
/**
|
||||
* One of the number keys 1-9, correspond to slots on the hotbar.
|
||||
*/
|
||||
NUMBER_KEY,
|
||||
/**
|
||||
* Pressing the left mouse button twice in quick succession.
|
||||
*/
|
||||
DOUBLE_CLICK,
|
||||
/**
|
||||
* The "Drop" key (defaults to Q).
|
||||
*/
|
||||
DROP,
|
||||
/**
|
||||
* Holding Ctrl while pressing the "Drop" key (defaults to Q).
|
||||
*/
|
||||
CONTROL_DROP,
|
||||
/**
|
||||
* Any action done with the Creative inventory open.
|
||||
*/
|
||||
CREATIVE,
|
||||
/**
|
||||
* The "swap item with offhand" key (defaults to F).
|
||||
*/
|
||||
SWAP_OFFHAND,
|
||||
/**
|
||||
* A type of inventory manipulation not yet recognized by Bukkit.
|
||||
* <p>
|
||||
* This is only for transitional purposes on a new Minecraft update, and
|
||||
* should never be relied upon.
|
||||
* <p>
|
||||
* Any ClickType.UNKNOWN is called on a best-effort basis.
|
||||
*/
|
||||
UNKNOWN,
|
||||
;
|
||||
|
||||
/**
|
||||
* Gets whether this ClickType represents the pressing of a key on a
|
||||
* keyboard.
|
||||
*
|
||||
* @return true if this ClickType represents the pressing of a key
|
||||
*/
|
||||
public boolean isKeyboardClick() {
|
||||
return (this == ClickType.NUMBER_KEY) || (this == ClickType.DROP) || (this == ClickType.CONTROL_DROP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this ClickType represents an action that can only be
|
||||
* performed by a Player in creative mode.
|
||||
*
|
||||
* @return true if this action requires Creative mode
|
||||
*/
|
||||
public boolean isCreativeAction() {
|
||||
// Why use middle click?
|
||||
return (this == ClickType.MIDDLE) || (this == ClickType.CREATIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this ClickType represents a right click.
|
||||
*
|
||||
* @return true if this ClickType represents a right click
|
||||
*/
|
||||
public boolean isRightClick() {
|
||||
return (this == ClickType.RIGHT) || (this == ClickType.SHIFT_RIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this ClickType represents a left click.
|
||||
*
|
||||
* @return true if this ClickType represents a left click
|
||||
*/
|
||||
public boolean isLeftClick() {
|
||||
return (this == ClickType.LEFT) || (this == ClickType.SHIFT_LEFT) || (this == ClickType.DOUBLE_CLICK) || (this == ClickType.CREATIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this ClickType indicates that the shift key was pressed
|
||||
* down when the click was made.
|
||||
*
|
||||
* @return true if the action uses Shift.
|
||||
*/
|
||||
public boolean isShiftClick() {
|
||||
return (this == ClickType.SHIFT_LEFT) || (this == ClickType.SHIFT_RIGHT) || (this == ClickType.CONTROL_DROP);
|
||||
}
|
||||
}
|
||||
|
|
@ -49,9 +49,4 @@ public class CustomInventory extends AbstractInventory implements TitledInventor
|
|||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package com.loohp.limbo.inventory;
|
||||
|
||||
/**
|
||||
* Represents the effect of a drag that will be applied to an Inventory in an
|
||||
* InventoryDragEvent.
|
||||
*/
|
||||
public enum DragType {
|
||||
/**
|
||||
* One item from the cursor is placed in each selected slot.
|
||||
*/
|
||||
SINGLE,
|
||||
/**
|
||||
* The cursor is split evenly across all selected slots, not to exceed the
|
||||
* Material's max stack size, with the remainder going to the cursor.
|
||||
*/
|
||||
EVEN,
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
package com.loohp.limbo.inventory;
|
||||
|
||||
/**
|
||||
* An estimation of what the result will be.
|
||||
*/
|
||||
public enum InventoryAction {
|
||||
|
||||
/**
|
||||
* Nothing will happen from the click.
|
||||
* <p>
|
||||
* There may be cases where nothing will happen and this is value is not
|
||||
* provided, but it is guaranteed that this value is accurate when given.
|
||||
*/
|
||||
NOTHING,
|
||||
/**
|
||||
* All of the items on the clicked slot are moved to the cursor.
|
||||
*/
|
||||
PICKUP_ALL,
|
||||
/**
|
||||
* Some of the items on the clicked slot are moved to the cursor.
|
||||
*/
|
||||
PICKUP_SOME,
|
||||
/**
|
||||
* Half of the items on the clicked slot are moved to the cursor.
|
||||
*/
|
||||
PICKUP_HALF,
|
||||
/**
|
||||
* One of the items on the clicked slot are moved to the cursor.
|
||||
*/
|
||||
PICKUP_ONE,
|
||||
/**
|
||||
* All of the items on the cursor are moved to the clicked slot.
|
||||
*/
|
||||
PLACE_ALL,
|
||||
/**
|
||||
* Some of the items from the cursor are moved to the clicked slot
|
||||
* (usually up to the max stack size).
|
||||
*/
|
||||
PLACE_SOME,
|
||||
/**
|
||||
* A single item from the cursor is moved to the clicked slot.
|
||||
*/
|
||||
PLACE_ONE,
|
||||
/**
|
||||
* The clicked item and the cursor are exchanged.
|
||||
*/
|
||||
SWAP_WITH_CURSOR,
|
||||
/**
|
||||
* The entire cursor item is dropped.
|
||||
*/
|
||||
DROP_ALL_CURSOR,
|
||||
/**
|
||||
* One item is dropped from the cursor.
|
||||
*/
|
||||
DROP_ONE_CURSOR,
|
||||
/**
|
||||
* The entire clicked slot is dropped.
|
||||
*/
|
||||
DROP_ALL_SLOT,
|
||||
/**
|
||||
* One item is dropped from the clicked slot.
|
||||
*/
|
||||
DROP_ONE_SLOT,
|
||||
/**
|
||||
* The item is moved to the opposite inventory if a space is found.
|
||||
*/
|
||||
MOVE_TO_OTHER_INVENTORY,
|
||||
/**
|
||||
* The clicked item is moved to the hotbar, and the item currently there
|
||||
* is re-added to the player's inventory.
|
||||
*
|
||||
* The hotbar includes the player's off hand.
|
||||
*/
|
||||
HOTBAR_MOVE_AND_READD,
|
||||
/**
|
||||
* The clicked slot and the picked hotbar slot are swapped.
|
||||
*
|
||||
* The hotbar includes the player's off hand.
|
||||
*/
|
||||
HOTBAR_SWAP,
|
||||
/**
|
||||
* A max-size stack of the clicked item is put on the cursor.
|
||||
*/
|
||||
CLONE_STACK,
|
||||
/**
|
||||
* The inventory is searched for the same material, and they are put on
|
||||
* the cursor up to {@link ItemStack#getMaxStackSize()}.
|
||||
*/
|
||||
COLLECT_TO_CURSOR,
|
||||
/**
|
||||
* An unrecognized ClickType.
|
||||
*/
|
||||
UNKNOWN,
|
||||
;
|
||||
}
|
||||
|
|
@ -19,10 +19,14 @@
|
|||
|
||||
package com.loohp.limbo.inventory;
|
||||
|
||||
import com.loohp.limbo.location.Location;
|
||||
|
||||
public interface InventoryHolder {
|
||||
|
||||
Inventory getInventory();
|
||||
|
||||
InventoryHolder getHolder();
|
||||
|
||||
Location getLocation();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,11 @@
|
|||
|
||||
package com.loohp.limbo.inventory;
|
||||
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutSetSlot;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutWindowData;
|
||||
import com.loohp.limbo.player.Player;
|
||||
import com.loohp.limbo.player.PlayerInventory;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
|
@ -29,8 +32,10 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
public class InventoryView {
|
||||
|
||||
public static final int OUTSIDE = -999;
|
||||
|
||||
private final Player player;
|
||||
private final String title;
|
||||
private Component title;
|
||||
private Inventory topInventory;
|
||||
private final Inventory bottomInventory;
|
||||
private final Map<Property, Integer> properties;
|
||||
|
|
@ -38,7 +43,7 @@ public class InventoryView {
|
|||
|
||||
private final Unsafe unsafe;
|
||||
|
||||
public InventoryView(Player player, String title, Inventory topInventory, Inventory bottomInventory) {
|
||||
public InventoryView(Player player, Component title, Inventory topInventory, Inventory bottomInventory) {
|
||||
this.player = player;
|
||||
this.title = title;
|
||||
this.topInventory = topInventory;
|
||||
|
|
@ -58,14 +63,14 @@ public class InventoryView {
|
|||
}
|
||||
|
||||
public InventoryType getType() {
|
||||
return topInventory.getType();
|
||||
return topInventory == null ? bottomInventory.getType() : topInventory.getType();
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
public Component getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
|
|
@ -81,29 +86,237 @@ public class InventoryView {
|
|||
return Collections.unmodifiableMap(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the inventory corresponding to the given raw slot ID.
|
||||
*
|
||||
* If the slot ID is {@link #OUTSIDE} null will be returned, otherwise
|
||||
* behaviour for illegal and negative slot IDs is undefined.
|
||||
*
|
||||
* May be used with {@link #convertSlot(int)} to directly index an
|
||||
* underlying inventory.
|
||||
*
|
||||
* @param rawSlot The raw slot ID.
|
||||
* @return corresponding inventory, or null
|
||||
*/
|
||||
public Inventory getInventory(int rawSlot) {
|
||||
// Slot may be -1 if not properly detected due to client bug
|
||||
// e.g. dropping an item into part of the enchantment list section of an enchanting table
|
||||
if (rawSlot == OUTSIDE || rawSlot == -1) {
|
||||
return null;
|
||||
}
|
||||
if (rawSlot < 0) {
|
||||
throw new IllegalArgumentException("Negative, non outside slot " + rawSlot);
|
||||
}
|
||||
if (rawSlot >= countSlots()) {
|
||||
throw new IllegalArgumentException("Slot " + rawSlot + " greater than inventory slot count");
|
||||
}
|
||||
|
||||
if (rawSlot < topInventory.getSize()) {
|
||||
return getTopInventory();
|
||||
} else {
|
||||
return getBottomInventory();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a raw slot ID into its local slot ID into whichever of the two
|
||||
* inventories the slot points to.
|
||||
* <p>
|
||||
* If the raw slot refers to the upper inventory, it will be returned
|
||||
* unchanged and thus be suitable for getTopInventory().getItem(); if it
|
||||
* refers to the lower inventory, the output will differ from the input
|
||||
* and be suitable for getBottomInventory().getItem().
|
||||
*
|
||||
* @param rawSlot The raw slot ID.
|
||||
* @return The converted slot ID.
|
||||
*/
|
||||
public int convertSlot(int rawSlot) {
|
||||
int numInTop = topInventory == null ? 0 : topInventory.getSize();
|
||||
// Index from the top inventory as having slots from [0,size]
|
||||
if (rawSlot < numInTop) {
|
||||
return rawSlot;
|
||||
}
|
||||
|
||||
// Move down the slot index by the top size
|
||||
int slot = rawSlot - numInTop;
|
||||
|
||||
// Player crafting slots are indexed differently. The matrix is caught by the first return.
|
||||
// Creative mode is the same, except that you can't see the crafting slots (but the IDs are still used)
|
||||
if (getType() == InventoryType.CRAFTING || getType() == InventoryType.CREATIVE) {
|
||||
/*
|
||||
* Raw Slots:
|
||||
*
|
||||
* 5 1 2 0
|
||||
* 6 3 4
|
||||
* 7
|
||||
* 8 45
|
||||
* 9 10 11 12 13 14 15 16 17
|
||||
* 18 19 20 21 22 23 24 25 26
|
||||
* 27 28 29 30 31 32 33 34 35
|
||||
* 36 37 38 39 40 41 42 43 44
|
||||
*/
|
||||
|
||||
/*
|
||||
* Converted Slots:
|
||||
*
|
||||
* 39 1 2 0
|
||||
* 38 3 4
|
||||
* 37
|
||||
* 36 40
|
||||
* 9 10 11 12 13 14 15 16 17
|
||||
* 18 19 20 21 22 23 24 25 26
|
||||
* 27 28 29 30 31 32 33 34 35
|
||||
* 0 1 2 3 4 5 6 7 8
|
||||
*/
|
||||
|
||||
if (slot < 4) {
|
||||
// Send [5,8] to [39,36]
|
||||
return 39 - slot;
|
||||
} else if (slot > 39) {
|
||||
// Slot lives in the extra slot section
|
||||
return slot;
|
||||
} else {
|
||||
// Reset index so 9 -> 0
|
||||
slot -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
// 27 = 36 - 9
|
||||
if (slot >= 27) {
|
||||
// Put into hotbar section
|
||||
slot -= 27;
|
||||
} else {
|
||||
// Take out of hotbar section
|
||||
// 9 = 36 - 27
|
||||
slot += 9;
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the type of the slot by its raw slot ID.
|
||||
* <p>
|
||||
* If the type of the slot is unknown, then
|
||||
* {@link InventoryType.SlotType#CONTAINER} will be returned.
|
||||
*
|
||||
* @param slot The raw slot ID
|
||||
* @return the slot type
|
||||
*/
|
||||
public InventoryType.SlotType getSlotType(int slot) {
|
||||
InventoryType.SlotType type = InventoryType.SlotType.CONTAINER;
|
||||
if (topInventory != null && slot >= 0 && slot < topInventory.getSize()) {
|
||||
switch (this.getType()) {
|
||||
case BLAST_FURNACE:
|
||||
case FURNACE:
|
||||
case SMOKER:
|
||||
if (slot == 2) {
|
||||
type = InventoryType.SlotType.RESULT;
|
||||
} else if (slot == 1) {
|
||||
type = InventoryType.SlotType.FUEL;
|
||||
} else {
|
||||
type = InventoryType.SlotType.CRAFTING;
|
||||
}
|
||||
break;
|
||||
case BREWING:
|
||||
if (slot == 3) {
|
||||
type = InventoryType.SlotType.FUEL;
|
||||
} else {
|
||||
type = InventoryType.SlotType.CRAFTING;
|
||||
}
|
||||
break;
|
||||
case ENCHANTING:
|
||||
case BEACON:
|
||||
type = InventoryType.SlotType.CRAFTING;
|
||||
break;
|
||||
case WORKBENCH:
|
||||
case CRAFTING:
|
||||
if (slot == 0) {
|
||||
type = InventoryType.SlotType.RESULT;
|
||||
} else {
|
||||
type = InventoryType.SlotType.CRAFTING;
|
||||
}
|
||||
break;
|
||||
case ANVIL:
|
||||
case SMITHING:
|
||||
case CARTOGRAPHY:
|
||||
case GRINDSTONE:
|
||||
case MERCHANT:
|
||||
if (slot == 2) {
|
||||
type = InventoryType.SlotType.RESULT;
|
||||
} else {
|
||||
type = InventoryType.SlotType.CRAFTING;
|
||||
}
|
||||
break;
|
||||
case STONECUTTER:
|
||||
if (slot == 1) {
|
||||
type = InventoryType.SlotType.RESULT;
|
||||
} else {
|
||||
type = InventoryType.SlotType.CRAFTING;
|
||||
}
|
||||
break;
|
||||
case LOOM:
|
||||
if (slot == 3) {
|
||||
type = InventoryType.SlotType.RESULT;
|
||||
} else {
|
||||
type = InventoryType.SlotType.CRAFTING;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Nothing to do, it's a CONTAINER slot
|
||||
}
|
||||
} else {
|
||||
if (slot < 0) {
|
||||
type = InventoryType.SlotType.OUTSIDE;
|
||||
} else if (this.getType() == InventoryType.CRAFTING) { // Also includes creative inventory
|
||||
if (slot < 9) {
|
||||
type = InventoryType.SlotType.ARMOR;
|
||||
} else if (slot > 35) {
|
||||
type = InventoryType.SlotType.QUICKBAR;
|
||||
}
|
||||
} else if (slot >= (this.countSlots() - (9 + 4 + 1))) { // Quickbar, Armor, Offhand
|
||||
type = InventoryType.SlotType.QUICKBAR;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the total number of slots in this view, combining the upper and
|
||||
* lower inventories.
|
||||
* <p>
|
||||
* Note though that it's possible for this to be greater than the sum of
|
||||
* the two inventories if for example some slots are not being used.
|
||||
*
|
||||
* @return The total size
|
||||
*/
|
||||
public int countSlots() {
|
||||
return topInventory.getSize() + bottomInventory.getSize();
|
||||
return (topInventory == null ? 0 : topInventory.getSize()) + bottomInventory.getSize();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
player.closeInventory();
|
||||
}
|
||||
|
||||
public boolean isSlot(int index) {
|
||||
if (topInventory != null) {
|
||||
if (index < topInventory.getSize()) {
|
||||
return true;
|
||||
}
|
||||
index -= topInventory.getSize();
|
||||
}
|
||||
if (bottomInventory instanceof PlayerInventory) {
|
||||
return index < 36;
|
||||
}
|
||||
return index < bottomInventory.getSize();
|
||||
}
|
||||
|
||||
public ItemStack getItem(int index) {
|
||||
if (topInventory != null) {
|
||||
if (index < topInventory.getSize()) {
|
||||
return topInventory.getItem(topInventory.getUnsafe().b().applyAsInt(index));
|
||||
}
|
||||
index -= topInventory.getSize();
|
||||
}
|
||||
return bottomInventory.getItem(bottomInventory.getUnsafe().b().applyAsInt(index));
|
||||
return getInventory(index).getItem(convertSlot(index));
|
||||
}
|
||||
|
||||
public void setItem(int index, ItemStack itemStack) {
|
||||
if (topInventory != null) {
|
||||
if (index < topInventory.getSize()) {
|
||||
topInventory.setItem(topInventory.getUnsafe().b().applyAsInt(index), itemStack);
|
||||
return;
|
||||
}
|
||||
index -= topInventory.getSize();
|
||||
}
|
||||
bottomInventory.setItem(bottomInventory.getUnsafe().b().applyAsInt(index), itemStack);
|
||||
getInventory(index).setItem(convertSlot(index), itemStack);
|
||||
}
|
||||
|
||||
public void setProperty(InventoryView.Property prop, int value) {
|
||||
|
|
@ -121,6 +334,18 @@ public class InventoryView {
|
|||
}
|
||||
}
|
||||
|
||||
public void updateView() {
|
||||
if (topInventory != null) {
|
||||
topInventory.updateInventory(player);
|
||||
}
|
||||
bottomInventory.updateInventory(player);
|
||||
try {
|
||||
player.clientConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, 0, carriedItem));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||
@Deprecated
|
||||
public Unsafe getUnsafe() {
|
||||
|
|
@ -139,10 +364,20 @@ public class InventoryView {
|
|||
}
|
||||
|
||||
@Deprecated
|
||||
public void a(Inventory topInventory) {
|
||||
public void a(Inventory topInventory, Component title) {
|
||||
inventoryView.topInventory = topInventory;
|
||||
inventoryView.title = title;
|
||||
inventoryView.properties.clear();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int a() {
|
||||
if (inventoryView.topInventory != null) {
|
||||
return inventoryView.topInventory.getUnsafe().c().getOrDefault(inventoryView.player, -1);
|
||||
}
|
||||
return inventoryView.bottomInventory.getUnsafe().c().getOrDefault(inventoryView.player, -1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -20,8 +20,12 @@
|
|||
package com.loohp.limbo.inventory;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.querz.nbt.io.SNBTUtil;
|
||||
import net.querz.nbt.tag.CompoundTag;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemStack implements Cloneable {
|
||||
|
|
@ -86,6 +90,43 @@ public class ItemStack implements Cloneable {
|
|||
return new ItemStack(material, amount, nbt == null ? null : nbt.clone());
|
||||
}
|
||||
|
||||
public Component displayName() {
|
||||
if (type().equals(AIR.type()) || nbt == null) {
|
||||
return null;
|
||||
}
|
||||
CompoundTag displayTag = nbt.getCompoundTag("display");
|
||||
if (displayTag == null) {
|
||||
return null;
|
||||
}
|
||||
String json = displayTag.getString("Name");
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return GsonComponentSerializer.gson().deserialize(json);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack displayName(Component component) {
|
||||
if (type().equals(AIR.type())) {
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
String json = GsonComponentSerializer.gson().serialize(component);
|
||||
CompoundTag nbt = this.nbt.clone();
|
||||
CompoundTag displayTag = nbt.getCompoundTag("display");
|
||||
if (displayTag == null) {
|
||||
nbt.put("display", displayTag = new CompoundTag());
|
||||
}
|
||||
displayTag.putString("Name", json);
|
||||
return nbt(nbt);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getMaxStackSize() {
|
||||
return 64;
|
||||
}
|
||||
|
|
@ -112,11 +153,21 @@ public class ItemStack implements Cloneable {
|
|||
}
|
||||
|
||||
public boolean isSimilar(ItemStack stack) {
|
||||
return material.equals(stack.material) && Objects.equals(nbt, stack.nbt);
|
||||
return stack != null && material.equals(stack.material) && Objects.equals(nbt, stack.nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(material, amount, nbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return SNBTUtil.toSNBT(getFullTag());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
package com.loohp.limbo.network;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.entity.EntityEquipment;
|
||||
import com.loohp.limbo.events.inventory.AnvilRenameInputEvent;
|
||||
import com.loohp.limbo.events.inventory.InventoryCloseEvent;
|
||||
import com.loohp.limbo.events.inventory.InventoryCreativeEvent;
|
||||
import com.loohp.limbo.events.player.PlayerInteractEvent;
|
||||
|
|
@ -30,10 +32,13 @@ import com.loohp.limbo.events.player.PlayerQuitEvent;
|
|||
import com.loohp.limbo.events.player.PlayerResourcePackStatusEvent;
|
||||
import com.loohp.limbo.events.player.PlayerSelectedSlotChangeEvent;
|
||||
import com.loohp.limbo.events.player.PlayerSpawnEvent;
|
||||
import com.loohp.limbo.events.player.PlayerSwapHandItemsEvent;
|
||||
import com.loohp.limbo.events.player.PluginMessageEvent;
|
||||
import com.loohp.limbo.events.status.StatusPingEvent;
|
||||
import com.loohp.limbo.file.ServerProperties;
|
||||
import com.loohp.limbo.inventory.AnvilInventory;
|
||||
import com.loohp.limbo.inventory.Inventory;
|
||||
import com.loohp.limbo.inventory.ItemStack;
|
||||
import com.loohp.limbo.location.Location;
|
||||
import com.loohp.limbo.network.protocol.packets.Packet;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketHandshakingIn;
|
||||
|
|
@ -44,11 +49,14 @@ import com.loohp.limbo.network.protocol.packets.PacketLoginOutDisconnect;
|
|||
import com.loohp.limbo.network.protocol.packets.PacketLoginOutLoginSuccess;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketLoginOutPluginMessaging;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketOut;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInBlockDig;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInBlockPlace;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInChat;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInCloseWindow;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInHeldItemChange;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInItemName;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInKeepAlive;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPickItem;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPosition;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPositionAndLook;
|
||||
|
|
@ -85,6 +93,7 @@ import com.loohp.limbo.network.protocol.packets.PacketStatusOutResponse;
|
|||
import com.loohp.limbo.network.protocol.packets.ServerboundChatCommandPacket;
|
||||
import com.loohp.limbo.player.Player;
|
||||
import com.loohp.limbo.player.PlayerInteractManager;
|
||||
import com.loohp.limbo.player.PlayerInventory;
|
||||
import com.loohp.limbo.utils.BungeecordAdventureConversionUtils;
|
||||
import com.loohp.limbo.utils.CheckedBiConsumer;
|
||||
import com.loohp.limbo.utils.CustomStringUtils;
|
||||
|
|
@ -92,6 +101,7 @@ import com.loohp.limbo.utils.DataTypeIO;
|
|||
import com.loohp.limbo.utils.DeclareCommands;
|
||||
import com.loohp.limbo.utils.ForwardingUtils;
|
||||
import com.loohp.limbo.utils.GameMode;
|
||||
import com.loohp.limbo.utils.InventoryClickUtils;
|
||||
import com.loohp.limbo.utils.MojangAPIUtils;
|
||||
import com.loohp.limbo.utils.MojangAPIUtils.SkinResponse;
|
||||
import com.loohp.limbo.world.BlockPosition;
|
||||
|
|
@ -99,6 +109,7 @@ import com.loohp.limbo.world.BlockState;
|
|||
import com.loohp.limbo.world.World;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
|
@ -124,7 +135,6 @@ import java.util.Arrays;
|
|||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
|
@ -668,9 +678,9 @@ public class ClientConnection extends Thread {
|
|||
sendPacket(response);
|
||||
}
|
||||
};
|
||||
System.out.println("Waiting");
|
||||
|
||||
PacketIn packetIn = channel.readPacket();
|
||||
System.out.println("Received " + packetIn.getClass());
|
||||
|
||||
if (packetIn instanceof PacketPlayInPositionAndLook) {
|
||||
PacketPlayInPositionAndLook pos = (PacketPlayInPositionAndLook) packetIn;
|
||||
Location from = player.getLocation();
|
||||
|
|
@ -757,33 +767,80 @@ public class ClientConnection extends Thread {
|
|||
Limbo.getInstance().getEventsManager().callEvent(new PlayerInteractEvent(player, PlayerInteractEvent.Action.RIGHT_CLICK_AIR, player.getEquipment().getItem(packet.getHand()), block, packet.getBlockHit().getDirection(), packet.getHand()));
|
||||
} else if (packetIn instanceof PacketPlayInSetCreativeSlot) {
|
||||
PacketPlayInSetCreativeSlot packet = (PacketPlayInSetCreativeSlot) packetIn;
|
||||
InventoryCreativeEvent event = Limbo.getInstance().getEventsManager().callEvent(new InventoryCreativeEvent(player, player.getInventoryView(), player.getInventory(), player.getInventory().getUnsafe().b().applyAsInt(packet.getSlotNumber()), packet.getItemStack()));
|
||||
InventoryCreativeEvent event = Limbo.getInstance().getEventsManager().callEvent(new InventoryCreativeEvent(player.getInventoryView(), player.getInventory().getUnsafe().b().applyAsInt(packet.getSlotNumber()), packet.getItemStack()));
|
||||
if (event.isCancelled()) {
|
||||
player.updateInventory();
|
||||
} else {
|
||||
player.getInventory().getUnsafe().b(packet.getSlotNumber(), event.getNewItem());
|
||||
player.getInventory().setItem(event.getSlot(), event.getNewItem());
|
||||
}
|
||||
} else if (packetIn instanceof PacketPlayInWindowClick) {
|
||||
PacketPlayInWindowClick packet = (PacketPlayInWindowClick) packetIn;
|
||||
/*
|
||||
InventoryCreativeEvent event = Limbo.getInstance().getEventsManager().callEvent(new InventoryCreativeEvent(player, player.getInventoryView(), player.getInventory(), player.getInventory().getUnsafe().b().applyAsInt(packet.getSlotNumber()), packet.getItemStack()));
|
||||
if (event.isCancelled()) {
|
||||
player.updateInventory();
|
||||
} else {
|
||||
player.getInventory().getUnsafe().b(packet.getSlotNumber(), event.getNewItem());
|
||||
try {
|
||||
InventoryClickUtils.handle(player, packet);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
} else if (packetIn instanceof PacketPlayInCloseWindow) {
|
||||
PacketPlayInCloseWindow packet = (PacketPlayInCloseWindow) packetIn;
|
||||
Inventory inventory = player.getInventoryView().getTopInventory();
|
||||
if (inventory != null) {
|
||||
Integer id = inventory.getUnsafe().c().get(player);
|
||||
if (id != null) {
|
||||
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(player, player.getInventoryView()));
|
||||
player.getInventoryView().getUnsafe().a(null);
|
||||
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(player.getInventoryView()));
|
||||
player.getInventoryView().getUnsafe().a(null, null);
|
||||
inventory.getUnsafe().c().remove(player);
|
||||
}
|
||||
}
|
||||
} else if (packetIn instanceof PacketPlayInBlockDig) {
|
||||
PacketPlayInBlockDig packet = (PacketPlayInBlockDig) packetIn;
|
||||
//noinspection SwitchStatementWithTooFewBranches
|
||||
switch (packet.getAction()) {
|
||||
case SWAP_ITEM_WITH_OFFHAND: {
|
||||
EntityEquipment equipment = player.getEquipment();
|
||||
PlayerSwapHandItemsEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerSwapHandItemsEvent(player, equipment.getItemInOffHand(), equipment.getItemInMainHand()));
|
||||
if (!event.isCancelled()) {
|
||||
equipment.setItemInMainHand(event.getMainHandItem());
|
||||
equipment.setItemInOffHand(event.getOffHandItem());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (packetIn instanceof PacketPlayInPickItem) {
|
||||
PacketPlayInPickItem packet = (PacketPlayInPickItem) packetIn;
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
int slot = inventory.getUnsafe().b().applyAsInt(packet.getSlot());
|
||||
int i = player.getSelectedSlot();
|
||||
byte selectedSlot = -1;
|
||||
boolean firstRun = true;
|
||||
while (selectedSlot < 0 || (!firstRun && i == player.getSelectedSlot())) {
|
||||
ItemStack itemStack = inventory.getItem(i);
|
||||
if (itemStack == null) {
|
||||
selectedSlot = (byte) i;
|
||||
break;
|
||||
}
|
||||
if (++i >= 9) {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
if (selectedSlot < 0) {
|
||||
selectedSlot = player.getSelectedSlot();
|
||||
}
|
||||
ItemStack leavingHotbar = inventory.getItem(selectedSlot);
|
||||
inventory.setItem(selectedSlot, inventory.getItem(slot));
|
||||
inventory.setItem(slot, leavingHotbar);
|
||||
player.setSelectedSlot(selectedSlot);
|
||||
} else if (packetIn instanceof PacketPlayInItemName) {
|
||||
PacketPlayInItemName packet = (PacketPlayInItemName) packetIn;
|
||||
if (player.getInventoryView().getTopInventory() instanceof AnvilInventory) {
|
||||
AnvilRenameInputEvent event = Limbo.getInstance().getEventsManager().callEvent(new AnvilRenameInputEvent(player.getInventoryView(), packet.getName()));
|
||||
if (!event.isCancelled()) {
|
||||
AnvilInventory anvilInventory = (AnvilInventory) player.getInventoryView().getTopInventory();
|
||||
ItemStack result = anvilInventory.getItem(2);
|
||||
if (result != null) {
|
||||
result.displayName(LegacyComponentSerializer.legacySection().deserialize(event.getInput()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* This file is part of Limbo.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import com.loohp.limbo.location.BlockFace;
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
import com.loohp.limbo.world.BlockPosition;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayInBlockDig extends PacketIn {
|
||||
|
||||
public enum PlayerDigType {
|
||||
|
||||
START_DESTROY_BLOCK,
|
||||
ABORT_DESTROY_BLOCK,
|
||||
STOP_DESTROY_BLOCK,
|
||||
DROP_ALL_ITEMS,
|
||||
DROP_ITEM,
|
||||
RELEASE_USE_ITEM,
|
||||
SWAP_ITEM_WITH_OFFHAND;
|
||||
|
||||
}
|
||||
|
||||
private PlayerDigType action;
|
||||
private BlockPosition pos;
|
||||
private BlockFace direction;
|
||||
private int sequence;
|
||||
|
||||
public PacketPlayInBlockDig(PlayerDigType action, BlockPosition pos, BlockFace direction, int sequence) {
|
||||
this.action = action;
|
||||
this.pos = pos;
|
||||
this.direction = direction;
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
public PacketPlayInBlockDig(DataInputStream in) throws IOException {
|
||||
this(PlayerDigType.values()[DataTypeIO.readVarInt(in)], DataTypeIO.readBlockPosition(in), BlockFace.values()[in.readByte()], DataTypeIO.readVarInt(in));
|
||||
}
|
||||
|
||||
public BlockPosition getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
public BlockFace getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public PlayerDigType getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public int getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* This file is part of Limbo.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class PacketPlayInItemName extends PacketIn {
|
||||
|
||||
private String name;
|
||||
|
||||
public PacketPlayInItemName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public PacketPlayInItemName(DataInputStream in) throws IOException {
|
||||
this(DataTypeIO.readString(in, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* This file is part of Limbo.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.loohp.limbo.network.protocol.packets;
|
||||
|
||||
import com.loohp.limbo.utils.DataTypeIO;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketPlayInPickItem extends PacketIn {
|
||||
|
||||
private int slot;
|
||||
|
||||
public PacketPlayInPickItem(int slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public PacketPlayInPickItem(DataInputStream in) throws IOException {
|
||||
this(DataTypeIO.readVarInt(in));
|
||||
}
|
||||
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ public class PacketPlayOutPlayerAbilities extends PacketOut {
|
|||
ALLOW_FLYING(0x04),
|
||||
CREATIVE(0x08);
|
||||
|
||||
int bitvalue;
|
||||
private final int bitvalue;
|
||||
|
||||
PlayerAbilityFlags(int bitvalue) {
|
||||
this.bitvalue = bitvalue;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public class PacketPlayOutSetSlot extends PacketOut {
|
|||
this.containerId = containerId;
|
||||
this.stateId = stateId;
|
||||
this.slot = slot;
|
||||
this.itemStack = itemStack;
|
||||
this.itemStack = itemStack == null ? ItemStack.AIR : itemStack;
|
||||
}
|
||||
|
||||
public int getContainerId() {
|
||||
|
|
|
|||
|
|
@ -132,8 +132,9 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold
|
|||
}
|
||||
|
||||
public void setSelectedSlot(byte slot) {
|
||||
if(slot == selectedSlot)
|
||||
if (slot == selectedSlot) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
PacketPlayOutHeldItemChange state = new PacketPlayOutHeldItemChange(slot);
|
||||
clientConnection.sendPacket(state);
|
||||
|
|
@ -603,22 +604,22 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold
|
|||
}
|
||||
|
||||
public void openInventory(Inventory inventory) {
|
||||
inventoryView.getUnsafe().a(inventory);
|
||||
Component title = inventory instanceof TitledInventory ? ((TitledInventory) inventory).getTitle() : Component.translatable("container.chest");
|
||||
inventoryView.getUnsafe().a(inventory, title);
|
||||
int id = nextContainerId();
|
||||
inventory.getUnsafe().c().put(this, id);
|
||||
InventoryOpenEvent event = Limbo.getInstance().getEventsManager().callEvent(new InventoryOpenEvent(this, inventoryView));
|
||||
InventoryOpenEvent event = Limbo.getInstance().getEventsManager().callEvent(new InventoryOpenEvent(inventoryView));
|
||||
if (event.isCancelled()) {
|
||||
inventoryView.getUnsafe().a(null);
|
||||
inventoryView.getUnsafe().a(null, null);
|
||||
inventory.getUnsafe().c().remove(this);
|
||||
} else {
|
||||
Component title = inventory instanceof TitledInventory ? ((TitledInventory) inventory).getTitle() : Component.translatable("container.chest");
|
||||
PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, inventory.getType().getRawType(inventory.getSize()), title);
|
||||
try {
|
||||
clientConnection.sendPacket(packet);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
inventory.updateInventory(this);
|
||||
inventoryView.updateView();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -627,8 +628,8 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold
|
|||
if (inventory != null) {
|
||||
Integer id = inventory.getUnsafe().c().get(this);
|
||||
if (id != null) {
|
||||
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(this, inventoryView));
|
||||
inventoryView.getUnsafe().a(null);
|
||||
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(inventoryView));
|
||||
inventoryView.getUnsafe().a(null, null);
|
||||
inventory.getUnsafe().c().remove(this);
|
||||
PacketPlayOutCloseWindow packet = new PacketPlayOutCloseWindow(id);
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import com.loohp.limbo.inventory.AbstractInventory;
|
|||
import com.loohp.limbo.inventory.EquipmentSlot;
|
||||
import com.loohp.limbo.inventory.InventoryType;
|
||||
import com.loohp.limbo.inventory.ItemStack;
|
||||
import com.loohp.limbo.location.Location;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
|
@ -165,9 +164,4 @@ public class PlayerInventory extends AbstractInventory implements EntityEquipmen
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return player.getLocation();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,531 @@
|
|||
/*
|
||||
* This file is part of Limbo.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.loohp.limbo.utils;
|
||||
|
||||
import com.loohp.limbo.Limbo;
|
||||
import com.loohp.limbo.events.inventory.InventoryClickEvent;
|
||||
import com.loohp.limbo.events.inventory.InventoryDragEvent;
|
||||
import com.loohp.limbo.inventory.ClickType;
|
||||
import com.loohp.limbo.inventory.Inventory;
|
||||
import com.loohp.limbo.inventory.InventoryAction;
|
||||
import com.loohp.limbo.inventory.InventoryClickType;
|
||||
import com.loohp.limbo.inventory.InventoryType;
|
||||
import com.loohp.limbo.inventory.InventoryView;
|
||||
import com.loohp.limbo.inventory.ItemStack;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInWindowClick;
|
||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutSetSlot;
|
||||
import com.loohp.limbo.player.Player;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class InventoryClickUtils {
|
||||
|
||||
private static final Map<Player, QuickCraftInfo> QUICK_CRAFT_INFO = Collections.synchronizedMap(new WeakHashMap<>());
|
||||
|
||||
public static synchronized void handle(Player player, PacketPlayInWindowClick packetplayinwindowclick) {
|
||||
InventoryClickEvent event;
|
||||
|
||||
InventoryView inventory = player.getInventoryView();
|
||||
InventoryType.SlotType type = inventory.getSlotType(packetplayinwindowclick.getSlotNum());
|
||||
int rawSlot = packetplayinwindowclick.getSlotNum();
|
||||
|
||||
boolean cancelled = player.getGamemode().equals(GameMode.SPECTATOR);
|
||||
ClickType click = ClickType.UNKNOWN;
|
||||
InventoryAction action = InventoryAction.UNKNOWN;
|
||||
|
||||
ItemStack itemstack = null;
|
||||
|
||||
switch (packetplayinwindowclick.getClickType()) {
|
||||
case PICKUP:
|
||||
if (packetplayinwindowclick.getButtonNum() == 0) {
|
||||
click = ClickType.LEFT;
|
||||
} else if (packetplayinwindowclick.getButtonNum() == 1) {
|
||||
click = ClickType.RIGHT;
|
||||
}
|
||||
if (packetplayinwindowclick.getButtonNum() == 0 || packetplayinwindowclick.getButtonNum() == 1) {
|
||||
action = InventoryAction.NOTHING; // Don't want to repeat ourselves
|
||||
if (packetplayinwindowclick.getSlotNum() == -999) {
|
||||
if (inventory.getCarriedItem() != null) {
|
||||
action = packetplayinwindowclick.getButtonNum() == 0 ? InventoryAction.DROP_ALL_CURSOR : InventoryAction.DROP_ONE_CURSOR;
|
||||
}
|
||||
} else if (packetplayinwindowclick.getSlotNum() < 0) {
|
||||
action = InventoryAction.NOTHING;
|
||||
} else {
|
||||
ItemStack clickedItem = inventory.getItem(rawSlot);
|
||||
if (inventory.isSlot(rawSlot)) {
|
||||
ItemStack cursor = inventory.getCarriedItem();
|
||||
if (clickedItem == null) {
|
||||
if (cursor != null) {
|
||||
action = packetplayinwindowclick.getButtonNum() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE;
|
||||
}
|
||||
} else {
|
||||
if (cursor == null) {
|
||||
action = packetplayinwindowclick.getButtonNum() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF;
|
||||
} else {
|
||||
if (clickedItem.isSimilar(cursor)) {
|
||||
int toPlace = packetplayinwindowclick.getButtonNum() == 0 ? cursor.amount() : 1;
|
||||
toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.amount());
|
||||
toPlace = Math.min(toPlace, cursor.getMaxStackSize() - clickedItem.amount());
|
||||
if (toPlace == 1) {
|
||||
action = InventoryAction.PLACE_ONE;
|
||||
} else if (toPlace == cursor.amount()) {
|
||||
action = InventoryAction.PLACE_ALL;
|
||||
} else if (toPlace < 0) {
|
||||
action = toPlace != -1 ? InventoryAction.PICKUP_SOME : InventoryAction.PICKUP_ONE; // this happens with oversized stacks
|
||||
} else if (toPlace != 0) {
|
||||
action = InventoryAction.PLACE_SOME;
|
||||
}
|
||||
} else if (cursor.amount() <= cursor.getMaxStackSize()) {
|
||||
action = InventoryAction.SWAP_WITH_CURSOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QUICK_MOVE:
|
||||
if (packetplayinwindowclick.getButtonNum() == 0) {
|
||||
click = ClickType.SHIFT_LEFT;
|
||||
} else if (packetplayinwindowclick.getButtonNum() == 1) {
|
||||
click = ClickType.SHIFT_RIGHT;
|
||||
}
|
||||
if (packetplayinwindowclick.getButtonNum() == 0 || packetplayinwindowclick.getButtonNum() == 1) {
|
||||
if (packetplayinwindowclick.getSlotNum() < 0) {
|
||||
action = InventoryAction.NOTHING;
|
||||
} else {
|
||||
ItemStack slot = inventory.getItem(rawSlot);
|
||||
if (inventory.isSlot(rawSlot) && slot != null) {
|
||||
action = InventoryAction.MOVE_TO_OTHER_INVENTORY;
|
||||
} else {
|
||||
action = InventoryAction.NOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SWAP:
|
||||
if ((packetplayinwindowclick.getButtonNum() >= 0 && packetplayinwindowclick.getButtonNum() < 9) || packetplayinwindowclick.getButtonNum() == 40) {
|
||||
click = (packetplayinwindowclick.getButtonNum() == 40) ? ClickType.SWAP_OFFHAND : ClickType.NUMBER_KEY;
|
||||
ItemStack clickedSlot = inventory.getItem(rawSlot);
|
||||
ItemStack hotbar = inventory.getPlayer().getInventory().getItem(packetplayinwindowclick.getButtonNum());
|
||||
boolean canCleanSwap = hotbar == null || inventory.getInventory(rawSlot).equals(inventory.getPlayer().getInventory()); // the slot will accept the hotbar item
|
||||
if (clickedSlot != null) {
|
||||
if (canCleanSwap) {
|
||||
action = InventoryAction.HOTBAR_SWAP;
|
||||
} else {
|
||||
action = InventoryAction.HOTBAR_MOVE_AND_READD;
|
||||
}
|
||||
} else if (clickedSlot == null && hotbar != null) {
|
||||
action = InventoryAction.HOTBAR_SWAP;
|
||||
} else {
|
||||
action = InventoryAction.NOTHING;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLONE:
|
||||
if (packetplayinwindowclick.getButtonNum() == 2) {
|
||||
click = ClickType.MIDDLE;
|
||||
if (packetplayinwindowclick.getSlotNum() < 0) {
|
||||
action = InventoryAction.NOTHING;
|
||||
} else {
|
||||
ItemStack slot = inventory.getItem(rawSlot);
|
||||
if (inventory.isSlot(rawSlot) && slot != null && player.getGamemode().equals(GameMode.CREATIVE) && inventory.getCarriedItem() == null) {
|
||||
action = InventoryAction.CLONE_STACK;
|
||||
} else {
|
||||
action = InventoryAction.NOTHING;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
click = ClickType.UNKNOWN;
|
||||
action = InventoryAction.UNKNOWN;
|
||||
}
|
||||
break;
|
||||
case THROW:
|
||||
if (packetplayinwindowclick.getSlotNum() >= 0) {
|
||||
if (packetplayinwindowclick.getButtonNum() == 0) {
|
||||
click = ClickType.DROP;
|
||||
ItemStack slot = inventory.getItem(rawSlot);
|
||||
if (inventory.isSlot(rawSlot) && slot != null && !slot.type().equals(ItemStack.AIR.type())) {
|
||||
action = InventoryAction.DROP_ONE_SLOT;
|
||||
} else {
|
||||
action = InventoryAction.NOTHING;
|
||||
}
|
||||
} else if (packetplayinwindowclick.getButtonNum() == 1) {
|
||||
click = ClickType.CONTROL_DROP;
|
||||
ItemStack slot = inventory.getItem(rawSlot);
|
||||
if (inventory.isSlot(rawSlot) && slot != null && !slot.type().equals(ItemStack.AIR.type())) {
|
||||
action = InventoryAction.DROP_ALL_SLOT;
|
||||
} else {
|
||||
action = InventoryAction.NOTHING;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Sane default (because this happens when they are holding nothing. Don't ask why.)
|
||||
click = ClickType.LEFT;
|
||||
if (packetplayinwindowclick.getButtonNum() == 1) {
|
||||
click = ClickType.RIGHT;
|
||||
}
|
||||
action = InventoryAction.NOTHING;
|
||||
}
|
||||
break;
|
||||
case PICKUP_ALL:
|
||||
click = ClickType.DOUBLE_CLICK;
|
||||
action = InventoryAction.NOTHING;
|
||||
if (packetplayinwindowclick.getSlotNum() >= 0 && inventory.getCarriedItem() != null) {
|
||||
ItemStack cursor = inventory.getCarriedItem();
|
||||
int amount = cursor == null ? 0 : cursor.amount();
|
||||
action = InventoryAction.NOTHING;
|
||||
// Quick check for if we have any of the item
|
||||
if ((inventory.getTopInventory() != null && inventory.getTopInventory().containsAtLeast(cursor, 1)) || inventory.getBottomInventory().containsAtLeast(cursor, 1)) {
|
||||
action = InventoryAction.COLLECT_TO_CURSOR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QUICK_CRAFT: {
|
||||
QuickCraftInfo quickCraft;
|
||||
synchronized (QUICK_CRAFT_INFO) {
|
||||
quickCraft = QUICK_CRAFT_INFO.get(player);
|
||||
if (quickCraft == null) {
|
||||
QUICK_CRAFT_INFO.put(player, quickCraft = new QuickCraftInfo());
|
||||
}
|
||||
}
|
||||
int slotNum = packetplayinwindowclick.getSlotNum();
|
||||
int buttonNum = packetplayinwindowclick.getButtonNum();
|
||||
int quickcraftStatus = quickCraft.quickcraftStatus;
|
||||
ItemStack itemstack1;
|
||||
int l;
|
||||
|
||||
quickCraft.quickcraftStatus = getQuickcraftHeader(buttonNum);
|
||||
if ((quickcraftStatus != 1 || quickCraft.quickcraftStatus != 2) && quickcraftStatus != quickCraft.quickcraftStatus) {
|
||||
quickCraft.resetQuickCraft();
|
||||
} else if (inventory.getCarriedItem() == null) {
|
||||
quickCraft.resetQuickCraft();
|
||||
} else if (quickCraft.quickcraftStatus == 0) {
|
||||
quickCraft.quickcraftType = getQuickcraftType(buttonNum);
|
||||
if (isValidQuickcraftType(quickCraft.quickcraftType, player)) {
|
||||
quickCraft.quickcraftStatus = 1;
|
||||
quickCraft.quickcraftSlots.clear();
|
||||
} else {
|
||||
quickCraft.resetQuickCraft();
|
||||
}
|
||||
} else if (quickCraft.quickcraftStatus == 1) {
|
||||
itemstack = inventory.getCarriedItem();
|
||||
if (canItemQuickReplace(inventory, slotNum, itemstack, true) && (quickCraft.quickcraftType == 2 || itemstack.amount() > quickCraft.quickcraftSlots.size())) {
|
||||
quickCraft.quickcraftSlots.add(slotNum);
|
||||
}
|
||||
} else if (quickCraft.quickcraftStatus == 2) {
|
||||
if (!quickCraft.quickcraftSlots.isEmpty()) {
|
||||
itemstack1 = inventory.getCarriedItem();
|
||||
l = inventory.getCarriedItem().amount();
|
||||
Iterator<Integer> iterator = quickCraft.quickcraftSlots.iterator();
|
||||
|
||||
Map<Integer, ItemStack> draggedSlots = new HashMap<>(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack)
|
||||
while (iterator.hasNext()) {
|
||||
int slot1 = iterator.next();
|
||||
ItemStack slotItem = inventory.getItem(slot1);
|
||||
ItemStack itemstack2 = inventory.getCarriedItem();
|
||||
|
||||
if (inventory.isSlot(slot1) && canItemQuickReplace(inventory, slot1, slotItem, true) && (quickCraft.quickcraftType == 2 || itemstack2.amount() >= quickCraft.quickcraftSlots.size())) {
|
||||
ItemStack itemstack3 = itemstack1;
|
||||
int j1 = slotItem != null ? slotItem.amount() : 0;
|
||||
|
||||
itemstack3 = getQuickCraftSlotCount(quickCraft.quickcraftSlots, quickCraft.quickcraftType, itemstack3, j1);
|
||||
int k1 = Math.min(itemstack3.getMaxStackSize(), slotItem == null ? 64 : slotItem.getMaxStackSize());
|
||||
|
||||
if (itemstack3.amount() > k1) {
|
||||
itemstack3 = itemstack3.amount(k1);
|
||||
}
|
||||
|
||||
l -= itemstack3.amount() - j1;
|
||||
// slot1.set(itemstack3);
|
||||
draggedSlots.put(slot1, itemstack3); // CraftBukkit - Put in map instead of setting
|
||||
}
|
||||
}
|
||||
|
||||
// CraftBukkit start - InventoryDragEvent
|
||||
ItemStack newcursor = itemstack1.amount(l);
|
||||
|
||||
// It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory.
|
||||
ItemStack oldCursor = inventory.getCarriedItem();
|
||||
inventory.setCarriedItem(newcursor);
|
||||
|
||||
InventoryDragEvent dragEvent = new InventoryDragEvent(inventory, (newcursor.type() != ItemStack.AIR.type() ? newcursor : null), oldCursor, quickCraft.quickcraftType == 1, draggedSlots);
|
||||
Limbo.getInstance().getEventsManager().callEvent(dragEvent);
|
||||
|
||||
if (!dragEvent.isCancelled()) {
|
||||
for (Map.Entry<Integer, ItemStack> dslot : draggedSlots.entrySet()) {
|
||||
inventory.setItem(dslot.getKey(), dslot.getValue());
|
||||
}
|
||||
// The only time the carried item will be set to null is if the inventory is closed by the server.
|
||||
// If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early.
|
||||
if (inventory.getCarriedItem() != null) {
|
||||
inventory.setCarriedItem(dragEvent.getCarriedItem());
|
||||
}
|
||||
} else {
|
||||
inventory.setCarriedItem(oldCursor);
|
||||
}
|
||||
inventory.updateView();
|
||||
}
|
||||
|
||||
quickCraft.resetQuickCraft();
|
||||
} else {
|
||||
quickCraft.resetQuickCraft();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (packetplayinwindowclick.getClickType() != InventoryClickType.QUICK_CRAFT) {
|
||||
if (click == ClickType.NUMBER_KEY) {
|
||||
event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.getSlotNum(), click, action, packetplayinwindowclick.getButtonNum());
|
||||
} else {
|
||||
event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.getSlotNum(), click, action);
|
||||
}
|
||||
|
||||
event.setCancelled(cancelled);
|
||||
Inventory oldTopInventory = player.getInventoryView().getTopInventory();
|
||||
Limbo.getInstance().getEventsManager().callEvent(event);
|
||||
if (player.getInventoryView().getTopInventory() != oldTopInventory) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.isCancelled()) {
|
||||
try {
|
||||
switch (action) {
|
||||
// Modified other slots
|
||||
case PICKUP_ALL:
|
||||
case MOVE_TO_OTHER_INVENTORY:
|
||||
case HOTBAR_MOVE_AND_READD:
|
||||
case HOTBAR_SWAP:
|
||||
case COLLECT_TO_CURSOR:
|
||||
case UNKNOWN:
|
||||
player.getInventoryView().updateView();
|
||||
break;
|
||||
// Modified cursor and clicked
|
||||
case PICKUP_SOME:
|
||||
case PICKUP_HALF:
|
||||
case PICKUP_ONE:
|
||||
case PLACE_ALL:
|
||||
case PLACE_SOME:
|
||||
case PLACE_ONE:
|
||||
case SWAP_WITH_CURSOR:
|
||||
player.clientConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, 0, inventory.getCarriedItem()));
|
||||
player.clientConnection.sendPacket(new PacketPlayOutSetSlot(inventory.getUnsafe().a(), 0, packetplayinwindowclick.getSlotNum(), inventory.getItem(packetplayinwindowclick.getSlotNum())));
|
||||
break;
|
||||
// Modified clicked only
|
||||
case DROP_ALL_SLOT:
|
||||
case DROP_ONE_SLOT:
|
||||
player.clientConnection.sendPacket(new PacketPlayOutSetSlot(inventory.getUnsafe().a(), 0, packetplayinwindowclick.getSlotNum(), inventory.getItem(packetplayinwindowclick.getSlotNum())));
|
||||
break;
|
||||
// Modified cursor only
|
||||
case DROP_ALL_CURSOR:
|
||||
case DROP_ONE_CURSOR:
|
||||
case CLONE_STACK:
|
||||
player.clientConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, 0, inventory.getCarriedItem()));
|
||||
break;
|
||||
// Nothing
|
||||
case NOTHING:
|
||||
break;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
switch (event.getAction()) {
|
||||
case PICKUP_ALL: {
|
||||
inventory.setCarriedItem(event.getCurrentItem());
|
||||
inventory.setItem(event.getRawSlot(), null);
|
||||
break;
|
||||
}
|
||||
case PICKUP_SOME: {
|
||||
int amountTaken = Math.min(event.getCurrentItem().getMaxStackSize(), event.getCurrentItem().amount());
|
||||
inventory.setCarriedItem(event.getCurrentItem().amount(amountTaken));
|
||||
ItemStack oversize = event.getCurrentItem();
|
||||
inventory.setItem(event.getRawSlot(), oversize.amount(oversize.amount() - amountTaken));
|
||||
break;
|
||||
}
|
||||
case PICKUP_HALF: {
|
||||
int amountTaken = (int) Math.ceil((double) event.getCurrentItem().amount() / 2.0);
|
||||
inventory.setCarriedItem(event.getCurrentItem().amount(amountTaken));
|
||||
ItemStack left = event.getCurrentItem();
|
||||
inventory.setItem(event.getRawSlot(), left.amount(left.amount() - amountTaken));
|
||||
break;
|
||||
}
|
||||
case PICKUP_ONE: {
|
||||
inventory.setCarriedItem(event.getCurrentItem().amount(1));
|
||||
ItemStack left = event.getCurrentItem();
|
||||
inventory.setItem(event.getRawSlot(), left.amount(left.amount() - 1));
|
||||
break;
|
||||
}
|
||||
case PLACE_ALL: {
|
||||
ItemStack stack = event.getCarriedItem();
|
||||
inventory.setCarriedItem(null);
|
||||
ItemStack item = event.getCurrentItem();
|
||||
inventory.setItem(event.getRawSlot(), stack.amount((item == null ? 0 : item.amount()) + stack.amount()));
|
||||
break;
|
||||
}
|
||||
case PLACE_SOME: {
|
||||
ItemStack stack = event.getCarriedItem();
|
||||
ItemStack item = event.getCurrentItem();
|
||||
int amountPlaced = item.getMaxStackSize() - item.amount();
|
||||
inventory.setItem(event.getRawSlot(), item.amount(item.getMaxStackSize()));
|
||||
inventory.setCarriedItem(event.getCarriedItem().amount(event.getCarriedItem().amount() - amountPlaced));
|
||||
break;
|
||||
}
|
||||
case PLACE_ONE: {
|
||||
ItemStack stack = event.getCarriedItem();
|
||||
ItemStack item = event.getCurrentItem();
|
||||
inventory.setItem(event.getRawSlot(), item == null ? stack.amount(1) : item.amount(item.amount() + 1));
|
||||
inventory.setCarriedItem(event.getCarriedItem().amount(event.getCarriedItem().amount() - 1));
|
||||
break;
|
||||
}
|
||||
case SWAP_WITH_CURSOR: {
|
||||
ItemStack stack = event.getCarriedItem();
|
||||
inventory.setCarriedItem(event.getCurrentItem());
|
||||
inventory.setItem(event.getRawSlot(), stack);
|
||||
break;
|
||||
}
|
||||
case DROP_ALL_CURSOR: {
|
||||
inventory.setCarriedItem(null);
|
||||
break;
|
||||
}
|
||||
case DROP_ONE_CURSOR: {
|
||||
inventory.setCarriedItem(event.getCarriedItem().amount(event.getCarriedItem().amount() - 1));
|
||||
break;
|
||||
}
|
||||
case DROP_ALL_SLOT: {
|
||||
inventory.setItem(event.getRawSlot(), null);
|
||||
break;
|
||||
}
|
||||
case DROP_ONE_SLOT: {
|
||||
ItemStack item = event.getCurrentItem();
|
||||
inventory.setItem(event.getRawSlot(), item.amount(item.amount() - 1));
|
||||
break;
|
||||
}
|
||||
case MOVE_TO_OTHER_INVENTORY: {
|
||||
ItemStack item = event.getCurrentItem();
|
||||
Inventory inv;
|
||||
if (event.getClickedInventory() == inventory.getTopInventory()) {
|
||||
inv = inventory.getBottomInventory();
|
||||
} else {
|
||||
inv = inventory.getTopInventory();
|
||||
}
|
||||
HashMap<Integer, ItemStack> leftOver = inv.addItem(item);
|
||||
if (leftOver.isEmpty()) {
|
||||
inventory.setItem(event.getRawSlot(), null);
|
||||
} else {
|
||||
inventory.setItem(event.getRawSlot(), leftOver.values().iterator().next());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HOTBAR_MOVE_AND_READD: {
|
||||
ItemStack item = inventory.getPlayer().getInventory().getItem(event.getHotbarKey());
|
||||
inventory.getPlayer().getInventory().setItem(event.getHotbarKey(), event.getCurrentItem());
|
||||
inventory.setItem(event.getRawSlot(), null);
|
||||
inventory.getPlayer().getInventory().addItem(item);
|
||||
break;
|
||||
}
|
||||
case HOTBAR_SWAP: {
|
||||
int hotbarNum = event.getClick().equals(ClickType.SWAP_OFFHAND) ? 40 : event.getHotbarKey();
|
||||
ItemStack item = inventory.getPlayer().getInventory().getItem(hotbarNum);
|
||||
inventory.getPlayer().getInventory().setItem(hotbarNum, event.getCurrentItem());
|
||||
inventory.setItem(event.getRawSlot(), item);
|
||||
break;
|
||||
}
|
||||
case CLONE_STACK: {
|
||||
ItemStack item = event.getCurrentItem();
|
||||
inventory.setCarriedItem(item.amount(item.getMaxStackSize()));
|
||||
break;
|
||||
}
|
||||
case COLLECT_TO_CURSOR: {
|
||||
ItemStack item = event.getCarriedItem();
|
||||
ItemStack toSearch = item.amount(item.getMaxStackSize() - item.amount());
|
||||
HashMap<Integer, ItemStack> grabbed = event.getClickedInventory().removeItem(toSearch);
|
||||
int newAmount = item.amount() + toSearch.amount();
|
||||
if (!grabbed.isEmpty()) {
|
||||
newAmount -= grabbed.values().iterator().next().amount();
|
||||
}
|
||||
inventory.setCarriedItem(item.amount(newAmount));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
inventory.updateView();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getQuickcraftType(int i) {
|
||||
return i >> 2 & 3;
|
||||
}
|
||||
|
||||
public static int getQuickcraftHeader(int i) {
|
||||
return i & 3;
|
||||
}
|
||||
|
||||
public static int getQuickcraftMask(int i, int j) {
|
||||
return i & 3 | (j & 3) << 2;
|
||||
}
|
||||
|
||||
public static boolean isValidQuickcraftType(int i, Player player) {
|
||||
return i == 0 || (i == 1 || i == 2 && player.getGamemode().equals(GameMode.CREATIVE));
|
||||
}
|
||||
|
||||
public static boolean canItemQuickReplace(InventoryView view, int slot, ItemStack itemstack, boolean flag) {
|
||||
boolean flag1 = !view.isSlot(slot) || view.getItem(slot) == null;
|
||||
ItemStack slotItem = view.getItem(slot);
|
||||
return !flag1 && slotItem.isSimilar(itemstack) ? slotItem.amount() + (flag ? 0 : itemstack.amount()) <= itemstack.getMaxStackSize() : flag1;
|
||||
}
|
||||
|
||||
public static ItemStack getQuickCraftSlotCount(Set<Integer> set, int i, ItemStack itemstack, int j) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
itemstack = itemstack.amount((int) Math.floor((float) itemstack.amount() / (float) set.size()));
|
||||
break;
|
||||
case 1:
|
||||
itemstack = itemstack.amount(1);
|
||||
break;
|
||||
case 2:
|
||||
itemstack = itemstack.amount(itemstack.getMaxStackSize());
|
||||
}
|
||||
return itemstack.amount(itemstack.amount() + j);
|
||||
}
|
||||
|
||||
public static class QuickCraftInfo {
|
||||
|
||||
public int quickcraftType;
|
||||
public int quickcraftStatus;
|
||||
public final Set<Integer> quickcraftSlots = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public void resetQuickCraft() {
|
||||
quickcraftStatus = 0;
|
||||
quickcraftSlots.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -26,7 +26,10 @@
|
|||
"0x31": "PacketPlayInUseItem",
|
||||
"0x2B": "PacketPlayInSetCreativeSlot",
|
||||
"0x0A": "PacketPlayInWindowClick",
|
||||
"0x0B": "PacketPlayInCloseWindow"
|
||||
"0x0B": "PacketPlayInCloseWindow",
|
||||
"0x19": "PacketPlayInPickItem",
|
||||
"0x1C": "PacketPlayInBlockDig",
|
||||
"0x23": "PacketPlayInItemName"
|
||||
},
|
||||
"PlayOut": {
|
||||
"PacketPlayOutLogin": "0x24",
|
||||
|
|
|
|||
Loading…
Reference in New Issue