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.consolegui.GUI;
|
||||||
import com.loohp.limbo.events.EventsManager;
|
import com.loohp.limbo.events.EventsManager;
|
||||||
import com.loohp.limbo.file.ServerProperties;
|
import com.loohp.limbo.file.ServerProperties;
|
||||||
|
import com.loohp.limbo.inventory.AnvilInventory;
|
||||||
import com.loohp.limbo.inventory.CustomInventory;
|
import com.loohp.limbo.inventory.CustomInventory;
|
||||||
import com.loohp.limbo.inventory.Inventory;
|
import com.loohp.limbo.inventory.Inventory;
|
||||||
import com.loohp.limbo.inventory.InventoryHolder;
|
import com.loohp.limbo.inventory.InventoryHolder;
|
||||||
|
|
@ -626,7 +627,15 @@ public final class Limbo {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Inventory createInventory(Component title, InventoryType type, InventoryHolder holder) {
|
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;
|
package com.loohp.limbo.events.inventory;
|
||||||
|
|
||||||
import com.loohp.limbo.events.Cancellable;
|
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.inventory.InventoryView;
|
||||||
import com.loohp.limbo.player.Player;
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
|
|
||||||
public class InventoryClickEvent extends InventoryEvent implements Cancellable {
|
public class InventoryClickEvent extends InventoryEvent implements Cancellable {
|
||||||
|
|
||||||
private boolean cancelled;
|
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) {
|
public InventoryClickEvent(InventoryView view, InventoryType.SlotType type, int rawSlot, ClickType click, InventoryAction action) {
|
||||||
super(player, inventoryView, clickedInventory);
|
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
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,11 @@
|
||||||
package com.loohp.limbo.events.inventory;
|
package com.loohp.limbo.events.inventory;
|
||||||
|
|
||||||
import com.loohp.limbo.inventory.InventoryView;
|
import com.loohp.limbo.inventory.InventoryView;
|
||||||
import com.loohp.limbo.player.Player;
|
|
||||||
|
|
||||||
public class InventoryCloseEvent extends InventoryEvent {
|
public class InventoryCloseEvent extends InventoryEvent {
|
||||||
|
|
||||||
public InventoryCloseEvent(Player player, InventoryView inventoryView) {
|
public InventoryCloseEvent(InventoryView inventoryView) {
|
||||||
super(player, inventoryView, inventoryView.getTopInventory());
|
super(inventoryView, inventoryView.getTopInventory());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ package com.loohp.limbo.events.inventory;
|
||||||
import com.loohp.limbo.events.Cancellable;
|
import com.loohp.limbo.events.Cancellable;
|
||||||
import com.loohp.limbo.inventory.InventoryView;
|
import com.loohp.limbo.inventory.InventoryView;
|
||||||
import com.loohp.limbo.inventory.ItemStack;
|
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 {
|
public class InventoryCreativeEvent extends InventoryEvent implements Cancellable {
|
||||||
|
|
||||||
|
|
@ -31,8 +29,8 @@ public class InventoryCreativeEvent extends InventoryEvent implements Cancellabl
|
||||||
private final int slot;
|
private final int slot;
|
||||||
private ItemStack newItem;
|
private ItemStack newItem;
|
||||||
|
|
||||||
public InventoryCreativeEvent(Player player, InventoryView inventoryView, PlayerInventory playerInventory, int slot, ItemStack newItem) {
|
public InventoryCreativeEvent(InventoryView inventoryView, int slot, ItemStack newItem) {
|
||||||
super(player, inventoryView, playerInventory);
|
super(inventoryView, inventoryView.getBottomInventory());
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
this.newItem = newItem;
|
this.newItem = newItem;
|
||||||
this.cancelled = false;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -26,21 +26,19 @@ import com.loohp.limbo.player.Player;
|
||||||
|
|
||||||
public class InventoryEvent extends Event {
|
public class InventoryEvent extends Event {
|
||||||
|
|
||||||
private final Player player;
|
|
||||||
private final InventoryView inventoryView;
|
private final InventoryView inventoryView;
|
||||||
private final Inventory clickedInventory;
|
private final Inventory clickedInventory;
|
||||||
|
|
||||||
public InventoryEvent(Player player, InventoryView inventoryView, Inventory clickedInventory) {
|
public InventoryEvent(InventoryView inventoryView, Inventory clickedInventory) {
|
||||||
this.player = player;
|
|
||||||
this.inventoryView = inventoryView;
|
this.inventoryView = inventoryView;
|
||||||
this.clickedInventory = clickedInventory;
|
this.clickedInventory = clickedInventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player getPlayer() {
|
public Player getPlayer() {
|
||||||
return player;
|
return inventoryView.getPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public InventoryView getInventoryView() {
|
public InventoryView getView() {
|
||||||
return inventoryView;
|
return inventoryView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,13 @@ package com.loohp.limbo.events.inventory;
|
||||||
|
|
||||||
import com.loohp.limbo.events.Cancellable;
|
import com.loohp.limbo.events.Cancellable;
|
||||||
import com.loohp.limbo.inventory.InventoryView;
|
import com.loohp.limbo.inventory.InventoryView;
|
||||||
import com.loohp.limbo.player.Player;
|
|
||||||
|
|
||||||
public class InventoryOpenEvent extends InventoryEvent implements Cancellable {
|
public class InventoryOpenEvent extends InventoryEvent implements Cancellable {
|
||||||
|
|
||||||
private boolean cancelled;
|
private boolean cancelled;
|
||||||
|
|
||||||
public InventoryOpenEvent(Player player, InventoryView inventoryView) {
|
public InventoryOpenEvent(InventoryView inventoryView) {
|
||||||
super(player, inventoryView, inventoryView.getTopInventory());
|
super(inventoryView, inventoryView.getTopInventory());
|
||||||
this.cancelled = false;
|
this.cancelled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,22 +24,23 @@ import com.loohp.limbo.player.Player;
|
||||||
|
|
||||||
public class PlayerSelectedSlotChangeEvent extends PlayerEvent implements Cancellable {
|
public class PlayerSelectedSlotChangeEvent extends PlayerEvent implements Cancellable {
|
||||||
|
|
||||||
private boolean cancel = false;
|
private boolean cancelled;
|
||||||
private byte slot;
|
private byte slot;
|
||||||
|
|
||||||
public PlayerSelectedSlotChangeEvent(Player player, byte slot) {
|
public PlayerSelectedSlotChangeEvent(Player player, byte slot) {
|
||||||
super(player);
|
super(player);
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
|
this.cancelled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCancelled(boolean cancelled) {
|
public void setCancelled(boolean cancelled) {
|
||||||
this.cancel = cancelled;
|
this.cancelled = cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return cancel;
|
return cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getSlot() {
|
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;
|
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.PacketPlayOutSetSlot;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutWindowItems;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutWindowItems;
|
||||||
import com.loohp.limbo.player.Player;
|
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
|
@Override
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return inventory.length();
|
return inventory.length();
|
||||||
|
|
@ -311,7 +317,7 @@ public abstract class AbstractInventory implements Inventory {
|
||||||
public boolean contains(ItemStack item) {
|
public boolean contains(ItemStack item) {
|
||||||
for (int i = 0; i < inventory.length(); i++) {
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
ItemStack itemStack = getItem(i);
|
ItemStack itemStack = getItem(i);
|
||||||
if (itemStack.equals(item)) {
|
if (Objects.equals(itemStack, item)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -525,6 +531,9 @@ public abstract class AbstractInventory implements Inventory {
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void a(int index, ItemStack itemStack) {
|
public void a(int index, ItemStack itemStack) {
|
||||||
|
if (itemStack != null && itemStack.type().equals(ItemStack.AIR.type())) {
|
||||||
|
itemStack = null;
|
||||||
|
}
|
||||||
inventory.inventory.set(index, itemStack);
|
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;
|
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;
|
package com.loohp.limbo.inventory;
|
||||||
|
|
||||||
|
import com.loohp.limbo.location.Location;
|
||||||
|
|
||||||
public interface InventoryHolder {
|
public interface InventoryHolder {
|
||||||
|
|
||||||
Inventory getInventory();
|
Inventory getInventory();
|
||||||
|
|
||||||
InventoryHolder getHolder();
|
InventoryHolder getHolder();
|
||||||
|
|
||||||
|
Location getLocation();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,11 @@
|
||||||
|
|
||||||
package com.loohp.limbo.inventory;
|
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.network.protocol.packets.PacketPlayOutWindowData;
|
||||||
import com.loohp.limbo.player.Player;
|
import com.loohp.limbo.player.Player;
|
||||||
|
import com.loohp.limbo.player.PlayerInventory;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -29,8 +32,10 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class InventoryView {
|
public class InventoryView {
|
||||||
|
|
||||||
|
public static final int OUTSIDE = -999;
|
||||||
|
|
||||||
private final Player player;
|
private final Player player;
|
||||||
private final String title;
|
private Component title;
|
||||||
private Inventory topInventory;
|
private Inventory topInventory;
|
||||||
private final Inventory bottomInventory;
|
private final Inventory bottomInventory;
|
||||||
private final Map<Property, Integer> properties;
|
private final Map<Property, Integer> properties;
|
||||||
|
|
@ -38,7 +43,7 @@ public class InventoryView {
|
||||||
|
|
||||||
private final Unsafe unsafe;
|
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.player = player;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.topInventory = topInventory;
|
this.topInventory = topInventory;
|
||||||
|
|
@ -58,14 +63,14 @@ public class InventoryView {
|
||||||
}
|
}
|
||||||
|
|
||||||
public InventoryType getType() {
|
public InventoryType getType() {
|
||||||
return topInventory.getType();
|
return topInventory == null ? bottomInventory.getType() : topInventory.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player getPlayer() {
|
public Player getPlayer() {
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
public Component getTitle() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,29 +86,237 @@ public class InventoryView {
|
||||||
return Collections.unmodifiableMap(properties);
|
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() {
|
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) {
|
public ItemStack getItem(int index) {
|
||||||
if (topInventory != null) {
|
return getInventory(index).getItem(convertSlot(index));
|
||||||
if (index < topInventory.getSize()) {
|
|
||||||
return topInventory.getItem(topInventory.getUnsafe().b().applyAsInt(index));
|
|
||||||
}
|
|
||||||
index -= topInventory.getSize();
|
|
||||||
}
|
|
||||||
return bottomInventory.getItem(bottomInventory.getUnsafe().b().applyAsInt(index));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItem(int index, ItemStack itemStack) {
|
public void setItem(int index, ItemStack itemStack) {
|
||||||
if (topInventory != null) {
|
getInventory(index).setItem(convertSlot(index), itemStack);
|
||||||
if (index < topInventory.getSize()) {
|
|
||||||
topInventory.setItem(topInventory.getUnsafe().b().applyAsInt(index), itemStack);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
index -= topInventory.getSize();
|
|
||||||
}
|
|
||||||
bottomInventory.setItem(bottomInventory.getUnsafe().b().applyAsInt(index), itemStack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProperty(InventoryView.Property prop, int value) {
|
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")
|
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Unsafe getUnsafe() {
|
public Unsafe getUnsafe() {
|
||||||
|
|
@ -139,10 +364,20 @@ public class InventoryView {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void a(Inventory topInventory) {
|
public void a(Inventory topInventory, Component title) {
|
||||||
inventoryView.topInventory = topInventory;
|
inventoryView.topInventory = topInventory;
|
||||||
|
inventoryView.title = title;
|
||||||
inventoryView.properties.clear();
|
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;
|
package com.loohp.limbo.inventory;
|
||||||
|
|
||||||
import net.kyori.adventure.key.Key;
|
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 net.querz.nbt.tag.CompoundTag;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ItemStack implements Cloneable {
|
public class ItemStack implements Cloneable {
|
||||||
|
|
@ -86,6 +90,43 @@ public class ItemStack implements Cloneable {
|
||||||
return new ItemStack(material, amount, nbt == null ? null : nbt.clone());
|
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() {
|
public int getMaxStackSize() {
|
||||||
return 64;
|
return 64;
|
||||||
}
|
}
|
||||||
|
|
@ -112,11 +153,21 @@ public class ItemStack implements Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSimilar(ItemStack stack) {
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(material, amount, nbt);
|
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;
|
package com.loohp.limbo.network;
|
||||||
|
|
||||||
import com.loohp.limbo.Limbo;
|
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.InventoryCloseEvent;
|
||||||
import com.loohp.limbo.events.inventory.InventoryCreativeEvent;
|
import com.loohp.limbo.events.inventory.InventoryCreativeEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerInteractEvent;
|
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.PlayerResourcePackStatusEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerSelectedSlotChangeEvent;
|
import com.loohp.limbo.events.player.PlayerSelectedSlotChangeEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerSpawnEvent;
|
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.player.PluginMessageEvent;
|
||||||
import com.loohp.limbo.events.status.StatusPingEvent;
|
import com.loohp.limbo.events.status.StatusPingEvent;
|
||||||
import com.loohp.limbo.file.ServerProperties;
|
import com.loohp.limbo.file.ServerProperties;
|
||||||
|
import com.loohp.limbo.inventory.AnvilInventory;
|
||||||
import com.loohp.limbo.inventory.Inventory;
|
import com.loohp.limbo.inventory.Inventory;
|
||||||
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
import com.loohp.limbo.location.Location;
|
import com.loohp.limbo.location.Location;
|
||||||
import com.loohp.limbo.network.protocol.packets.Packet;
|
import com.loohp.limbo.network.protocol.packets.Packet;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketHandshakingIn;
|
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.PacketLoginOutLoginSuccess;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketLoginOutPluginMessaging;
|
import com.loohp.limbo.network.protocol.packets.PacketLoginOutPluginMessaging;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketOut;
|
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.PacketPlayInBlockPlace;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInChat;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInChat;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInCloseWindow;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInCloseWindow;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInHeldItemChange;
|
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.PacketPlayInKeepAlive;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPickItem;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPosition;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPosition;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPositionAndLook;
|
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.network.protocol.packets.ServerboundChatCommandPacket;
|
||||||
import com.loohp.limbo.player.Player;
|
import com.loohp.limbo.player.Player;
|
||||||
import com.loohp.limbo.player.PlayerInteractManager;
|
import com.loohp.limbo.player.PlayerInteractManager;
|
||||||
|
import com.loohp.limbo.player.PlayerInventory;
|
||||||
import com.loohp.limbo.utils.BungeecordAdventureConversionUtils;
|
import com.loohp.limbo.utils.BungeecordAdventureConversionUtils;
|
||||||
import com.loohp.limbo.utils.CheckedBiConsumer;
|
import com.loohp.limbo.utils.CheckedBiConsumer;
|
||||||
import com.loohp.limbo.utils.CustomStringUtils;
|
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.DeclareCommands;
|
||||||
import com.loohp.limbo.utils.ForwardingUtils;
|
import com.loohp.limbo.utils.ForwardingUtils;
|
||||||
import com.loohp.limbo.utils.GameMode;
|
import com.loohp.limbo.utils.GameMode;
|
||||||
|
import com.loohp.limbo.utils.InventoryClickUtils;
|
||||||
import com.loohp.limbo.utils.MojangAPIUtils;
|
import com.loohp.limbo.utils.MojangAPIUtils;
|
||||||
import com.loohp.limbo.utils.MojangAPIUtils.SkinResponse;
|
import com.loohp.limbo.utils.MojangAPIUtils.SkinResponse;
|
||||||
import com.loohp.limbo.world.BlockPosition;
|
import com.loohp.limbo.world.BlockPosition;
|
||||||
|
|
@ -99,6 +109,7 @@ import com.loohp.limbo.world.BlockState;
|
||||||
import com.loohp.limbo.world.World;
|
import com.loohp.limbo.world.World;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
|
@ -124,7 +135,6 @@ import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -668,9 +678,9 @@ public class ClientConnection extends Thread {
|
||||||
sendPacket(response);
|
sendPacket(response);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
System.out.println("Waiting");
|
|
||||||
PacketIn packetIn = channel.readPacket();
|
PacketIn packetIn = channel.readPacket();
|
||||||
System.out.println("Received " + packetIn.getClass());
|
|
||||||
if (packetIn instanceof PacketPlayInPositionAndLook) {
|
if (packetIn instanceof PacketPlayInPositionAndLook) {
|
||||||
PacketPlayInPositionAndLook pos = (PacketPlayInPositionAndLook) packetIn;
|
PacketPlayInPositionAndLook pos = (PacketPlayInPositionAndLook) packetIn;
|
||||||
Location from = player.getLocation();
|
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()));
|
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) {
|
} else if (packetIn instanceof PacketPlayInSetCreativeSlot) {
|
||||||
PacketPlayInSetCreativeSlot packet = (PacketPlayInSetCreativeSlot) packetIn;
|
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()) {
|
if (event.isCancelled()) {
|
||||||
player.updateInventory();
|
player.updateInventory();
|
||||||
} else {
|
} else {
|
||||||
player.getInventory().getUnsafe().b(packet.getSlotNumber(), event.getNewItem());
|
player.getInventory().setItem(event.getSlot(), event.getNewItem());
|
||||||
}
|
}
|
||||||
} else if (packetIn instanceof PacketPlayInWindowClick) {
|
} else if (packetIn instanceof PacketPlayInWindowClick) {
|
||||||
PacketPlayInWindowClick packet = (PacketPlayInWindowClick) packetIn;
|
PacketPlayInWindowClick packet = (PacketPlayInWindowClick) packetIn;
|
||||||
/*
|
try {
|
||||||
InventoryCreativeEvent event = Limbo.getInstance().getEventsManager().callEvent(new InventoryCreativeEvent(player, player.getInventoryView(), player.getInventory(), player.getInventory().getUnsafe().b().applyAsInt(packet.getSlotNumber()), packet.getItemStack()));
|
InventoryClickUtils.handle(player, packet);
|
||||||
if (event.isCancelled()) {
|
} catch (Throwable e) {
|
||||||
player.updateInventory();
|
e.printStackTrace();
|
||||||
} else {
|
|
||||||
player.getInventory().getUnsafe().b(packet.getSlotNumber(), event.getNewItem());
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
} else if (packetIn instanceof PacketPlayInCloseWindow) {
|
} else if (packetIn instanceof PacketPlayInCloseWindow) {
|
||||||
PacketPlayInCloseWindow packet = (PacketPlayInCloseWindow) packetIn;
|
PacketPlayInCloseWindow packet = (PacketPlayInCloseWindow) packetIn;
|
||||||
Inventory inventory = player.getInventoryView().getTopInventory();
|
Inventory inventory = player.getInventoryView().getTopInventory();
|
||||||
if (inventory != null) {
|
if (inventory != null) {
|
||||||
Integer id = inventory.getUnsafe().c().get(player);
|
Integer id = inventory.getUnsafe().c().get(player);
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(player, player.getInventoryView()));
|
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(player.getInventoryView()));
|
||||||
player.getInventoryView().getUnsafe().a(null);
|
player.getInventoryView().getUnsafe().a(null, null);
|
||||||
inventory.getUnsafe().c().remove(player);
|
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) {
|
} catch (Exception e) {
|
||||||
break;
|
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),
|
ALLOW_FLYING(0x04),
|
||||||
CREATIVE(0x08);
|
CREATIVE(0x08);
|
||||||
|
|
||||||
int bitvalue;
|
private final int bitvalue;
|
||||||
|
|
||||||
PlayerAbilityFlags(int bitvalue) {
|
PlayerAbilityFlags(int bitvalue) {
|
||||||
this.bitvalue = bitvalue;
|
this.bitvalue = bitvalue;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ public class PacketPlayOutSetSlot extends PacketOut {
|
||||||
this.containerId = containerId;
|
this.containerId = containerId;
|
||||||
this.stateId = stateId;
|
this.stateId = stateId;
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
this.itemStack = itemStack;
|
this.itemStack = itemStack == null ? ItemStack.AIR : itemStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getContainerId() {
|
public int getContainerId() {
|
||||||
|
|
|
||||||
|
|
@ -132,8 +132,9 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedSlot(byte slot) {
|
public void setSelectedSlot(byte slot) {
|
||||||
if(slot == selectedSlot)
|
if (slot == selectedSlot) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
PacketPlayOutHeldItemChange state = new PacketPlayOutHeldItemChange(slot);
|
PacketPlayOutHeldItemChange state = new PacketPlayOutHeldItemChange(slot);
|
||||||
clientConnection.sendPacket(state);
|
clientConnection.sendPacket(state);
|
||||||
|
|
@ -603,22 +604,22 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openInventory(Inventory inventory) {
|
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();
|
int id = nextContainerId();
|
||||||
inventory.getUnsafe().c().put(this, id);
|
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()) {
|
if (event.isCancelled()) {
|
||||||
inventoryView.getUnsafe().a(null);
|
inventoryView.getUnsafe().a(null, null);
|
||||||
inventory.getUnsafe().c().remove(this);
|
inventory.getUnsafe().c().remove(this);
|
||||||
} else {
|
} else {
|
||||||
Component title = inventory instanceof TitledInventory ? ((TitledInventory) inventory).getTitle() : Component.translatable("container.chest");
|
|
||||||
PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, inventory.getType().getRawType(inventory.getSize()), title);
|
PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, inventory.getType().getRawType(inventory.getSize()), title);
|
||||||
try {
|
try {
|
||||||
clientConnection.sendPacket(packet);
|
clientConnection.sendPacket(packet);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
inventory.updateInventory(this);
|
inventoryView.updateView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -627,8 +628,8 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold
|
||||||
if (inventory != null) {
|
if (inventory != null) {
|
||||||
Integer id = inventory.getUnsafe().c().get(this);
|
Integer id = inventory.getUnsafe().c().get(this);
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(this, inventoryView));
|
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(inventoryView));
|
||||||
inventoryView.getUnsafe().a(null);
|
inventoryView.getUnsafe().a(null, null);
|
||||||
inventory.getUnsafe().c().remove(this);
|
inventory.getUnsafe().c().remove(this);
|
||||||
PacketPlayOutCloseWindow packet = new PacketPlayOutCloseWindow(id);
|
PacketPlayOutCloseWindow packet = new PacketPlayOutCloseWindow(id);
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import com.loohp.limbo.inventory.AbstractInventory;
|
||||||
import com.loohp.limbo.inventory.EquipmentSlot;
|
import com.loohp.limbo.inventory.EquipmentSlot;
|
||||||
import com.loohp.limbo.inventory.InventoryType;
|
import com.loohp.limbo.inventory.InventoryType;
|
||||||
import com.loohp.limbo.inventory.ItemStack;
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
import com.loohp.limbo.location.Location;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
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",
|
"0x31": "PacketPlayInUseItem",
|
||||||
"0x2B": "PacketPlayInSetCreativeSlot",
|
"0x2B": "PacketPlayInSetCreativeSlot",
|
||||||
"0x0A": "PacketPlayInWindowClick",
|
"0x0A": "PacketPlayInWindowClick",
|
||||||
"0x0B": "PacketPlayInCloseWindow"
|
"0x0B": "PacketPlayInCloseWindow",
|
||||||
|
"0x19": "PacketPlayInPickItem",
|
||||||
|
"0x1C": "PacketPlayInBlockDig",
|
||||||
|
"0x23": "PacketPlayInItemName"
|
||||||
},
|
},
|
||||||
"PlayOut": {
|
"PlayOut": {
|
||||||
"PacketPlayOutLogin": "0x24",
|
"PacketPlayOutLogin": "0x24",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue