forked from BLOCKFANTASY/LOOHP-Limbo
Inventories! (Part 1)
This commit is contained in:
parent
ca186938f4
commit
949d2f34d7
2
pom.xml
2
pom.xml
|
|
@ -24,7 +24,7 @@
|
||||||
<groupId>com.loohp</groupId>
|
<groupId>com.loohp</groupId>
|
||||||
<artifactId>Limbo</artifactId>
|
<artifactId>Limbo</artifactId>
|
||||||
<name>Limbo</name>
|
<name>Limbo</name>
|
||||||
<version>0.6.21-ALPHA</version>
|
<version>0.7.0-ALPHA</version>
|
||||||
|
|
||||||
<description>Standalone Limbo Minecraft Server.</description>
|
<description>Standalone Limbo Minecraft Server.</description>
|
||||||
<url>https://github.com/LOOHP/Limbo</url>
|
<url>https://github.com/LOOHP/Limbo</url>
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@ 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.CustomInventory;
|
||||||
|
import com.loohp.limbo.inventory.Inventory;
|
||||||
|
import com.loohp.limbo.inventory.InventoryHolder;
|
||||||
|
import com.loohp.limbo.inventory.InventoryType;
|
||||||
import com.loohp.limbo.location.Location;
|
import com.loohp.limbo.location.Location;
|
||||||
import com.loohp.limbo.metrics.Metrics;
|
import com.loohp.limbo.metrics.Metrics;
|
||||||
import com.loohp.limbo.network.ServerConnection;
|
import com.loohp.limbo.network.ServerConnection;
|
||||||
|
|
@ -435,15 +439,15 @@ public final class Limbo {
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyedBossBar createBossBar(Key Key, Component name, float progress, BossBar.Color color, BossBar.Overlay overlay, BossBar.Flag... flags) {
|
public KeyedBossBar createBossBar(Key Key, Component name, float progress, BossBar.Color color, BossBar.Overlay overlay, BossBar.Flag... flags) {
|
||||||
KeyedBossBar keyedBossBar = com.loohp.limbo.bossbar.Unsafe.create(Key, BossBar.bossBar(name, progress, color, overlay, new HashSet<>(Arrays.asList(flags))));
|
KeyedBossBar keyedBossBar = com.loohp.limbo.bossbar.Unsafe.a(Key, BossBar.bossBar(name, progress, color, overlay, new HashSet<>(Arrays.asList(flags))));
|
||||||
bossBars.put(Key, keyedBossBar);
|
bossBars.put(Key, keyedBossBar);
|
||||||
return keyedBossBar;
|
return keyedBossBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeBossBar(Key Key) {
|
public void removeBossBar(Key Key) {
|
||||||
KeyedBossBar keyedBossBar = bossBars.remove(Key);
|
KeyedBossBar keyedBossBar = bossBars.remove(Key);
|
||||||
keyedBossBar.getProperties().removeListener(keyedBossBar.getUnsafe().getLimboListener());
|
keyedBossBar.getProperties().removeListener(keyedBossBar.getUnsafe().a());
|
||||||
keyedBossBar.getUnsafe().invalidate();
|
keyedBossBar.getUnsafe().b();
|
||||||
PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(keyedBossBar, PacketPlayOutBoss.BossBarAction.REMOVE);
|
PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(keyedBossBar, PacketPlayOutBoss.BossBarAction.REMOVE);
|
||||||
for (Player player : keyedBossBar.getPlayers()) {
|
for (Player player : keyedBossBar.getPlayers()) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -578,11 +582,7 @@ public final class Limbo {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNextEntityId() {
|
public int getNextEntityId() {
|
||||||
if (entityIdCount.get() == Integer.MAX_VALUE) {
|
return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i);
|
||||||
return entityIdCount.getAndSet(0);
|
|
||||||
} else {
|
|
||||||
return entityIdCount.getAndIncrement();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispatchCommand(CommandSender sender, String str) {
|
public void dispatchCommand(CommandSender sender, String str) {
|
||||||
|
|
@ -607,14 +607,26 @@ public final class Limbo {
|
||||||
Enumeration<URL> manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
|
Enumeration<URL> manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
|
||||||
while (manifests.hasMoreElements()) {
|
while (manifests.hasMoreElements()) {
|
||||||
URL url = manifests.nextElement();
|
URL url = manifests.nextElement();
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
|
||||||
Optional<String> line = br.lines().filter(each -> each.startsWith("Limbo-Version:")).findFirst();
|
Optional<String> line = br.lines().filter(each -> each.startsWith("Limbo-Version:")).findFirst();
|
||||||
br.close();
|
if (line.isPresent()) {
|
||||||
if (line.isPresent()) {
|
return line.get().substring(14).trim();
|
||||||
return line.get().substring(14).trim();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Inventory createInventory(Component title, int slots, InventoryHolder holder) {
|
||||||
|
return CustomInventory.create(title, slots, holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory createInventory(InventoryType type, InventoryHolder holder) {
|
||||||
|
return createInventory(null, type, holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory createInventory(Component title, InventoryType type, InventoryHolder holder) {
|
||||||
|
throw new UnsupportedOperationException("This function has not been implemented yet.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,43 +52,43 @@ public class Unsafe {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setPlayerGameModeSilently(Player player, GameMode mode) {
|
public void a(Player player, GameMode mode) {
|
||||||
playerUnsafe.a(player, mode);
|
playerUnsafe.a(player, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setSelectedSlotSilently(Player player, byte slot) {
|
public void a(Player player, byte slot) {
|
||||||
playerUnsafe.a(player, slot);
|
playerUnsafe.a(player, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setPlayerEntityId(Player player, int entityId) {
|
public void a(Player player, int entityId) {
|
||||||
playerUnsafe.a(player, entityId);
|
playerUnsafe.a(player, entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void removeEntity(World world, Entity entity) {
|
public void a(World world, Entity entity) {
|
||||||
worldUnsafe.a(world, entity);
|
worldUnsafe.a(world, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public DataWatcher getDataWatcher(World world, Entity entity) {
|
public DataWatcher b(World world, Entity entity) {
|
||||||
return worldUnsafe.b(world, entity);
|
return worldUnsafe.b(world, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setPlayerLocationSilently(Player player, Location location) {
|
public void a(Player player, Location location) {
|
||||||
playerUnsafe.a(player, location);
|
playerUnsafe.a(player, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void addPlayer(Player player) {
|
public void a(Player player) {
|
||||||
instance.playersByName.put(player.getName(), player);
|
instance.playersByName.put(player.getName(), player);
|
||||||
instance.playersByUUID.put(player.getUniqueId(), player);
|
instance.playersByUUID.put(player.getUniqueId(), player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void removePlayer(Player player) {
|
public void b(Player player) {
|
||||||
instance.getBossBars().values().forEach(each -> each.hidePlayer(player));
|
instance.getBossBars().values().forEach(each -> each.hidePlayer(player));
|
||||||
instance.playersByName.remove(player.getName());
|
instance.playersByName.remove(player.getName());
|
||||||
instance.playersByUUID.remove(player.getUniqueId());
|
instance.playersByUUID.remove(player.getUniqueId());
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import net.kyori.adventure.key.Key;
|
||||||
public class Unsafe {
|
public class Unsafe {
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static KeyedBossBar create(Key key, BossBar properties) {
|
public static KeyedBossBar a(Key key, BossBar properties) {
|
||||||
return new KeyedBossBar(key, properties);
|
return new KeyedBossBar(key, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,12 +38,12 @@ public class Unsafe {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public KeyedBossBar.LimboBossBarHandler getLimboListener() {
|
public KeyedBossBar.LimboBossBarHandler a() {
|
||||||
return instance.listener;
|
return instance.listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void invalidate() {
|
public void b() {
|
||||||
instance.valid.set(false);
|
instance.valid.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,5 +150,4 @@ public class ArmorStand extends LivingEntity {
|
||||||
public void setRightLegRotation(Rotation3f rightLegRotation) {
|
public void setRightLegRotation(Rotation3f rightLegRotation) {
|
||||||
this.rightLegRotation = rightLegRotation;
|
this.rightLegRotation = rightLegRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -301,12 +301,12 @@ public abstract class Entity implements Sound.Emitter {
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public void remove() {
|
public void remove() {
|
||||||
Limbo.getInstance().getUnsafe().removeEntity(world, this);
|
Limbo.getInstance().getUnsafe().a(world, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public DataWatcher getDataWatcher() {
|
public DataWatcher getDataWatcher() {
|
||||||
return Limbo.getInstance().getUnsafe().getDataWatcher(world, this);
|
return Limbo.getInstance().getUnsafe().b(world, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* 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.entity;
|
||||||
|
|
||||||
|
import com.loohp.limbo.inventory.EquipmentSlot;
|
||||||
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface to a creatures inventory
|
||||||
|
*/
|
||||||
|
public interface EntityEquipment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the ItemStack at the given equipment slot in the inventory.
|
||||||
|
*
|
||||||
|
* @param slot the slot to put the ItemStack
|
||||||
|
* @param item the ItemStack to set
|
||||||
|
*/
|
||||||
|
void setItem(EquipmentSlot slot, ItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ItemStack at the given equipment slot in the inventory.
|
||||||
|
*
|
||||||
|
* @param slot the slot to get the ItemStack
|
||||||
|
* @return the ItemStack in the given slot
|
||||||
|
*/
|
||||||
|
ItemStack getItem(EquipmentSlot slot);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a copy of the item the entity is currently holding
|
||||||
|
* in their main hand.
|
||||||
|
*
|
||||||
|
* @return the currently held item
|
||||||
|
*/
|
||||||
|
ItemStack getItemInMainHand();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the item the entity is holding in their main hand.
|
||||||
|
*
|
||||||
|
* @param item The item to put into the entities hand
|
||||||
|
*/
|
||||||
|
void setItemInMainHand(ItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a copy of the item the entity is currently holding
|
||||||
|
* in their off hand.
|
||||||
|
*
|
||||||
|
* @return the currently held item
|
||||||
|
*/
|
||||||
|
ItemStack getItemInOffHand();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the item the entity is holding in their off hand.
|
||||||
|
*
|
||||||
|
* @param item The item to put into the entities hand
|
||||||
|
*/
|
||||||
|
void setItemInOffHand(ItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a copy of the helmet currently being worn by the entity
|
||||||
|
*
|
||||||
|
* @return The helmet being worn
|
||||||
|
*/
|
||||||
|
ItemStack getHelmet();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the helmet worn by the entity
|
||||||
|
*
|
||||||
|
* @param helmet The helmet to put on the entity
|
||||||
|
*/
|
||||||
|
void setHelmet(ItemStack helmet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a copy of the chest plate currently being worn by the entity
|
||||||
|
*
|
||||||
|
* @return The chest plate being worn
|
||||||
|
*/
|
||||||
|
ItemStack getChestplate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the chest plate worn by the entity
|
||||||
|
*
|
||||||
|
* @param chestplate The chest plate to put on the entity
|
||||||
|
*/
|
||||||
|
void setChestplate(ItemStack chestplate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a copy of the leggings currently being worn by the entity
|
||||||
|
*
|
||||||
|
* @return The leggings being worn
|
||||||
|
*/
|
||||||
|
ItemStack getLeggings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the leggings worn by the entity
|
||||||
|
*
|
||||||
|
* @param leggings The leggings to put on the entity
|
||||||
|
*/
|
||||||
|
void setLeggings(ItemStack leggings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a copy of the boots currently being worn by the entity
|
||||||
|
*
|
||||||
|
* @return The boots being worn
|
||||||
|
*/
|
||||||
|
ItemStack getBoots();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the boots worn by the entity
|
||||||
|
*
|
||||||
|
* @param boots The boots to put on the entity
|
||||||
|
*/
|
||||||
|
void setBoots(ItemStack boots);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a copy of all worn armor
|
||||||
|
*
|
||||||
|
* @return The array of worn armor. Individual items may be null.
|
||||||
|
*/
|
||||||
|
ItemStack[] getArmorContents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the entities armor to the provided array of ItemStacks
|
||||||
|
*
|
||||||
|
* @param items The items to set the armor as. Individual items may be null.
|
||||||
|
*/
|
||||||
|
void setArmorContents(ItemStack[] items);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the entity of all armor and held items
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entity this EntityEquipment belongs to
|
||||||
|
*
|
||||||
|
* @return the entity this EntityEquipment belongs to
|
||||||
|
*/
|
||||||
|
Entity getHolder();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* 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.entity;
|
||||||
|
|
||||||
|
import com.loohp.limbo.inventory.EquipmentSlot;
|
||||||
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
|
||||||
|
public class StandardEntityEquipment implements EntityEquipment {
|
||||||
|
|
||||||
|
private final Entity entity;
|
||||||
|
private final EnumMap<EquipmentSlot, ItemStack> itemStacks;
|
||||||
|
|
||||||
|
public StandardEntityEquipment(Entity entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.itemStacks = new EnumMap<>(EquipmentSlot.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItem(EquipmentSlot slot, ItemStack item) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItem(EquipmentSlot slot) {
|
||||||
|
return itemStacks.get(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemInMainHand() {
|
||||||
|
return itemStacks.get(EquipmentSlot.MAINHAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItemInMainHand(ItemStack item) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemInOffHand() {
|
||||||
|
return getItem(EquipmentSlot.OFFHAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItemInOffHand(ItemStack item) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getHelmet() {
|
||||||
|
return getItem(EquipmentSlot.HELMET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHelmet(ItemStack helmet) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getChestplate() {
|
||||||
|
return getItem(EquipmentSlot.CHESTPLATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChestplate(ItemStack chestplate) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getLeggings() {
|
||||||
|
return getItem(EquipmentSlot.LEGGINGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLeggings(ItemStack leggings) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getBoots() {
|
||||||
|
return getItem(EquipmentSlot.BOOTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBoots(ItemStack boots) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack[] getArmorContents() {
|
||||||
|
return itemStacks.values().toArray(new ItemStack[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setArmorContents(ItemStack[] items) {
|
||||||
|
if (items.length != 6) {
|
||||||
|
throw new IllegalArgumentException("items must have a length of 6");
|
||||||
|
}
|
||||||
|
EquipmentSlot[] equipmentSlots = EquipmentSlot.values();
|
||||||
|
int i = 0;
|
||||||
|
for (EquipmentSlot equipmentSlot : equipmentSlots) {
|
||||||
|
setItem(equipmentSlot, items[i++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
for (EquipmentSlot equipmentSlot : itemStacks.keySet()) {
|
||||||
|
setItem(equipmentSlot, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity getHolder() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.Inventory;
|
||||||
|
import com.loohp.limbo.inventory.InventoryView;
|
||||||
|
import com.loohp.limbo.player.Player;
|
||||||
|
|
||||||
|
public class InventoryClickEvent extends InventoryEvent implements Cancellable {
|
||||||
|
|
||||||
|
private boolean cancelled;
|
||||||
|
|
||||||
|
public InventoryClickEvent(Player player, InventoryView inventoryView, Inventory clickedInventory) {
|
||||||
|
super(player, inventoryView, clickedInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancelled) {
|
||||||
|
this.cancelled = cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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.inventory.InventoryView;
|
||||||
|
import com.loohp.limbo.player.Player;
|
||||||
|
|
||||||
|
public class InventoryCloseEvent extends InventoryEvent {
|
||||||
|
|
||||||
|
public InventoryCloseEvent(Player player, InventoryView inventoryView) {
|
||||||
|
super(player, inventoryView, inventoryView.getTopInventory());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
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 {
|
||||||
|
|
||||||
|
private boolean cancelled;
|
||||||
|
private final int slot;
|
||||||
|
private ItemStack newItem;
|
||||||
|
|
||||||
|
public InventoryCreativeEvent(Player player, InventoryView inventoryView, PlayerInventory playerInventory, int slot, ItemStack newItem) {
|
||||||
|
super(player, inventoryView, playerInventory);
|
||||||
|
this.slot = slot;
|
||||||
|
this.newItem = newItem;
|
||||||
|
this.cancelled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlot() {
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancelled) {
|
||||||
|
this.cancelled = cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getNewItem() {
|
||||||
|
return newItem == null ? null : newItem.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewItem(ItemStack newItem) {
|
||||||
|
this.newItem = newItem == null ? null : newItem.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.Event;
|
||||||
|
import com.loohp.limbo.inventory.Inventory;
|
||||||
|
import com.loohp.limbo.inventory.InventoryView;
|
||||||
|
import com.loohp.limbo.player.Player;
|
||||||
|
|
||||||
|
public class InventoryEvent extends Event {
|
||||||
|
|
||||||
|
private final Player player;
|
||||||
|
private final InventoryView inventoryView;
|
||||||
|
private final Inventory clickedInventory;
|
||||||
|
|
||||||
|
public InventoryEvent(Player player, InventoryView inventoryView, Inventory clickedInventory) {
|
||||||
|
this.player = player;
|
||||||
|
this.inventoryView = inventoryView;
|
||||||
|
this.clickedInventory = clickedInventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryView getInventoryView() {
|
||||||
|
return inventoryView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getClickedInventory() {
|
||||||
|
return clickedInventory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
import com.loohp.limbo.player.Player;
|
||||||
|
|
||||||
|
public class InventoryOpenEvent extends InventoryEvent implements Cancellable {
|
||||||
|
|
||||||
|
private boolean cancelled;
|
||||||
|
|
||||||
|
public InventoryOpenEvent(Player player, InventoryView inventoryView) {
|
||||||
|
super(player, inventoryView, inventoryView.getTopInventory());
|
||||||
|
this.cancelled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancelled) {
|
||||||
|
this.cancelled = cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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.EquipmentSlot;
|
||||||
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
|
import com.loohp.limbo.location.BlockFace;
|
||||||
|
import com.loohp.limbo.player.Player;
|
||||||
|
import com.loohp.limbo.world.BlockState;
|
||||||
|
|
||||||
|
public class PlayerInteractEvent extends PlayerEvent implements Cancellable {
|
||||||
|
|
||||||
|
public enum Action {
|
||||||
|
|
||||||
|
LEFT_CLICK_AIR,
|
||||||
|
LEFT_CLICK_BLOCK,
|
||||||
|
PHYSICAL,
|
||||||
|
RIGHT_CLICK_AIR,
|
||||||
|
RIGHT_CLICK_BLOCK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cancelled = false;
|
||||||
|
private final Action action;
|
||||||
|
private final ItemStack item;
|
||||||
|
private final BlockState clickedBlock;
|
||||||
|
private final BlockFace clickedFace;
|
||||||
|
private final EquipmentSlot hand;
|
||||||
|
|
||||||
|
public PlayerInteractEvent(Player player, Action action, ItemStack item, BlockState clickedBlock, BlockFace clickedFace, EquipmentSlot hand) {
|
||||||
|
super(player);
|
||||||
|
this.action = action;
|
||||||
|
this.item = item;
|
||||||
|
this.clickedBlock = clickedBlock;
|
||||||
|
this.clickedFace = clickedFace;
|
||||||
|
this.hand = hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockState getClickedBlock() {
|
||||||
|
return clickedBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockFace getClickedFace() {
|
||||||
|
return clickedFace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EquipmentSlot getHand() {
|
||||||
|
return hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancelled) {
|
||||||
|
this.cancelled = cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,552 @@
|
||||||
|
/*
|
||||||
|
* 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 com.loohp.limbo.network.protocol.packets.PacketPlayOutSetSlot;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutWindowItems;
|
||||||
|
import com.loohp.limbo.player.Player;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||||
|
import java.util.function.IntUnaryOperator;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
public abstract class AbstractInventory implements Inventory {
|
||||||
|
|
||||||
|
protected final InventoryHolder inventoryHolder;
|
||||||
|
protected final Map<Player, Integer> viewers;
|
||||||
|
protected final InventoryType inventoryType;
|
||||||
|
protected final AtomicReferenceArray<ItemStack> inventory;
|
||||||
|
protected final InventoryUpdateListener listener;
|
||||||
|
protected final IntUnaryOperator slotConvertor;
|
||||||
|
protected final IntUnaryOperator inverseSlotConvertor;
|
||||||
|
|
||||||
|
private final Unsafe unsafe;
|
||||||
|
|
||||||
|
protected int maxStackSize;
|
||||||
|
|
||||||
|
public AbstractInventory(int size, InventoryHolder inventoryHolder, InventoryType inventoryType, IntUnaryOperator slotConvertor, IntUnaryOperator inverseSlotConvertor) {
|
||||||
|
this.inventoryHolder = inventoryHolder;
|
||||||
|
this.viewers = new ConcurrentHashMap<>();
|
||||||
|
this.inventoryType = inventoryType;
|
||||||
|
this.inventory = new AtomicReferenceArray<>(size);
|
||||||
|
this.slotConvertor = slotConvertor == null ? IntUnaryOperator.identity() : slotConvertor;
|
||||||
|
this.inverseSlotConvertor = inverseSlotConvertor == null ? IntUnaryOperator.identity() : inverseSlotConvertor;
|
||||||
|
this.listener = (inventory, slot, oldItem, newItem) -> {
|
||||||
|
for (Map.Entry<Player, Integer> entry : viewers.entrySet()) {
|
||||||
|
try {
|
||||||
|
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(entry.getValue(), 0, this.slotConvertor.applyAsInt(slot), newItem);
|
||||||
|
entry.getKey().clientConnection.sendPacket(packet);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.maxStackSize = 64;
|
||||||
|
this.unsafe = new Unsafe(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateInventory(Player player) {
|
||||||
|
Integer windowId = viewers.get(player);
|
||||||
|
if (windowId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ItemStack[] itemStackArray = new ItemStack[IntStream.range(0, inventory.length()).map(slotConvertor).max().orElse(-1) + 1];
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
itemStackArray[slotConvertor.applyAsInt(i)] = getItem(i);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
PacketPlayOutWindowItems packet = new PacketPlayOutWindowItems(windowId, 0, Arrays.asList(itemStackArray), ItemStack.AIR);
|
||||||
|
player.clientConnection.sendPacket(packet);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateInventory() {
|
||||||
|
ItemStack[] itemStackArray = new ItemStack[IntStream.range(0, inventory.length()).map(slotConvertor).max().orElse(0)];
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
itemStackArray[slotConvertor.applyAsInt(i)] = getItem(i);
|
||||||
|
}
|
||||||
|
List<ItemStack> itemStacks = Arrays.asList(itemStackArray);
|
||||||
|
for (Map.Entry<Player, Integer> entry : viewers.entrySet()) {
|
||||||
|
try {
|
||||||
|
PacketPlayOutWindowItems packet = new PacketPlayOutWindowItems(entry.getValue(), 0, itemStacks, ItemStack.AIR);
|
||||||
|
entry.getKey().clientConnection.sendPacket(packet);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSize() {
|
||||||
|
return inventory.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxStackSize() {
|
||||||
|
return maxStackSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxStackSize(int size) {
|
||||||
|
this.maxStackSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItem(int index) {
|
||||||
|
return inventory.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItem(int index, ItemStack item) {
|
||||||
|
if (item != null && item.type().equals(ItemStack.AIR.type())) {
|
||||||
|
item = null;
|
||||||
|
}
|
||||||
|
ItemStack oldItem = getItem(index);
|
||||||
|
if (!Objects.equals(item, oldItem)) {
|
||||||
|
inventory.set(index, item);
|
||||||
|
listener.slotChanged(this, index, oldItem, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int firstPartial(Key material) {
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack item = getItem(i);
|
||||||
|
if (item != null && item.type().equals(material) && item.amount() < item.getMaxStackSize()) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int firstPartial(ItemStack item) {
|
||||||
|
if (item == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack cItem = getItem(i);
|
||||||
|
if (cItem != null && cItem.amount() < cItem.getMaxStackSize() && cItem.isSimilar(item)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<Integer, ItemStack> addItem(ItemStack... items) throws IllegalArgumentException {
|
||||||
|
HashMap<Integer, ItemStack> leftover = new HashMap<>();
|
||||||
|
for (int i = 0; i < items.length; i++) {
|
||||||
|
ItemStack item = items[i];
|
||||||
|
while (true) {
|
||||||
|
// Do we already have a stack of it?
|
||||||
|
int firstPartial = firstPartial(item);
|
||||||
|
|
||||||
|
// Drat! no partial stack
|
||||||
|
if (firstPartial == -1) {
|
||||||
|
// Find a free spot!
|
||||||
|
int firstFree = firstEmpty();
|
||||||
|
|
||||||
|
if (firstFree == -1) {
|
||||||
|
// No space at all!
|
||||||
|
leftover.put(i, item);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// More than a single stack!
|
||||||
|
if (item.amount() > getMaxStackSize()) {
|
||||||
|
ItemStack stack = item.clone();
|
||||||
|
stack = stack.amount(getMaxStackSize());
|
||||||
|
setItem(firstFree, stack);
|
||||||
|
item = item.amount(item.amount() - getMaxStackSize());
|
||||||
|
items[i] = item;
|
||||||
|
} else {
|
||||||
|
// Just store it
|
||||||
|
setItem(firstFree, item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// So, apparently it might only partially fit, well lets do just that
|
||||||
|
ItemStack partialItem = getItem(firstPartial);
|
||||||
|
|
||||||
|
int amount = item.amount();
|
||||||
|
int partialAmount = partialItem.amount();
|
||||||
|
int maxAmount = partialItem.getMaxStackSize();
|
||||||
|
|
||||||
|
// Check if it fully fits
|
||||||
|
if (amount + partialAmount <= maxAmount) {
|
||||||
|
partialItem = partialItem.amount(amount + partialAmount);
|
||||||
|
// To make sure the packet is sent to the client
|
||||||
|
setItem(firstPartial, partialItem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It fits partially
|
||||||
|
partialItem = partialItem.amount(maxAmount);
|
||||||
|
// To make sure the packet is sent to the client
|
||||||
|
setItem(firstPartial, partialItem);
|
||||||
|
item = item.amount(amount + partialAmount - maxAmount);
|
||||||
|
items[i] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return leftover;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<Integer, ItemStack> removeItem(ItemStack... items) throws IllegalArgumentException {
|
||||||
|
HashMap<Integer, ItemStack> leftover = new HashMap<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < items.length; i++) {
|
||||||
|
ItemStack item = items[i];
|
||||||
|
int toDelete = item.amount();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int first = first(item, false);
|
||||||
|
|
||||||
|
// Drat! we don't have this type in the inventory
|
||||||
|
if (first == -1) {
|
||||||
|
item = item.amount(toDelete);
|
||||||
|
items[i] = item;
|
||||||
|
leftover.put(i, item);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ItemStack itemStack = getItem(first);
|
||||||
|
int amount = itemStack.amount();
|
||||||
|
|
||||||
|
if (amount <= toDelete) {
|
||||||
|
toDelete -= amount;
|
||||||
|
// clear the slot, all used up
|
||||||
|
clear(first);
|
||||||
|
} else {
|
||||||
|
// split the stack and store
|
||||||
|
itemStack = itemStack.amount(amount - toDelete);
|
||||||
|
setItem(first, itemStack);
|
||||||
|
toDelete = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bail when done
|
||||||
|
if (toDelete <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return leftover;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack[] getContents() {
|
||||||
|
return StreamSupport.stream(spliterator(), false).toArray(ItemStack[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContents(ItemStack[] items) throws IllegalArgumentException {
|
||||||
|
if (getSize() < items.length) {
|
||||||
|
throw new IllegalArgumentException("Invalid inventory size; expected " + getSize() + " or less");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < getSize(); i++) {
|
||||||
|
if (i >= items.length) {
|
||||||
|
setItem(i, null);
|
||||||
|
} else {
|
||||||
|
setItem(i, items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack[] getStorageContents() {
|
||||||
|
return getContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStorageContents(ItemStack[] items) throws IllegalArgumentException {
|
||||||
|
setContents(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Key material) throws IllegalArgumentException {
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack itemStack = getItem(i);
|
||||||
|
if (itemStack != null && itemStack.type().equals(material)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(ItemStack item) {
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack itemStack = getItem(i);
|
||||||
|
if (itemStack.equals(item)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Key material, int amount) throws IllegalArgumentException {
|
||||||
|
if (amount <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack itemStack = getItem(i);
|
||||||
|
if (itemStack != null && itemStack.type().equals(material)) {
|
||||||
|
if ((amount -= itemStack.amount()) <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(ItemStack item, int amount) {
|
||||||
|
if (item == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amount <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack itemStack = getItem(i);
|
||||||
|
if (item.equals(itemStack) && --amount <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAtLeast(ItemStack item, int amount) {
|
||||||
|
if (item == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amount <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack itemStack = getItem(i);
|
||||||
|
if (item.isSimilar(itemStack) && (amount -= itemStack.amount()) <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<Integer, ? extends ItemStack> all(Key material) throws IllegalArgumentException {
|
||||||
|
HashMap<Integer, ItemStack> slots = new HashMap<>();
|
||||||
|
ItemStack[] inventory = getStorageContents();
|
||||||
|
for (int i = 0; i < inventory.length; i++) {
|
||||||
|
ItemStack item = inventory[i];
|
||||||
|
if (item != null && item.type().equals(material)) {
|
||||||
|
slots.put(i, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<Integer, ? extends ItemStack> all(ItemStack item) {
|
||||||
|
HashMap<Integer, ItemStack> slots = new HashMap<>();
|
||||||
|
if (item != null) {
|
||||||
|
ItemStack[] inventory = getStorageContents();
|
||||||
|
for (int i = 0; i < inventory.length; i++) {
|
||||||
|
if (item.equals(inventory[i])) {
|
||||||
|
slots.put(i, inventory[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int first(Key material) throws IllegalArgumentException {
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack item = getItem(i);
|
||||||
|
if (item != null && item.type().equals(material)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int first(ItemStack item) {
|
||||||
|
return first(item, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int first(ItemStack item, boolean withAmount) {
|
||||||
|
if (item == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack itemStack = inventory.get(i);
|
||||||
|
if (itemStack == null) continue;
|
||||||
|
|
||||||
|
if (withAmount ? item.equals(itemStack) : item.isSimilar(itemStack)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int firstEmpty() {
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
if (getItem(i) == null) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
if (getItem(i) != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Key material) throws IllegalArgumentException {
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack itemStack = getItem(i);
|
||||||
|
if (itemStack != null && itemStack.type().equals(material)) {
|
||||||
|
clear(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(ItemStack item) {
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
ItemStack itemStack = getItem(i);
|
||||||
|
if (itemStack != null && itemStack.equals(item)) {
|
||||||
|
clear(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear(int index) {
|
||||||
|
setItem(index, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
for (int i = 0; i < inventory.length(); i++) {
|
||||||
|
setItem(i, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Player> getViewers() {
|
||||||
|
return Collections.unmodifiableSet(viewers.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InventoryType getType() {
|
||||||
|
return inventoryType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InventoryHolder getHolder() {
|
||||||
|
return inventoryHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListIterator<ItemStack> iterator() {
|
||||||
|
return new InventoryIterator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListIterator<ItemStack> iterator(int index) {
|
||||||
|
if (index < 0) {
|
||||||
|
index += getSize() + 1; // ie, with -1, previous() will return the last element
|
||||||
|
}
|
||||||
|
return new InventoryIterator(this, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||||
|
@Deprecated
|
||||||
|
public Unsafe getUnsafe() {
|
||||||
|
return unsafe;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||||
|
@Deprecated
|
||||||
|
public static class Unsafe implements Inventory.Unsafe {
|
||||||
|
|
||||||
|
private final AbstractInventory inventory;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public Unsafe(AbstractInventory inventory) {
|
||||||
|
this.inventory = inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void a(int index, ItemStack itemStack) {
|
||||||
|
inventory.inventory.set(index, itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void b(int index, ItemStack itemStack) {
|
||||||
|
inventory.inventory.set(inventory.inverseSlotConvertor.applyAsInt(index), itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public IntUnaryOperator a() {
|
||||||
|
return inventory.slotConvertor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public IntUnaryOperator b() {
|
||||||
|
return inventory.inverseSlotConvertor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Player, Integer> c() {
|
||||||
|
return inventory.viewers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* 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 com.loohp.limbo.location.Location;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
|
||||||
|
public class CustomInventory extends AbstractInventory implements TitledInventory {
|
||||||
|
|
||||||
|
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||||
|
@Deprecated
|
||||||
|
public static CustomInventory create(Component title, int size, InventoryHolder inventoryHolder) {
|
||||||
|
if (size % 9 != 0 || size > 54 || size < 9) {
|
||||||
|
throw new IllegalArgumentException("size must be a multiple of 9 and within 9 - 54");
|
||||||
|
}
|
||||||
|
return new CustomInventory(title, size, inventoryHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component title;
|
||||||
|
|
||||||
|
private CustomInventory(Component title, int size, InventoryHolder inventoryHolder) {
|
||||||
|
super(size, inventoryHolder, InventoryType.CHEST, null, null);
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(Component title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Location getLocation() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -28,4 +28,24 @@ public enum EquipmentSlot {
|
||||||
LEGGINGS,
|
LEGGINGS,
|
||||||
BOOTS;
|
BOOTS;
|
||||||
|
|
||||||
|
public boolean isHandSlot() {
|
||||||
|
switch (this) {
|
||||||
|
case MAINHAND:
|
||||||
|
case OFFHAND:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isArmorSlot() {
|
||||||
|
switch (this) {
|
||||||
|
case HELMET:
|
||||||
|
case CHESTPLATE:
|
||||||
|
case LEGGINGS:
|
||||||
|
case BOOTS:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,403 @@
|
||||||
|
/*
|
||||||
|
* 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 com.loohp.limbo.location.Location;
|
||||||
|
import com.loohp.limbo.player.Player;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.IntUnaryOperator;
|
||||||
|
|
||||||
|
public interface Inventory extends Iterable<ItemStack> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the size of the inventory
|
||||||
|
*
|
||||||
|
* @return The size of the inventory
|
||||||
|
*/
|
||||||
|
int getSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum stack size for an ItemStack in this inventory.
|
||||||
|
*
|
||||||
|
* @return The maximum size for an ItemStack in this inventory.
|
||||||
|
*/
|
||||||
|
int getMaxStackSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method allows you to change the maximum stack size for an
|
||||||
|
* inventory.
|
||||||
|
* <p>
|
||||||
|
* <b>Caveats:</b>
|
||||||
|
* <ul>
|
||||||
|
* <li>Not all inventories respect this value.
|
||||||
|
* <li>Stacks larger than 127 may be clipped when the world is saved.
|
||||||
|
* <li>This value is not guaranteed to be preserved; be sure to set it
|
||||||
|
* before every time you want to set a slot over the max stack size.
|
||||||
|
* <li>Stacks larger than the default max size for this type of inventory
|
||||||
|
* may not display correctly in the client.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param size The new maximum stack size for items in this inventory.
|
||||||
|
*/
|
||||||
|
void setMaxStackSize(int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ItemStack found in the slot at the given index
|
||||||
|
*
|
||||||
|
* @param index The index of the Slot's ItemStack to return
|
||||||
|
* @return The ItemStack in the slot
|
||||||
|
*/
|
||||||
|
ItemStack getItem(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the ItemStack at the given index of the inventory.
|
||||||
|
*
|
||||||
|
* @param index The index where to put the ItemStack
|
||||||
|
* @param item The ItemStack to set
|
||||||
|
*/
|
||||||
|
void setItem(int index, ItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the given ItemStacks in the inventory. This will try to fill
|
||||||
|
* existing stacks and empty slots as well as it can.
|
||||||
|
* <p>
|
||||||
|
* The returned HashMap contains what it couldn't store, where the key is
|
||||||
|
* the index of the parameter, and the value is the ItemStack at that
|
||||||
|
* index of the varargs parameter. If all items are stored, it will return
|
||||||
|
* an empty HashMap.
|
||||||
|
* <p>
|
||||||
|
* If you pass in ItemStacks which exceed the maximum stack size for the
|
||||||
|
* Material, first they will be added to partial stacks where
|
||||||
|
* Material.getMaxStackSize() is not exceeded, up to
|
||||||
|
* Material.getMaxStackSize(). When there are no partial stacks left
|
||||||
|
* stacks will be split on Inventory.getMaxStackSize() allowing you to
|
||||||
|
* exceed the maximum stack size for that material.
|
||||||
|
* <p>
|
||||||
|
* It is known that in some implementations this method will also set
|
||||||
|
* the inputted argument amount to the number of that item not placed in
|
||||||
|
* slots.
|
||||||
|
*
|
||||||
|
* @param items The ItemStacks to add
|
||||||
|
* @return A HashMap containing items that didn't fit.
|
||||||
|
* @throws IllegalArgumentException if items or any element in it is null
|
||||||
|
*/
|
||||||
|
HashMap<Integer, ItemStack> addItem(ItemStack... items) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given ItemStacks from the inventory.
|
||||||
|
* <p>
|
||||||
|
* It will try to remove 'as much as possible' from the types and amounts
|
||||||
|
* you give as arguments.
|
||||||
|
* <p>
|
||||||
|
* The returned HashMap contains what it couldn't remove, where the key is
|
||||||
|
* the index of the parameter, and the value is the ItemStack at that
|
||||||
|
* index of the varargs parameter. If all the given ItemStacks are
|
||||||
|
* removed, it will return an empty HashMap.
|
||||||
|
* <p>
|
||||||
|
* It is known that in some implementations this method will also set the
|
||||||
|
* inputted argument amount to the number of that item not removed from
|
||||||
|
* slots.
|
||||||
|
*
|
||||||
|
* @param items The ItemStacks to remove
|
||||||
|
* @return A HashMap containing items that couldn't be removed.
|
||||||
|
* @throws IllegalArgumentException if items is null
|
||||||
|
*/
|
||||||
|
HashMap<Integer, ItemStack> removeItem(ItemStack... items) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all ItemStacks from the inventory
|
||||||
|
*
|
||||||
|
* @return An array of ItemStacks from the inventory. Individual items may be null.
|
||||||
|
*/
|
||||||
|
ItemStack[] getContents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completely replaces the inventory's contents. Removes all existing
|
||||||
|
* contents and replaces it with the ItemStacks given in the array.
|
||||||
|
*
|
||||||
|
* @param items A complete replacement for the contents; the length must
|
||||||
|
* be less than or equal to {@link #getSize()}.
|
||||||
|
* @throws IllegalArgumentException If the array has more items than the
|
||||||
|
* inventory.
|
||||||
|
*/
|
||||||
|
void setContents(ItemStack[] items) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the contents from the section of the inventory where items can
|
||||||
|
* reasonably be expected to be stored. In most cases this will represent
|
||||||
|
* the entire inventory, but in some cases it may exclude armor or result
|
||||||
|
* slots.
|
||||||
|
* <br>
|
||||||
|
* It is these contents which will be used for add / contains / remove
|
||||||
|
* methods which look for a specific stack.
|
||||||
|
*
|
||||||
|
* @return inventory storage contents. Individual items may be null.
|
||||||
|
*/
|
||||||
|
ItemStack[] getStorageContents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put the given ItemStacks into the storage slots
|
||||||
|
*
|
||||||
|
* @param items The ItemStacks to use as storage contents
|
||||||
|
* @throws IllegalArgumentException If the array has more items than the
|
||||||
|
* inventory.
|
||||||
|
*/
|
||||||
|
void setStorageContents(ItemStack[] items) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the inventory contains any ItemStacks with the given
|
||||||
|
* material.
|
||||||
|
*
|
||||||
|
* @param material The material to check for
|
||||||
|
* @return true if an ItemStack is found with the given Material
|
||||||
|
* @throws IllegalArgumentException if material is null
|
||||||
|
*/
|
||||||
|
boolean contains(Key material) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the inventory contains any ItemStacks matching the given
|
||||||
|
* ItemStack.
|
||||||
|
* <p>
|
||||||
|
* This will only return true if both the type and the amount of the stack
|
||||||
|
* match.
|
||||||
|
*
|
||||||
|
* @param item The ItemStack to match against
|
||||||
|
* @return false if item is null, true if any exactly matching ItemStacks
|
||||||
|
* were found
|
||||||
|
*/
|
||||||
|
@Contract("null -> false")
|
||||||
|
boolean contains(ItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the inventory contains any ItemStacks with the given
|
||||||
|
* material, adding to at least the minimum amount specified.
|
||||||
|
*
|
||||||
|
* @param material The material to check for
|
||||||
|
* @param amount The minimum amount
|
||||||
|
* @return true if amount is less than 1, true if enough ItemStacks were
|
||||||
|
* found to add to the given amount
|
||||||
|
* @throws IllegalArgumentException if material is null
|
||||||
|
*/
|
||||||
|
boolean contains(Key material, int amount) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the inventory contains at least the minimum amount specified
|
||||||
|
* of exactly matching ItemStacks.
|
||||||
|
* <p>
|
||||||
|
* An ItemStack only counts if both the type and the amount of the stack
|
||||||
|
* match.
|
||||||
|
*
|
||||||
|
* @param item the ItemStack to match against
|
||||||
|
* @param amount how many identical stacks to check for
|
||||||
|
* @return false if item is null, true if amount less than 1, true if
|
||||||
|
* amount of exactly matching ItemStacks were found
|
||||||
|
* @see #containsAtLeast(ItemStack, int)
|
||||||
|
*/
|
||||||
|
@Contract("null, _ -> false")
|
||||||
|
boolean contains(ItemStack item, int amount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the inventory contains ItemStacks matching the given
|
||||||
|
* ItemStack whose amounts sum to at least the minimum amount specified.
|
||||||
|
*
|
||||||
|
* @param item the ItemStack to match against
|
||||||
|
* @param amount the minimum amount
|
||||||
|
* @return false if item is null, true if amount less than 1, true if
|
||||||
|
* enough ItemStacks were found to add to the given amount
|
||||||
|
*/
|
||||||
|
@Contract("null, _ -> false")
|
||||||
|
boolean containsAtLeast(ItemStack item, int amount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HashMap with all slots and ItemStacks in the inventory with
|
||||||
|
* the given Material.
|
||||||
|
* <p>
|
||||||
|
* The HashMap contains entries where, the key is the slot index, and the
|
||||||
|
* value is the ItemStack in that slot. If no matching ItemStack with the
|
||||||
|
* given Material is found, an empty map is returned.
|
||||||
|
*
|
||||||
|
* @param material The material to look for
|
||||||
|
* @return A HashMap containing the slot index, ItemStack pairs
|
||||||
|
* @throws IllegalArgumentException if material is null
|
||||||
|
*/
|
||||||
|
HashMap<Integer, ? extends ItemStack> all(Key material) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all slots in the inventory containing any ItemStacks with the
|
||||||
|
* given ItemStack. This will only match slots if both the type and the
|
||||||
|
* amount of the stack match
|
||||||
|
* <p>
|
||||||
|
* The HashMap contains entries where, the key is the slot index, and the
|
||||||
|
* value is the ItemStack in that slot. If no matching ItemStack with the
|
||||||
|
* given Material is found, an empty map is returned.
|
||||||
|
*
|
||||||
|
* @param item The ItemStack to match against
|
||||||
|
* @return A map from slot indexes to item at index
|
||||||
|
*/
|
||||||
|
HashMap<Integer, ? extends ItemStack> all(ItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the first slot in the inventory containing an ItemStack with the
|
||||||
|
* given material
|
||||||
|
*
|
||||||
|
* @param material The material to look for
|
||||||
|
* @return The slot index of the given Material or -1 if not found
|
||||||
|
* @throws IllegalArgumentException if material is null
|
||||||
|
*/
|
||||||
|
int first(Key material) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first slot in the inventory containing an ItemStack with
|
||||||
|
* the given stack. This will only match a slot if both the type and the
|
||||||
|
* amount of the stack match
|
||||||
|
*
|
||||||
|
* @param item The ItemStack to match against
|
||||||
|
* @return The slot index of the given ItemStack or -1 if not found
|
||||||
|
*/
|
||||||
|
int first(ItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first empty Slot.
|
||||||
|
*
|
||||||
|
* @return The first empty Slot found, or -1 if no empty slots.
|
||||||
|
*/
|
||||||
|
int firstEmpty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether or not this inventory is empty. An inventory is considered
|
||||||
|
* to be empty if there are no ItemStacks in any slot of this inventory.
|
||||||
|
*
|
||||||
|
* @return true if empty, false otherwise
|
||||||
|
*/
|
||||||
|
boolean isEmpty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all stacks in the inventory matching the given material.
|
||||||
|
*
|
||||||
|
* @param material The material to remove
|
||||||
|
* @throws IllegalArgumentException if material is null
|
||||||
|
*/
|
||||||
|
void remove(Key material) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all stacks in the inventory matching the given stack.
|
||||||
|
* <p>
|
||||||
|
* This will only match a slot if both the type and the amount of the
|
||||||
|
* stack match
|
||||||
|
*
|
||||||
|
* @param item The ItemStack to match against
|
||||||
|
*/
|
||||||
|
void remove(ItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears out a particular slot in the index.
|
||||||
|
*
|
||||||
|
* @param index The index to empty.
|
||||||
|
*/
|
||||||
|
void clear(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears out the whole Inventory.
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of players viewing the inventory. Note that a player is
|
||||||
|
* considered to be viewing their own inventory and internal crafting
|
||||||
|
* screen even when said inventory is not open. They will normally be
|
||||||
|
* considered to be viewing their inventory even when they have a
|
||||||
|
* different inventory screen open, but it's possible for customized
|
||||||
|
* inventory screens to exclude the viewer's inventory, so this should
|
||||||
|
* never be assumed to be non-empty.
|
||||||
|
*
|
||||||
|
* @return A set of HumanEntities who are viewing this Inventory.
|
||||||
|
*/
|
||||||
|
Set<Player> getViewers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns what type of inventory this is.
|
||||||
|
*
|
||||||
|
* @return The InventoryType representing the type of inventory.
|
||||||
|
*/
|
||||||
|
InventoryType getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the block or entity belonging to the open inventory
|
||||||
|
*
|
||||||
|
* @return The holder of the inventory; null if it has no holder.
|
||||||
|
*/
|
||||||
|
InventoryHolder getHolder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ListIterator<ItemStack> iterator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator starting at the given index. If the index is
|
||||||
|
* positive, then the first call to next() will return the item at that
|
||||||
|
* index; if it is negative, the first call to previous will return the
|
||||||
|
* item at index (getSize() + index).
|
||||||
|
*
|
||||||
|
* @param index The index.
|
||||||
|
* @return An iterator.
|
||||||
|
*/
|
||||||
|
ListIterator<ItemStack> iterator(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the location of the block or entity which corresponds to this inventory. May return null if this container
|
||||||
|
* was custom created or is a virtual / subcontainer.
|
||||||
|
*
|
||||||
|
* @return location or null if not applicable.
|
||||||
|
*/
|
||||||
|
Location getLocation();
|
||||||
|
|
||||||
|
void updateInventory();
|
||||||
|
|
||||||
|
void updateInventory(Player player);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
Unsafe getUnsafe();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
interface Unsafe {
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
void a(int index, ItemStack itemStack);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
void b(int index, ItemStack itemStack);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
IntUnaryOperator a();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
IntUnaryOperator b();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
Map<Player, Integer> c();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public enum InventoryClickType {
|
||||||
|
|
||||||
|
PICKUP, QUICK_MOVE, SWAP, CLONE, THROW, QUICK_CRAFT, PICKUP_ALL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public interface InventoryHolder {
|
||||||
|
|
||||||
|
Inventory getInventory();
|
||||||
|
|
||||||
|
InventoryHolder getHolder();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* 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 java.util.ListIterator;
|
||||||
|
|
||||||
|
public class InventoryIterator implements ListIterator<ItemStack> {
|
||||||
|
|
||||||
|
private final Inventory inventory;
|
||||||
|
private int nextIndex;
|
||||||
|
private Boolean lastDirection; // true = forward, false = backward, null = haven't moved yet
|
||||||
|
|
||||||
|
InventoryIterator(Inventory inventory) {
|
||||||
|
this.inventory = inventory;
|
||||||
|
this.nextIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryIterator(Inventory inventory, int index) {
|
||||||
|
this.inventory = inventory;
|
||||||
|
this.nextIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return nextIndex < inventory.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack next() {
|
||||||
|
lastDirection = true;
|
||||||
|
return inventory.getItem(nextIndex++);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextIndex() {
|
||||||
|
return nextIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPrevious() {
|
||||||
|
return nextIndex > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack previous() {
|
||||||
|
lastDirection = false;
|
||||||
|
return inventory.getItem(--nextIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int previousIndex() {
|
||||||
|
return nextIndex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(ItemStack item) {
|
||||||
|
if (lastDirection == null) {
|
||||||
|
throw new IllegalStateException("No current item!");
|
||||||
|
}
|
||||||
|
int i = lastDirection ? nextIndex - 1 : nextIndex;
|
||||||
|
inventory.setItem(i, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(ItemStack item) {
|
||||||
|
throw new UnsupportedOperationException("Can't change the size of an inventory!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException("Can't change the size of an inventory!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,263 @@
|
||||||
|
/*
|
||||||
|
* 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.key.Key;
|
||||||
|
|
||||||
|
public enum InventoryType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A chest inventory, with 0, 9, 18, 27, 36, 45, or 54 slots of type
|
||||||
|
* CONTAINER.
|
||||||
|
*/
|
||||||
|
CHEST(27, "Chest"),
|
||||||
|
/**
|
||||||
|
* A dispenser inventory, with 9 slots of type CONTAINER.
|
||||||
|
*/
|
||||||
|
DISPENSER(9, "Dispenser"),
|
||||||
|
/**
|
||||||
|
* A dropper inventory, with 9 slots of type CONTAINER.
|
||||||
|
*/
|
||||||
|
DROPPER(9, "Dropper"),
|
||||||
|
/**
|
||||||
|
* A furnace inventory, with a RESULT slot, a CRAFTING slot, and a FUEL
|
||||||
|
* slot.
|
||||||
|
*/
|
||||||
|
FURNACE(3, "Furnace"),
|
||||||
|
/**
|
||||||
|
* A workbench inventory, with 9 CRAFTING slots and a RESULT slot.
|
||||||
|
*/
|
||||||
|
WORKBENCH(10, "Crafting"),
|
||||||
|
/**
|
||||||
|
* A player's crafting inventory, with 4 CRAFTING slots and a RESULT slot.
|
||||||
|
* Also implies that the 4 ARMOR slots are accessible.
|
||||||
|
*/
|
||||||
|
CRAFTING(5, "Crafting", false),
|
||||||
|
/**
|
||||||
|
* An enchantment table inventory, with two CRAFTING slots and three
|
||||||
|
* enchanting buttons.
|
||||||
|
*/
|
||||||
|
ENCHANTING(2, "Enchanting"),
|
||||||
|
/**
|
||||||
|
* A brewing stand inventory, with one FUEL slot and four CRAFTING slots.
|
||||||
|
*/
|
||||||
|
BREWING(5, "Brewing"),
|
||||||
|
/**
|
||||||
|
* A player's inventory, with 9 QUICKBAR slots, 27 CONTAINER slots, 4 ARMOR
|
||||||
|
* slots and 1 offhand slot. The ARMOR and offhand slots may not be visible
|
||||||
|
* to the player, though.
|
||||||
|
*/
|
||||||
|
PLAYER(41, "Player"),
|
||||||
|
/**
|
||||||
|
* The creative mode inventory, with only 9 QUICKBAR slots and nothing
|
||||||
|
* else. (The actual creative interface with the items is client-side and
|
||||||
|
* cannot be altered by the server.)
|
||||||
|
*/
|
||||||
|
CREATIVE(9, "Creative", false),
|
||||||
|
/**
|
||||||
|
* The merchant inventory, with 2 CRAFTING slots, and 1 RESULT slot.
|
||||||
|
*/
|
||||||
|
MERCHANT(3, "Villager", false),
|
||||||
|
/**
|
||||||
|
* The ender chest inventory, with 27 slots.
|
||||||
|
*/
|
||||||
|
ENDER_CHEST(27, "Ender Chest"),
|
||||||
|
/**
|
||||||
|
* An anvil inventory, with 2 CRAFTING slots and 1 RESULT slot
|
||||||
|
*/
|
||||||
|
ANVIL(3, "Repairing"),
|
||||||
|
/**
|
||||||
|
* A smithing inventory, with 2 CRAFTING slots and 1 RESULT slot
|
||||||
|
*/
|
||||||
|
SMITHING(3, "Upgrade Gear"),
|
||||||
|
/**
|
||||||
|
* A beacon inventory, with 1 CRAFTING slot
|
||||||
|
*/
|
||||||
|
BEACON(1, "container.beacon"),
|
||||||
|
/**
|
||||||
|
* A hopper inventory, with 5 slots of type CONTAINER.
|
||||||
|
*/
|
||||||
|
HOPPER(5, "Item Hopper"),
|
||||||
|
/**
|
||||||
|
* A shulker box inventory, with 27 slots of type CONTAINER.
|
||||||
|
*/
|
||||||
|
SHULKER_BOX(27, "Shulker Box"),
|
||||||
|
/**
|
||||||
|
* A barrel box inventory, with 27 slots of type CONTAINER.
|
||||||
|
*/
|
||||||
|
BARREL(27, "Barrel"),
|
||||||
|
/**
|
||||||
|
* A blast furnace inventory, with a RESULT slot, a CRAFTING slot, and a
|
||||||
|
* FUEL slot.
|
||||||
|
*/
|
||||||
|
BLAST_FURNACE(3, "Blast Furnace"),
|
||||||
|
/**
|
||||||
|
* A lectern inventory, with 1 BOOK slot.
|
||||||
|
*/
|
||||||
|
LECTERN(1, "Lectern"),
|
||||||
|
/**
|
||||||
|
* A smoker inventory, with a RESULT slot, a CRAFTING slot, and a FUEL slot.
|
||||||
|
*/
|
||||||
|
SMOKER(3, "Smoker"),
|
||||||
|
/**
|
||||||
|
* Loom inventory, with 3 CRAFTING slots, and 1 RESULT slot.
|
||||||
|
*/
|
||||||
|
LOOM(4, "Loom"),
|
||||||
|
/**
|
||||||
|
* Cartography inventory with 2 CRAFTING slots, and 1 RESULT slot.
|
||||||
|
*/
|
||||||
|
CARTOGRAPHY(3, "Cartography Table"),
|
||||||
|
/**
|
||||||
|
* Grindstone inventory with 2 CRAFTING slots, and 1 RESULT slot.
|
||||||
|
*/
|
||||||
|
GRINDSTONE(3, "Repair & Disenchant"),
|
||||||
|
/**
|
||||||
|
* Stonecutter inventory with 1 CRAFTING slot, and 1 RESULT slot.
|
||||||
|
*/
|
||||||
|
STONECUTTER(2, "Stonecutter"),
|
||||||
|
/**
|
||||||
|
* Pseudo composter inventory with 0 or 1 slots of undefined type.
|
||||||
|
*/
|
||||||
|
COMPOSTER(1, "Composter"),
|
||||||
|
/**
|
||||||
|
* Pseudo chiseled bookshelf inventory, with 6 slots of undefined type.
|
||||||
|
*/
|
||||||
|
CHISELED_BOOKSHELF(6, "Chiseled Bookshelf"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final int size;
|
||||||
|
private final String title;
|
||||||
|
private final boolean isCreatable;
|
||||||
|
|
||||||
|
InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle) {
|
||||||
|
this(defaultSize, defaultTitle, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle, boolean isCreatable) {
|
||||||
|
size = defaultSize;
|
||||||
|
title = defaultTitle;
|
||||||
|
this.isCreatable = isCreatable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDefaultSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes that this InventoryType can be created via the normal
|
||||||
|
* {@link org.bukkit.Bukkit#createInventory} methods.
|
||||||
|
*
|
||||||
|
* @return if this InventoryType can be created and shown to a player
|
||||||
|
*/
|
||||||
|
public boolean isCreatable() {
|
||||||
|
return isCreatable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key getRawType(int slots) {
|
||||||
|
switch (this) {
|
||||||
|
case CHEST:
|
||||||
|
return Key.key("minecraft:generic_9x" + (slots / 9));
|
||||||
|
case DISPENSER:
|
||||||
|
case DROPPER:
|
||||||
|
return Key.key("minecraft:generic_3x3");
|
||||||
|
case FURNACE:
|
||||||
|
return Key.key("minecraft:furnace");
|
||||||
|
case WORKBENCH:
|
||||||
|
return Key.key("minecraft:crafting");
|
||||||
|
case ENCHANTING:
|
||||||
|
return Key.key("minecraft:enchantment");
|
||||||
|
case BREWING:
|
||||||
|
return Key.key("minecraft:brewing_stand");
|
||||||
|
case MERCHANT:
|
||||||
|
return Key.key("minecraft:merchant");
|
||||||
|
case ENDER_CHEST:
|
||||||
|
case BARREL:
|
||||||
|
return Key.key("minecraft:generic_9x3");
|
||||||
|
case ANVIL:
|
||||||
|
return Key.key("minecraft:anvil");
|
||||||
|
case SMITHING:
|
||||||
|
return Key.key("minecraft:smithing");
|
||||||
|
case BEACON:
|
||||||
|
return Key.key("minecraft:beacon");
|
||||||
|
case HOPPER:
|
||||||
|
return Key.key("minecraft:hopper");
|
||||||
|
case SHULKER_BOX:
|
||||||
|
return Key.key("minecraft:shulker_box");
|
||||||
|
case BLAST_FURNACE:
|
||||||
|
return Key.key("minecraft:blast_furnace");
|
||||||
|
case LECTERN:
|
||||||
|
return Key.key("minecraft:lectern");
|
||||||
|
case SMOKER:
|
||||||
|
return Key.key("minecraft:smoker");
|
||||||
|
case LOOM:
|
||||||
|
return Key.key("minecraft:loom");
|
||||||
|
case CARTOGRAPHY:
|
||||||
|
return Key.key("minecraft:cartography_table");
|
||||||
|
case GRINDSTONE:
|
||||||
|
return Key.key("minecraft:grindstone");
|
||||||
|
case STONECUTTER:
|
||||||
|
return Key.key("minecraft:stonecutter");
|
||||||
|
case CRAFTING:
|
||||||
|
case PLAYER:
|
||||||
|
case CREATIVE:
|
||||||
|
case COMPOSTER:
|
||||||
|
case CHISELED_BOOKSHELF:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SlotType {
|
||||||
|
/**
|
||||||
|
* A result slot in a furnace or crafting inventory.
|
||||||
|
*/
|
||||||
|
RESULT,
|
||||||
|
/**
|
||||||
|
* A slot in the crafting matrix, or an 'input' slot.
|
||||||
|
*/
|
||||||
|
CRAFTING,
|
||||||
|
/**
|
||||||
|
* An armour slot in the player's inventory.
|
||||||
|
*/
|
||||||
|
ARMOR,
|
||||||
|
/**
|
||||||
|
* A regular slot in the container or the player's inventory; anything
|
||||||
|
* not covered by the other enum values.
|
||||||
|
*/
|
||||||
|
CONTAINER,
|
||||||
|
/**
|
||||||
|
* A slot in the bottom row or quickbar.
|
||||||
|
*/
|
||||||
|
QUICKBAR,
|
||||||
|
/**
|
||||||
|
* A pseudo-slot representing the area outside the inventory window.
|
||||||
|
*/
|
||||||
|
OUTSIDE,
|
||||||
|
/**
|
||||||
|
* The fuel slot in a furnace inventory, or the ingredient slot in a
|
||||||
|
* brewing stand inventory.
|
||||||
|
*/
|
||||||
|
FUEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface InventoryUpdateListener {
|
||||||
|
|
||||||
|
void slotChanged(Inventory inventory, int slot, ItemStack oldItem, ItemStack newItem);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,267 @@
|
||||||
|
/*
|
||||||
|
* 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 com.loohp.limbo.network.protocol.packets.PacketPlayOutWindowData;
|
||||||
|
import com.loohp.limbo.player.Player;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class InventoryView {
|
||||||
|
|
||||||
|
private final Player player;
|
||||||
|
private final String title;
|
||||||
|
private Inventory topInventory;
|
||||||
|
private final Inventory bottomInventory;
|
||||||
|
private final Map<Property, Integer> properties;
|
||||||
|
private ItemStack carriedItem;
|
||||||
|
|
||||||
|
private final Unsafe unsafe;
|
||||||
|
|
||||||
|
public InventoryView(Player player, String title, Inventory topInventory, Inventory bottomInventory) {
|
||||||
|
this.player = player;
|
||||||
|
this.title = title;
|
||||||
|
this.topInventory = topInventory;
|
||||||
|
this.bottomInventory = bottomInventory;
|
||||||
|
this.properties = new ConcurrentHashMap<>();
|
||||||
|
this.carriedItem = null;
|
||||||
|
|
||||||
|
this.unsafe = new Unsafe(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getCarriedItem() {
|
||||||
|
return carriedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCarriedItem(ItemStack carriedItem) {
|
||||||
|
this.carriedItem = carriedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryType getType() {
|
||||||
|
return topInventory.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getTopInventory() {
|
||||||
|
return topInventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getBottomInventory() {
|
||||||
|
return bottomInventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Property, Integer> getProperties() {
|
||||||
|
return Collections.unmodifiableMap(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countSlots() {
|
||||||
|
return topInventory.getSize() + bottomInventory.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getItem(int index) {
|
||||||
|
if (topInventory != null) {
|
||||||
|
if (index < topInventory.getSize()) {
|
||||||
|
return topInventory.getItem(topInventory.getUnsafe().b().applyAsInt(index));
|
||||||
|
}
|
||||||
|
index -= topInventory.getSize();
|
||||||
|
}
|
||||||
|
return bottomInventory.getItem(bottomInventory.getUnsafe().b().applyAsInt(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItem(int index, ItemStack itemStack) {
|
||||||
|
if (topInventory != null) {
|
||||||
|
if (index < topInventory.getSize()) {
|
||||||
|
topInventory.setItem(topInventory.getUnsafe().b().applyAsInt(index), itemStack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index -= topInventory.getSize();
|
||||||
|
}
|
||||||
|
bottomInventory.setItem(bottomInventory.getUnsafe().b().applyAsInt(index), itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperty(InventoryView.Property prop, int value) {
|
||||||
|
if (topInventory != null && prop.getType().equals(topInventory.getType())) {
|
||||||
|
Integer id = topInventory.getUnsafe().c().get(player);
|
||||||
|
if (id != null) {
|
||||||
|
properties.put(prop, value);
|
||||||
|
PacketPlayOutWindowData packet = new PacketPlayOutWindowData(id, prop.getId(), value);
|
||||||
|
try {
|
||||||
|
player.clientConnection.sendPacket(packet);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||||
|
@Deprecated
|
||||||
|
public Unsafe getUnsafe() {
|
||||||
|
return unsafe;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||||
|
@Deprecated
|
||||||
|
public static class Unsafe {
|
||||||
|
|
||||||
|
private final InventoryView inventoryView;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public Unsafe(InventoryView inventoryView) {
|
||||||
|
this.inventoryView = inventoryView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void a(Inventory topInventory) {
|
||||||
|
inventoryView.topInventory = topInventory;
|
||||||
|
inventoryView.properties.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents various extra properties of certain inventory windows.
|
||||||
|
*/
|
||||||
|
public enum Property {
|
||||||
|
/**
|
||||||
|
* The progress of the down-pointing arrow in a brewing inventory.
|
||||||
|
*/
|
||||||
|
BREW_TIME(0, InventoryType.BREWING),
|
||||||
|
/**
|
||||||
|
* The progress of the fuel slot in a brewing inventory.
|
||||||
|
* <p>
|
||||||
|
* This is a value between 0 and 20, with 0 making the bar empty, and 20
|
||||||
|
* making the bar full.
|
||||||
|
*/
|
||||||
|
FUEL_TIME(1, InventoryType.BREWING),
|
||||||
|
/**
|
||||||
|
* The progress of the flame in a furnace inventory.
|
||||||
|
*/
|
||||||
|
BURN_TIME(0, InventoryType.FURNACE),
|
||||||
|
/**
|
||||||
|
* How many total ticks the current fuel should last.
|
||||||
|
*/
|
||||||
|
TICKS_FOR_CURRENT_FUEL(1, InventoryType.FURNACE),
|
||||||
|
/**
|
||||||
|
* The progress of the right-pointing arrow in a furnace inventory.
|
||||||
|
*/
|
||||||
|
COOK_TIME(2, InventoryType.FURNACE),
|
||||||
|
/**
|
||||||
|
* How many total ticks the current smelting should last.
|
||||||
|
*/
|
||||||
|
TICKS_FOR_CURRENT_SMELTING(3, InventoryType.FURNACE),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the top button's experience level
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
ENCHANT_BUTTON1(0, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the middle button's experience level
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
ENCHANT_BUTTON2(1, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the bottom button's experience level
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
ENCHANT_BUTTON3(2, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the first four bits of the player's xpSeed.
|
||||||
|
*/
|
||||||
|
ENCHANT_XP_SEED(3, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the top button's enchantment's id
|
||||||
|
*/
|
||||||
|
ENCHANT_ID1(4, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the middle button's enchantment's id
|
||||||
|
*/
|
||||||
|
ENCHANT_ID2(5, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the bottom button's enchantment's id
|
||||||
|
*/
|
||||||
|
ENCHANT_ID3(6, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the top button's level value.
|
||||||
|
*/
|
||||||
|
ENCHANT_LEVEL1(7, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the middle button's level value.
|
||||||
|
*/
|
||||||
|
ENCHANT_LEVEL2(8, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an enchanting inventory, the bottom button's level value.
|
||||||
|
*/
|
||||||
|
ENCHANT_LEVEL3(9, InventoryType.ENCHANTING),
|
||||||
|
/**
|
||||||
|
* In an beacon inventory, the levels of the beacon
|
||||||
|
*/
|
||||||
|
LEVELS(0, InventoryType.BEACON),
|
||||||
|
/**
|
||||||
|
* In an beacon inventory, the primary potion effect
|
||||||
|
*/
|
||||||
|
PRIMARY_EFFECT(1, InventoryType.BEACON),
|
||||||
|
/**
|
||||||
|
* In an beacon inventory, the secondary potion effect
|
||||||
|
*/
|
||||||
|
SECONDARY_EFFECT(2, InventoryType.BEACON),
|
||||||
|
/**
|
||||||
|
* The repair's cost in xp levels
|
||||||
|
*/
|
||||||
|
REPAIR_COST(0, InventoryType.ANVIL),
|
||||||
|
/**
|
||||||
|
* The lectern's current open book page
|
||||||
|
*/
|
||||||
|
BOOK_PAGE(0, InventoryType.LECTERN);
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
private final InventoryType style;
|
||||||
|
|
||||||
|
Property(int id, InventoryType appliesTo) {
|
||||||
|
this.id = id;
|
||||||
|
style = appliesTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryType getType() {
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id of this view.
|
||||||
|
*
|
||||||
|
* @return the id of this view
|
||||||
|
* @deprecated Magic value
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* 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.key.Key;
|
||||||
|
import net.querz.nbt.tag.CompoundTag;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class ItemStack implements Cloneable {
|
||||||
|
|
||||||
|
public static final ItemStack AIR = new ItemStack(Key.key("minecraft:air"));
|
||||||
|
|
||||||
|
private final Key material;
|
||||||
|
private final int amount;
|
||||||
|
private final CompoundTag nbt;
|
||||||
|
|
||||||
|
private CompoundTag fullTag;
|
||||||
|
|
||||||
|
public ItemStack(Key material) {
|
||||||
|
this(material, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack(Key material, int amount) {
|
||||||
|
this(material, amount, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack(Key material, int amount, CompoundTag nbt) {
|
||||||
|
this.material = material;
|
||||||
|
this.amount = amount;
|
||||||
|
this.nbt = nbt;
|
||||||
|
this.fullTag = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack(CompoundTag fullTag) {
|
||||||
|
this.material = Key.key(fullTag.getString("id"));
|
||||||
|
this.amount = fullTag.getInt("Count");
|
||||||
|
this.nbt = fullTag.containsKey("tag") ? fullTag.getCompoundTag("tag") : null;
|
||||||
|
this.fullTag = fullTag.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||||
|
@Override
|
||||||
|
public ItemStack clone() {
|
||||||
|
return new ItemStack(material, amount, nbt == null ? null : nbt.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key type() {
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack type(Key material) {
|
||||||
|
return new ItemStack(material, amount, nbt == null ? null : nbt.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int amount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack amount(int amount) {
|
||||||
|
return new ItemStack(material, amount, nbt == null ? null : nbt.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundTag nbt() {
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack nbt(CompoundTag nbt) {
|
||||||
|
return new ItemStack(material, amount, nbt == null ? null : nbt.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxStackSize() {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundTag getFullTag() {
|
||||||
|
if (fullTag != null) {
|
||||||
|
return fullTag;
|
||||||
|
}
|
||||||
|
CompoundTag compoundTag = new CompoundTag();
|
||||||
|
compoundTag.putString("id", material.toString());
|
||||||
|
compoundTag.putInt("Count", amount);
|
||||||
|
if (nbt != null) {
|
||||||
|
compoundTag.put("tag", nbt);
|
||||||
|
}
|
||||||
|
return fullTag = compoundTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
ItemStack itemStack = (ItemStack) o;
|
||||||
|
return amount == itemStack.amount && material.equals(itemStack.material) && Objects.equals(nbt, itemStack.nbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSimilar(ItemStack stack) {
|
||||||
|
return material.equals(stack.material) && Objects.equals(nbt, stack.nbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(material, amount, nbt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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 interface TitledInventory extends Inventory {
|
||||||
|
|
||||||
|
Component getTitle();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
* 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.location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the face of a block
|
||||||
|
*/
|
||||||
|
public enum BlockFace {
|
||||||
|
|
||||||
|
NORTH(0, 0, -1),
|
||||||
|
EAST(1, 0, 0),
|
||||||
|
SOUTH(0, 0, 1),
|
||||||
|
WEST(-1, 0, 0),
|
||||||
|
UP(0, 1, 0),
|
||||||
|
DOWN(0, -1, 0),
|
||||||
|
NORTH_EAST(NORTH, EAST),
|
||||||
|
NORTH_WEST(NORTH, WEST),
|
||||||
|
SOUTH_EAST(SOUTH, EAST),
|
||||||
|
SOUTH_WEST(SOUTH, WEST),
|
||||||
|
WEST_NORTH_WEST(WEST, NORTH_WEST),
|
||||||
|
NORTH_NORTH_WEST(NORTH, NORTH_WEST),
|
||||||
|
NORTH_NORTH_EAST(NORTH, NORTH_EAST),
|
||||||
|
EAST_NORTH_EAST(EAST, NORTH_EAST),
|
||||||
|
EAST_SOUTH_EAST(EAST, SOUTH_EAST),
|
||||||
|
SOUTH_SOUTH_EAST(SOUTH, SOUTH_EAST),
|
||||||
|
SOUTH_SOUTH_WEST(SOUTH, SOUTH_WEST),
|
||||||
|
WEST_SOUTH_WEST(WEST, SOUTH_WEST),
|
||||||
|
SELF(0, 0, 0);
|
||||||
|
|
||||||
|
private final int modX;
|
||||||
|
private final int modY;
|
||||||
|
private final int modZ;
|
||||||
|
|
||||||
|
BlockFace(final int modX, final int modY, final int modZ) {
|
||||||
|
this.modX = modX;
|
||||||
|
this.modY = modY;
|
||||||
|
this.modZ = modZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockFace(final BlockFace face1, final BlockFace face2) {
|
||||||
|
this.modX = face1.getModX() + face2.getModX();
|
||||||
|
this.modY = face1.getModY() + face2.getModY();
|
||||||
|
this.modZ = face1.getModZ() + face2.getModZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of X-coordinates to modify to get the represented block
|
||||||
|
*
|
||||||
|
* @return Amount of X-coordinates to modify
|
||||||
|
*/
|
||||||
|
public int getModX() {
|
||||||
|
return modX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of Y-coordinates to modify to get the represented block
|
||||||
|
*
|
||||||
|
* @return Amount of Y-coordinates to modify
|
||||||
|
*/
|
||||||
|
public int getModY() {
|
||||||
|
return modY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of Z-coordinates to modify to get the represented block
|
||||||
|
*
|
||||||
|
* @return Amount of Z-coordinates to modify
|
||||||
|
*/
|
||||||
|
public int getModZ() {
|
||||||
|
return modZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the normal vector corresponding to this block face.
|
||||||
|
*
|
||||||
|
* @return the normal vector
|
||||||
|
*/
|
||||||
|
public Vector getDirection() {
|
||||||
|
Vector direction = new Vector(modX, modY, modZ);
|
||||||
|
if (modX != 0 || modY != 0 || modZ != 0) {
|
||||||
|
direction.normalize();
|
||||||
|
}
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this face is aligned with one of the unit axes in 3D
|
||||||
|
* Cartesian space (ie NORTH, SOUTH, EAST, WEST, UP, DOWN).
|
||||||
|
*
|
||||||
|
* @return Cartesian status
|
||||||
|
*/
|
||||||
|
public boolean isCartesian() {
|
||||||
|
switch (this) {
|
||||||
|
case NORTH:
|
||||||
|
case SOUTH:
|
||||||
|
case EAST:
|
||||||
|
case WEST:
|
||||||
|
case UP:
|
||||||
|
case DOWN:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockFace getOppositeFace() {
|
||||||
|
switch (this) {
|
||||||
|
case NORTH:
|
||||||
|
return BlockFace.SOUTH;
|
||||||
|
|
||||||
|
case SOUTH:
|
||||||
|
return BlockFace.NORTH;
|
||||||
|
|
||||||
|
case EAST:
|
||||||
|
return BlockFace.WEST;
|
||||||
|
|
||||||
|
case WEST:
|
||||||
|
return BlockFace.EAST;
|
||||||
|
|
||||||
|
case UP:
|
||||||
|
return BlockFace.DOWN;
|
||||||
|
|
||||||
|
case DOWN:
|
||||||
|
return BlockFace.UP;
|
||||||
|
|
||||||
|
case NORTH_EAST:
|
||||||
|
return BlockFace.SOUTH_WEST;
|
||||||
|
|
||||||
|
case NORTH_WEST:
|
||||||
|
return BlockFace.SOUTH_EAST;
|
||||||
|
|
||||||
|
case SOUTH_EAST:
|
||||||
|
return BlockFace.NORTH_WEST;
|
||||||
|
|
||||||
|
case SOUTH_WEST:
|
||||||
|
return BlockFace.NORTH_EAST;
|
||||||
|
|
||||||
|
case WEST_NORTH_WEST:
|
||||||
|
return BlockFace.EAST_SOUTH_EAST;
|
||||||
|
|
||||||
|
case NORTH_NORTH_WEST:
|
||||||
|
return BlockFace.SOUTH_SOUTH_EAST;
|
||||||
|
|
||||||
|
case NORTH_NORTH_EAST:
|
||||||
|
return BlockFace.SOUTH_SOUTH_WEST;
|
||||||
|
|
||||||
|
case EAST_NORTH_EAST:
|
||||||
|
return BlockFace.WEST_SOUTH_WEST;
|
||||||
|
|
||||||
|
case EAST_SOUTH_EAST:
|
||||||
|
return BlockFace.WEST_NORTH_WEST;
|
||||||
|
|
||||||
|
case SOUTH_SOUTH_EAST:
|
||||||
|
return BlockFace.NORTH_NORTH_WEST;
|
||||||
|
|
||||||
|
case SOUTH_SOUTH_WEST:
|
||||||
|
return BlockFace.NORTH_NORTH_EAST;
|
||||||
|
|
||||||
|
case WEST_SOUTH_WEST:
|
||||||
|
return BlockFace.EAST_NORTH_EAST;
|
||||||
|
|
||||||
|
case SELF:
|
||||||
|
return BlockFace.SELF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlockFace.SELF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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.location;
|
||||||
|
|
||||||
|
import com.loohp.limbo.entity.Entity;
|
||||||
|
|
||||||
|
public abstract class MovingObjectPosition {
|
||||||
|
|
||||||
|
protected final Vector location;
|
||||||
|
|
||||||
|
protected MovingObjectPosition(Vector vec3d) {
|
||||||
|
this.location = vec3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double distanceTo(Entity entity) {
|
||||||
|
double d0 = this.location.x - entity.getX();
|
||||||
|
double d1 = this.location.y - entity.getY();
|
||||||
|
double d2 = this.location.z - entity.getZ();
|
||||||
|
|
||||||
|
return d0 * d0 + d1 * d1 + d2 * d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract MovingObjectPosition.EnumMovingObjectType getType();
|
||||||
|
|
||||||
|
public Vector getLocation() {
|
||||||
|
return this.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum EnumMovingObjectType {
|
||||||
|
|
||||||
|
MISS, BLOCK, ENTITY;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.location;
|
||||||
|
|
||||||
|
import com.loohp.limbo.world.BlockPosition;
|
||||||
|
|
||||||
|
public class MovingObjectPositionBlock extends MovingObjectPosition {
|
||||||
|
|
||||||
|
private final BlockFace direction;
|
||||||
|
private final BlockPosition blockPos;
|
||||||
|
private final boolean miss;
|
||||||
|
private final boolean inside;
|
||||||
|
|
||||||
|
public static MovingObjectPositionBlock miss(Vector vec3d, BlockFace direction, BlockPosition blockposition) {
|
||||||
|
return new MovingObjectPositionBlock(true, vec3d, direction, blockposition, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovingObjectPositionBlock(Vector vec3d, BlockFace direction, BlockPosition blockposition, boolean flag) {
|
||||||
|
this(false, vec3d, direction, blockposition, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MovingObjectPositionBlock(boolean flag, Vector vec3d, BlockFace direction, BlockPosition blockposition, boolean flag1) {
|
||||||
|
super(vec3d);
|
||||||
|
this.miss = flag;
|
||||||
|
this.direction = direction;
|
||||||
|
this.blockPos = blockposition;
|
||||||
|
this.inside = flag1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovingObjectPositionBlock withDirection(BlockFace direction) {
|
||||||
|
return new MovingObjectPositionBlock(this.miss, this.location, direction, this.blockPos, this.inside);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovingObjectPositionBlock withPosition(BlockPosition blockposition) {
|
||||||
|
return new MovingObjectPositionBlock(this.miss, this.location, this.direction, blockposition, this.inside);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPosition getBlockPos() {
|
||||||
|
return this.blockPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockFace getDirection() {
|
||||||
|
return this.direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MovingObjectPosition.EnumMovingObjectType getType() {
|
||||||
|
return this.miss ? MovingObjectPosition.EnumMovingObjectType.MISS : MovingObjectPosition.EnumMovingObjectType.BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInside() {
|
||||||
|
return this.inside;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,9 @@
|
||||||
package com.loohp.limbo.network;
|
package com.loohp.limbo.network;
|
||||||
|
|
||||||
import com.loohp.limbo.Limbo;
|
import com.loohp.limbo.Limbo;
|
||||||
|
import com.loohp.limbo.events.inventory.InventoryCloseEvent;
|
||||||
|
import com.loohp.limbo.events.inventory.InventoryCreativeEvent;
|
||||||
|
import com.loohp.limbo.events.player.PlayerInteractEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerJoinEvent;
|
import com.loohp.limbo.events.player.PlayerJoinEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerLoginEvent;
|
import com.loohp.limbo.events.player.PlayerLoginEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerMoveEvent;
|
import com.loohp.limbo.events.player.PlayerMoveEvent;
|
||||||
|
|
@ -30,6 +33,7 @@ import com.loohp.limbo.events.player.PlayerSpawnEvent;
|
||||||
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.Inventory;
|
||||||
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;
|
||||||
|
|
@ -40,7 +44,9 @@ 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.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.PacketPlayInHeldItemChange;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInHeldItemChange;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInKeepAlive;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInKeepAlive;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging;
|
||||||
|
|
@ -49,7 +55,10 @@ import com.loohp.limbo.network.protocol.packets.PacketPlayInPositionAndLook;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInResourcePackStatus;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInResourcePackStatus;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInResourcePackStatus.EnumResourcePackStatus;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInResourcePackStatus.EnumResourcePackStatus;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInRotation;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInRotation;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInSetCreativeSlot;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInTabComplete;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInTabComplete;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInUseItem;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInWindowClick;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutDeclareCommands;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutDeclareCommands;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutDisconnect;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutDisconnect;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata;
|
||||||
|
|
@ -86,6 +95,7 @@ import com.loohp.limbo.utils.GameMode;
|
||||||
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;
|
||||||
|
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;
|
||||||
|
|
@ -114,6 +124,7 @@ 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;
|
||||||
|
|
@ -491,7 +502,7 @@ public class ClientConnection extends Thread {
|
||||||
|
|
||||||
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
|
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
|
||||||
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
|
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
|
||||||
Limbo.getInstance().getUnsafe().addPlayer(player);
|
Limbo.getInstance().getUnsafe().a(player);
|
||||||
break;
|
break;
|
||||||
} else if (packetIn instanceof PacketLoginInPluginMessaging) {
|
} else if (packetIn instanceof PacketLoginInPluginMessaging) {
|
||||||
PacketLoginInPluginMessaging response = (PacketLoginInPluginMessaging) packetIn;
|
PacketLoginInPluginMessaging response = (PacketLoginInPluginMessaging) packetIn;
|
||||||
|
|
@ -519,7 +530,7 @@ public class ClientConnection extends Thread {
|
||||||
|
|
||||||
player = new Player(this, data.getUsername(), data.getUuid(), Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
|
player = new Player(this, data.getUsername(), data.getUuid(), Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
|
||||||
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
|
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
|
||||||
Limbo.getInstance().getUnsafe().addPlayer(player);
|
Limbo.getInstance().getUnsafe().a(player);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -551,7 +562,7 @@ public class ClientConnection extends Thread {
|
||||||
|
|
||||||
PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, properties.getDefaultGamemode(), Limbo.getInstance().getWorlds(), Limbo.getInstance().getDimensionRegistry().getCodec(), world, 0, (byte) properties.getMaxPlayers(), 8, 8, properties.isReducedDebugInfo(), true, false, true);
|
PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, properties.getDefaultGamemode(), Limbo.getInstance().getWorlds(), Limbo.getInstance().getDimensionRegistry().getCodec(), world, 0, (byte) properties.getMaxPlayers(), 8, 8, properties.isReducedDebugInfo(), true, false, true);
|
||||||
sendPacket(join);
|
sendPacket(join);
|
||||||
Limbo.getInstance().getUnsafe().setPlayerGameModeSilently(player, properties.getDefaultGamemode());
|
Limbo.getInstance().getUnsafe().a(player, properties.getDefaultGamemode());
|
||||||
|
|
||||||
ByteArrayOutputStream brandOut = new ByteArrayOutputStream();
|
ByteArrayOutputStream brandOut = new ByteArrayOutputStream();
|
||||||
DataTypeIO.writeString(new DataOutputStream(brandOut), properties.getServerModName(), StandardCharsets.UTF_8);
|
DataTypeIO.writeString(new DataOutputStream(brandOut), properties.getServerModName(), StandardCharsets.UTF_8);
|
||||||
|
|
@ -586,7 +597,7 @@ public class ClientConnection extends Thread {
|
||||||
sendPacket(spawnPos);
|
sendPacket(spawnPos);
|
||||||
|
|
||||||
PacketPlayOutPositionAndLook positionLook = new PacketPlayOutPositionAndLook(worldSpawn.getX(), worldSpawn.getY(), worldSpawn.getZ(), worldSpawn.getYaw(), worldSpawn.getPitch(), 1, false);
|
PacketPlayOutPositionAndLook positionLook = new PacketPlayOutPositionAndLook(worldSpawn.getX(), worldSpawn.getY(), worldSpawn.getZ(), worldSpawn.getYaw(), worldSpawn.getPitch(), 1, false);
|
||||||
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, new Location(world, worldSpawn.getX(), worldSpawn.getY(), worldSpawn.getZ(), worldSpawn.getYaw(), worldSpawn.getPitch()));
|
Limbo.getInstance().getUnsafe().a(player, new Location(world, worldSpawn.getX(), worldSpawn.getY(), worldSpawn.getZ(), worldSpawn.getYaw(), worldSpawn.getPitch()));
|
||||||
sendPacket(positionLook);
|
sendPacket(positionLook);
|
||||||
|
|
||||||
player.getDataWatcher().update();
|
player.getDataWatcher().update();
|
||||||
|
|
@ -647,7 +658,7 @@ public class ClientConnection extends Thread {
|
||||||
sendPacket(cancel);
|
sendPacket(cancel);
|
||||||
} else {
|
} else {
|
||||||
Location to = event.getTo();
|
Location to = event.getTo();
|
||||||
Limbo.getInstance().getUnsafe().setPlayerLocationSilently(player, to);
|
Limbo.getInstance().getUnsafe().a(player, to);
|
||||||
// If an event handler used setTo, let's make sure we tell the player about it.
|
// If an event handler used setTo, let's make sure we tell the player about it.
|
||||||
if (!originalTo.equals(to)) {
|
if (!originalTo.equals(to)) {
|
||||||
PacketPlayOutPositionAndLook pos = new PacketPlayOutPositionAndLook(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), 1, false);
|
PacketPlayOutPositionAndLook pos = new PacketPlayOutPositionAndLook(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), 1, false);
|
||||||
|
|
@ -657,7 +668,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();
|
||||||
|
|
@ -720,9 +733,9 @@ public class ClientConnection extends Thread {
|
||||||
} else if (change.getSlot() != event.getSlot()) {
|
} else if (change.getSlot() != event.getSlot()) {
|
||||||
PacketPlayOutHeldItemChange changePacket = new PacketPlayOutHeldItemChange(event.getSlot());
|
PacketPlayOutHeldItemChange changePacket = new PacketPlayOutHeldItemChange(event.getSlot());
|
||||||
sendPacket(changePacket);
|
sendPacket(changePacket);
|
||||||
Limbo.getInstance().getUnsafe().setSelectedSlotSilently(player, event.getSlot());
|
Limbo.getInstance().getUnsafe().a(player, event.getSlot());
|
||||||
} else {
|
} else {
|
||||||
Limbo.getInstance().getUnsafe().setSelectedSlotSilently(player, event.getSlot());
|
Limbo.getInstance().getUnsafe().a(player, event.getSlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (packetIn instanceof PacketPlayInResourcePackStatus) {
|
} else if (packetIn instanceof PacketPlayInResourcePackStatus) {
|
||||||
|
|
@ -735,6 +748,42 @@ public class ClientConnection extends Thread {
|
||||||
} else if (packetIn instanceof PacketPlayInPluginMessaging) {
|
} else if (packetIn instanceof PacketPlayInPluginMessaging) {
|
||||||
PacketPlayInPluginMessaging inPluginMessaging = (PacketPlayInPluginMessaging) packetIn;
|
PacketPlayInPluginMessaging inPluginMessaging = (PacketPlayInPluginMessaging) packetIn;
|
||||||
Limbo.getInstance().getEventsManager().callEvent(new PluginMessageEvent(player, inPluginMessaging.getChannel(), inPluginMessaging.getData()));
|
Limbo.getInstance().getEventsManager().callEvent(new PluginMessageEvent(player, inPluginMessaging.getChannel(), inPluginMessaging.getData()));
|
||||||
|
} else if (packetIn instanceof PacketPlayInBlockPlace) {
|
||||||
|
PacketPlayInBlockPlace packet = (PacketPlayInBlockPlace) packetIn;
|
||||||
|
Limbo.getInstance().getEventsManager().callEvent(new PlayerInteractEvent(player, PlayerInteractEvent.Action.RIGHT_CLICK_AIR, player.getEquipment().getItem(packet.getHand()), null, null, packet.getHand()));
|
||||||
|
} else if (packetIn instanceof PacketPlayInUseItem) {
|
||||||
|
PacketPlayInUseItem packet = (PacketPlayInUseItem) packetIn;
|
||||||
|
BlockState block = player.getWorld().getBlock(packet.getBlockHit().getBlockPos());
|
||||||
|
Limbo.getInstance().getEventsManager().callEvent(new PlayerInteractEvent(player, PlayerInteractEvent.Action.RIGHT_CLICK_AIR, player.getEquipment().getItem(packet.getHand()), block, packet.getBlockHit().getDirection(), packet.getHand()));
|
||||||
|
} else if (packetIn instanceof PacketPlayInSetCreativeSlot) {
|
||||||
|
PacketPlayInSetCreativeSlot packet = (PacketPlayInSetCreativeSlot) packetIn;
|
||||||
|
InventoryCreativeEvent event = Limbo.getInstance().getEventsManager().callEvent(new InventoryCreativeEvent(player, player.getInventoryView(), player.getInventory(), player.getInventory().getUnsafe().b().applyAsInt(packet.getSlotNumber()), packet.getItemStack()));
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
player.updateInventory();
|
||||||
|
} else {
|
||||||
|
player.getInventory().getUnsafe().b(packet.getSlotNumber(), event.getNewItem());
|
||||||
|
}
|
||||||
|
} else if (packetIn instanceof PacketPlayInWindowClick) {
|
||||||
|
PacketPlayInWindowClick packet = (PacketPlayInWindowClick) packetIn;
|
||||||
|
/*
|
||||||
|
InventoryCreativeEvent event = Limbo.getInstance().getEventsManager().callEvent(new InventoryCreativeEvent(player, player.getInventoryView(), player.getInventory(), player.getInventory().getUnsafe().b().applyAsInt(packet.getSlotNumber()), packet.getItemStack()));
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
player.updateInventory();
|
||||||
|
} else {
|
||||||
|
player.getInventory().getUnsafe().b(packet.getSlotNumber(), event.getNewItem());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
} else if (packetIn instanceof PacketPlayInCloseWindow) {
|
||||||
|
PacketPlayInCloseWindow packet = (PacketPlayInCloseWindow) packetIn;
|
||||||
|
Inventory inventory = player.getInventoryView().getTopInventory();
|
||||||
|
if (inventory != null) {
|
||||||
|
Integer id = inventory.getUnsafe().c().get(player);
|
||||||
|
if (id != null) {
|
||||||
|
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(player, player.getInventoryView()));
|
||||||
|
player.getInventoryView().getUnsafe().a(null);
|
||||||
|
inventory.getUnsafe().c().remove(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -757,7 +806,7 @@ public class ClientConnection extends Thread {
|
||||||
state = ClientState.DISCONNECTED;
|
state = ClientState.DISCONNECTED;
|
||||||
|
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
Limbo.getInstance().getUnsafe().removePlayer(player);
|
Limbo.getInstance().getUnsafe().b(player);
|
||||||
}
|
}
|
||||||
Limbo.getInstance().getServerConnection().getClients().remove(this);
|
Limbo.getInstance().getServerConnection().getClients().remove(this);
|
||||||
running = false;
|
running = false;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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.inventory.EquipmentSlot;
|
||||||
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PacketPlayInBlockPlace extends PacketIn {
|
||||||
|
|
||||||
|
private EquipmentSlot hand;
|
||||||
|
private int sequence;
|
||||||
|
|
||||||
|
public PacketPlayInBlockPlace(EquipmentSlot hand, int sequence) {
|
||||||
|
this.hand = hand;
|
||||||
|
this.sequence = sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketPlayInBlockPlace(DataInputStream in) throws IOException {
|
||||||
|
this(EquipmentSlot.values()[DataTypeIO.readVarInt(in)], DataTypeIO.readVarInt(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
public EquipmentSlot getHand() {
|
||||||
|
return hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSequence() {
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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 java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PacketPlayInCloseWindow extends PacketIn {
|
||||||
|
|
||||||
|
private int containerId;
|
||||||
|
|
||||||
|
public PacketPlayInCloseWindow(int containerId) {
|
||||||
|
this.containerId = containerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketPlayInCloseWindow(DataInputStream in) throws IOException {
|
||||||
|
this(in.readByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContainerId() {
|
||||||
|
return containerId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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.inventory.ItemStack;
|
||||||
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PacketPlayInSetCreativeSlot extends PacketIn {
|
||||||
|
|
||||||
|
private int slotNumber;
|
||||||
|
private ItemStack itemStack;
|
||||||
|
|
||||||
|
public PacketPlayInSetCreativeSlot(int slotNumber, ItemStack itemStack) {
|
||||||
|
this.slotNumber = slotNumber;
|
||||||
|
this.itemStack = itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketPlayInSetCreativeSlot(DataInputStream in) throws IOException {
|
||||||
|
this(in.readShort(), DataTypeIO.readItemStack(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlotNumber() {
|
||||||
|
return slotNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getItemStack() {
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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.inventory.EquipmentSlot;
|
||||||
|
import com.loohp.limbo.location.MovingObjectPositionBlock;
|
||||||
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PacketPlayInUseItem extends PacketIn {
|
||||||
|
|
||||||
|
private EquipmentSlot hand;
|
||||||
|
private MovingObjectPositionBlock blockHit;
|
||||||
|
private int sequence;
|
||||||
|
|
||||||
|
public PacketPlayInUseItem(EquipmentSlot hand, MovingObjectPositionBlock blockHit, int sequence) {
|
||||||
|
this.hand = hand;
|
||||||
|
this.blockHit = blockHit;
|
||||||
|
this.sequence = sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketPlayInUseItem(DataInputStream in) throws IOException {
|
||||||
|
this(EquipmentSlot.values()[DataTypeIO.readVarInt(in)], DataTypeIO.readBlockHitResult(in), DataTypeIO.readVarInt(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
public EquipmentSlot getHand() {
|
||||||
|
return hand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovingObjectPositionBlock getBlockHit() {
|
||||||
|
return blockHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSequence() {
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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.inventory.InventoryClickType;
|
||||||
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class PacketPlayInWindowClick extends PacketIn {
|
||||||
|
|
||||||
|
private int containerId;
|
||||||
|
private int stateId;
|
||||||
|
private int slotNum;
|
||||||
|
private int buttonNum;
|
||||||
|
private InventoryClickType clickType;
|
||||||
|
private Map<Integer, ItemStack> changedSlots;
|
||||||
|
private ItemStack carriedItem;
|
||||||
|
|
||||||
|
public PacketPlayInWindowClick(int containerId, int stateId, int slotNum, int buttonNum, InventoryClickType clickType, Map<Integer, ItemStack> changedSlots, ItemStack carriedItem) {
|
||||||
|
this.containerId = containerId;
|
||||||
|
this.stateId = stateId;
|
||||||
|
this.slotNum = slotNum;
|
||||||
|
this.buttonNum = buttonNum;
|
||||||
|
this.clickType = clickType;
|
||||||
|
this.changedSlots = changedSlots;
|
||||||
|
this.carriedItem = carriedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketPlayInWindowClick(DataInputStream in) throws IOException {
|
||||||
|
this.containerId = in.readByte();
|
||||||
|
this.stateId = DataTypeIO.readVarInt(in);
|
||||||
|
this.slotNum = in.readShort();
|
||||||
|
this.buttonNum = in.readByte();
|
||||||
|
this.clickType = InventoryClickType.values()[DataTypeIO.readVarInt(in)];
|
||||||
|
Map<Integer, ItemStack> changedSlots = new HashMap<>();
|
||||||
|
int size = DataTypeIO.readVarInt(in);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
int slot = in.readShort();
|
||||||
|
ItemStack itemStack = DataTypeIO.readItemStack(in);
|
||||||
|
changedSlots.put(slot, itemStack);
|
||||||
|
}
|
||||||
|
this.changedSlots = Collections.unmodifiableMap(changedSlots);
|
||||||
|
this.carriedItem = DataTypeIO.readItemStack(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContainerId() {
|
||||||
|
return containerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStateId() {
|
||||||
|
return stateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlotNum() {
|
||||||
|
return slotNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getButtonNum() {
|
||||||
|
return buttonNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryClickType getClickType() {
|
||||||
|
return clickType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Integer, ItemStack> getChangedSlots() {
|
||||||
|
return changedSlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getCarriedItem() {
|
||||||
|
return carriedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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 java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PacketPlayOutCloseWindow extends PacketOut {
|
||||||
|
|
||||||
|
private int containerId;
|
||||||
|
|
||||||
|
public PacketPlayOutCloseWindow(int containerId) {
|
||||||
|
this.containerId = containerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContainerId() {
|
||||||
|
return containerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serializePacket() throws IOException {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
|
|
||||||
|
output.writeByte(containerId);
|
||||||
|
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* 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.registry.Registry;
|
||||||
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class PacketPlayOutOpenWindow extends PacketOut {
|
||||||
|
|
||||||
|
private int containerId;
|
||||||
|
private Key type;
|
||||||
|
private Component title;
|
||||||
|
|
||||||
|
public PacketPlayOutOpenWindow(int containerId, Key type, Component title) {
|
||||||
|
this.containerId = containerId;
|
||||||
|
this.type = type;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContainerId() {
|
||||||
|
return containerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serializePacket() throws IOException {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
|
|
||||||
|
DataTypeIO.writeVarInt(output, containerId);
|
||||||
|
DataTypeIO.writeVarInt(output, Registry.MENU_REGISTRY.getId(type));
|
||||||
|
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(title), StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.inventory.ItemStack;
|
||||||
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PacketPlayOutSetSlot extends PacketOut {
|
||||||
|
|
||||||
|
private int containerId;
|
||||||
|
private int stateId;
|
||||||
|
private int slot;
|
||||||
|
private ItemStack itemStack;
|
||||||
|
|
||||||
|
public PacketPlayOutSetSlot(int containerId, int stateId, int slot, ItemStack itemStack) {
|
||||||
|
this.containerId = containerId;
|
||||||
|
this.stateId = stateId;
|
||||||
|
this.slot = slot;
|
||||||
|
this.itemStack = itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContainerId() {
|
||||||
|
return containerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStateId() {
|
||||||
|
return stateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlot() {
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getItemStack() {
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serializePacket() throws IOException {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
|
|
||||||
|
output.writeByte(containerId);
|
||||||
|
DataTypeIO.writeVarInt(output, stateId);
|
||||||
|
output.writeShort(slot);
|
||||||
|
DataTypeIO.writeItemStack(output, itemStack);
|
||||||
|
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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 java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PacketPlayOutWindowData extends PacketOut {
|
||||||
|
|
||||||
|
private int containerId;
|
||||||
|
private int id;
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
public PacketPlayOutWindowData(int containerId, int id, int value) {
|
||||||
|
this.containerId = containerId;
|
||||||
|
this.id = id;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContainerId() {
|
||||||
|
return containerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serializePacket() throws IOException {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
|
|
||||||
|
output.writeByte(containerId);
|
||||||
|
output.writeShort(id);
|
||||||
|
output.writeShort(value);
|
||||||
|
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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.inventory.ItemStack;
|
||||||
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PacketPlayOutWindowItems extends PacketOut {
|
||||||
|
|
||||||
|
private int containerId;
|
||||||
|
private int stateId;
|
||||||
|
private List<ItemStack> items;
|
||||||
|
private ItemStack carriedItem;
|
||||||
|
|
||||||
|
public PacketPlayOutWindowItems(int containerId, int stateId, List<ItemStack> items, ItemStack carriedItem) {
|
||||||
|
this.containerId = containerId;
|
||||||
|
this.stateId = stateId;
|
||||||
|
this.items = items;
|
||||||
|
this.carriedItem = carriedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getContainerId() {
|
||||||
|
return containerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStateId() {
|
||||||
|
return stateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ItemStack> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getCarriedItem() {
|
||||||
|
return carriedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serializePacket() throws IOException {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
|
|
||||||
|
output.writeByte(containerId);
|
||||||
|
DataTypeIO.writeVarInt(output, stateId);
|
||||||
|
DataTypeIO.writeVarInt(output, items.size());
|
||||||
|
for (ItemStack itemStack : items) {
|
||||||
|
DataTypeIO.writeItemStack(output, itemStack);
|
||||||
|
}
|
||||||
|
DataTypeIO.writeItemStack(output, carriedItem);
|
||||||
|
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,10 +24,17 @@ import com.loohp.limbo.commands.CommandSender;
|
||||||
import com.loohp.limbo.entity.DataWatcher;
|
import com.loohp.limbo.entity.DataWatcher;
|
||||||
import com.loohp.limbo.entity.DataWatcher.WatchableField;
|
import com.loohp.limbo.entity.DataWatcher.WatchableField;
|
||||||
import com.loohp.limbo.entity.DataWatcher.WatchableObjectType;
|
import com.loohp.limbo.entity.DataWatcher.WatchableObjectType;
|
||||||
|
import com.loohp.limbo.entity.EntityEquipment;
|
||||||
import com.loohp.limbo.entity.EntityType;
|
import com.loohp.limbo.entity.EntityType;
|
||||||
import com.loohp.limbo.entity.LivingEntity;
|
import com.loohp.limbo.entity.LivingEntity;
|
||||||
|
import com.loohp.limbo.events.inventory.InventoryCloseEvent;
|
||||||
|
import com.loohp.limbo.events.inventory.InventoryOpenEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerChatEvent;
|
import com.loohp.limbo.events.player.PlayerChatEvent;
|
||||||
import com.loohp.limbo.events.player.PlayerTeleportEvent;
|
import com.loohp.limbo.events.player.PlayerTeleportEvent;
|
||||||
|
import com.loohp.limbo.inventory.Inventory;
|
||||||
|
import com.loohp.limbo.inventory.InventoryHolder;
|
||||||
|
import com.loohp.limbo.inventory.InventoryView;
|
||||||
|
import com.loohp.limbo.inventory.TitledInventory;
|
||||||
import com.loohp.limbo.location.Location;
|
import com.loohp.limbo.location.Location;
|
||||||
import com.loohp.limbo.network.ClientConnection;
|
import com.loohp.limbo.network.ClientConnection;
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundClearTitlesPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundClearTitlesPacket;
|
||||||
|
|
@ -37,9 +44,11 @@ import com.loohp.limbo.network.protocol.packets.ClientboundSetTitleTextPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitlesAnimationPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundSetTitlesAnimationPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket;
|
import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketOut;
|
import com.loohp.limbo.network.protocol.packets.PacketOut;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutCloseWindow;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameState;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameState;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutNamedSoundEffect;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutNamedSoundEffect;
|
||||||
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutOpenWindow;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerListHeaderFooter;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerListHeaderFooter;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPositionAndLook;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPositionAndLook;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutResourcePackSend;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutResourcePackSend;
|
||||||
|
|
@ -70,8 +79,9 @@ import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class Player extends LivingEntity implements CommandSender {
|
public class Player extends LivingEntity implements CommandSender, InventoryHolder {
|
||||||
|
|
||||||
public static final String CHAT_DEFAULT_FORMAT = "<%name%> %message%";
|
public static final String CHAT_DEFAULT_FORMAT = "<%name%> %message%";
|
||||||
|
|
||||||
|
|
@ -82,6 +92,9 @@ public class Player extends LivingEntity implements CommandSender {
|
||||||
protected GameMode gamemode;
|
protected GameMode gamemode;
|
||||||
protected DataWatcher watcher;
|
protected DataWatcher watcher;
|
||||||
protected byte selectedSlot;
|
protected byte selectedSlot;
|
||||||
|
protected final PlayerInventory playerInventory;
|
||||||
|
protected final InventoryView inventoryView;
|
||||||
|
private final AtomicInteger containerIdCounter;
|
||||||
|
|
||||||
@WatchableField(MetadataIndex = 15, WatchableObjectType = WatchableObjectType.FLOAT)
|
@WatchableField(MetadataIndex = 15, WatchableObjectType = WatchableObjectType.FLOAT)
|
||||||
protected float additionalHearts = 0.0F;
|
protected float additionalHearts = 0.0F;
|
||||||
|
|
@ -101,12 +114,19 @@ public class Player extends LivingEntity implements CommandSender {
|
||||||
this.clientConnection = clientConnection;
|
this.clientConnection = clientConnection;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
|
this.containerIdCounter = new AtomicInteger(1);
|
||||||
|
this.playerInventory = new PlayerInventory(this);
|
||||||
|
this.inventoryView = new InventoryView(this, null, null, playerInventory);
|
||||||
this.playerInteractManager = playerInteractManager;
|
this.playerInteractManager = playerInteractManager;
|
||||||
this.playerInteractManager.setPlayer(this);
|
this.playerInteractManager.setPlayer(this);
|
||||||
this.watcher = new DataWatcher(this);
|
this.watcher = new DataWatcher(this);
|
||||||
this.watcher.update();
|
this.watcher.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int nextContainerId() {
|
||||||
|
return containerIdCounter.updateAndGet(i -> ++i > Byte.MAX_VALUE ? 1 : i);
|
||||||
|
}
|
||||||
|
|
||||||
public byte getSelectedSlot() {
|
public byte getSelectedSlot() {
|
||||||
return selectedSlot;
|
return selectedSlot;
|
||||||
}
|
}
|
||||||
|
|
@ -551,14 +571,81 @@ public class Player extends LivingEntity implements CommandSender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use {@link com.loohp.limbo.bossbar.KeyedBossBar#showPlayer(Player)} instead
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public void showBossBar(BossBar bar) {
|
public void showBossBar(BossBar bar) {
|
||||||
throw new UnsupportedOperationException("This function has not been implemented yet.");
|
Limbo.getInstance().getBossBars().values().stream().filter(each -> each.getProperties() == bar).findFirst().ifPresent(each -> each.showPlayer(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use {@link com.loohp.limbo.bossbar.KeyedBossBar#hidePlayer(Player)} instead
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public void hideBossBar(BossBar bar) {
|
||||||
|
Limbo.getInstance().getBossBars().values().stream().filter(each -> each.getProperties() == bar).findFirst().ifPresent(each -> each.hidePlayer(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hideBossBar(BossBar bar) {
|
public PlayerInventory getInventory() {
|
||||||
throw new UnsupportedOperationException("This function has not been implemented yet.");
|
return playerInventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InventoryView getInventoryView() {
|
||||||
|
return inventoryView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateInventory() {
|
||||||
|
playerInventory.updateInventory(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openInventory(Inventory inventory) {
|
||||||
|
inventoryView.getUnsafe().a(inventory);
|
||||||
|
int id = nextContainerId();
|
||||||
|
inventory.getUnsafe().c().put(this, id);
|
||||||
|
InventoryOpenEvent event = Limbo.getInstance().getEventsManager().callEvent(new InventoryOpenEvent(this, inventoryView));
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
inventoryView.getUnsafe().a(null);
|
||||||
|
inventory.getUnsafe().c().remove(this);
|
||||||
|
} else {
|
||||||
|
Component title = inventory instanceof TitledInventory ? ((TitledInventory) inventory).getTitle() : Component.translatable("container.chest");
|
||||||
|
PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, inventory.getType().getRawType(inventory.getSize()), title);
|
||||||
|
try {
|
||||||
|
clientConnection.sendPacket(packet);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
inventory.updateInventory(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeInventory() {
|
||||||
|
Inventory inventory = inventoryView.getTopInventory();
|
||||||
|
if (inventory != null) {
|
||||||
|
Integer id = inventory.getUnsafe().c().get(this);
|
||||||
|
if (id != null) {
|
||||||
|
Limbo.getInstance().getEventsManager().callEvent(new InventoryCloseEvent(this, inventoryView));
|
||||||
|
inventoryView.getUnsafe().a(null);
|
||||||
|
inventory.getUnsafe().c().remove(this);
|
||||||
|
PacketPlayOutCloseWindow packet = new PacketPlayOutCloseWindow(id);
|
||||||
|
try {
|
||||||
|
clientConnection.sendPacket(packet);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityEquipment getEquipment() {
|
||||||
|
return playerInventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InventoryHolder getHolder() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* 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.player;
|
||||||
|
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import com.google.common.collect.HashBiMap;
|
||||||
|
import com.google.common.collect.ImmutableBiMap;
|
||||||
|
import com.loohp.limbo.entity.EntityEquipment;
|
||||||
|
import com.loohp.limbo.inventory.AbstractInventory;
|
||||||
|
import com.loohp.limbo.inventory.EquipmentSlot;
|
||||||
|
import com.loohp.limbo.inventory.InventoryType;
|
||||||
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
|
import com.loohp.limbo.location.Location;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.ToIntFunction;
|
||||||
|
|
||||||
|
public class PlayerInventory extends AbstractInventory implements EntityEquipment {
|
||||||
|
|
||||||
|
private static final Map<EquipmentSlot, ToIntFunction<PlayerInventory>> EQUIPMENT_SLOT_MAPPING;
|
||||||
|
private static final BiMap<Integer, Integer> SLOT_MAPPING;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Map<EquipmentSlot, ToIntFunction<PlayerInventory>> equipmentSlotMapping = new EnumMap<>(EquipmentSlot.class);
|
||||||
|
equipmentSlotMapping.put(EquipmentSlot.MAINHAND, i -> i.getHolder().selectedSlot);
|
||||||
|
equipmentSlotMapping.put(EquipmentSlot.OFFHAND, i -> 40);
|
||||||
|
equipmentSlotMapping.put(EquipmentSlot.BOOTS, i -> 36);
|
||||||
|
equipmentSlotMapping.put(EquipmentSlot.LEGGINGS, i -> 37);
|
||||||
|
equipmentSlotMapping.put(EquipmentSlot.CHESTPLATE, i -> 38);
|
||||||
|
equipmentSlotMapping.put(EquipmentSlot.HELMET, i -> 39);
|
||||||
|
EQUIPMENT_SLOT_MAPPING = Collections.unmodifiableMap(equipmentSlotMapping);
|
||||||
|
|
||||||
|
BiMap<Integer, Integer> slotMapping = HashBiMap.create(41);
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
slotMapping.put(i, i + 36);
|
||||||
|
}
|
||||||
|
for (int i = 9; i < 36; i++) {
|
||||||
|
slotMapping.put(i, i);
|
||||||
|
}
|
||||||
|
for (int i = 36; i < 40; i++) {
|
||||||
|
slotMapping.put(i, i - 31);
|
||||||
|
}
|
||||||
|
slotMapping.put(40, 45);
|
||||||
|
SLOT_MAPPING = ImmutableBiMap.copyOf(slotMapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Player player;
|
||||||
|
|
||||||
|
public PlayerInventory(Player player) {
|
||||||
|
super(InventoryType.PLAYER.getDefaultSize(), player, InventoryType.PLAYER, i -> SLOT_MAPPING.getOrDefault(i, i), i -> SLOT_MAPPING.inverse().getOrDefault(i, i));
|
||||||
|
this.player = player;
|
||||||
|
this.viewers.put(player, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Player getHolder() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItem(EquipmentSlot slot, ItemStack item) {
|
||||||
|
setItem(EQUIPMENT_SLOT_MAPPING.get(slot).applyAsInt(this), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItem(EquipmentSlot slot) {
|
||||||
|
return getItem(EQUIPMENT_SLOT_MAPPING.get(slot).applyAsInt(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemInMainHand() {
|
||||||
|
return getItem(EquipmentSlot.MAINHAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItemInMainHand(ItemStack item) {
|
||||||
|
setItem(EquipmentSlot.MAINHAND, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemInOffHand() {
|
||||||
|
return getItem(EquipmentSlot.OFFHAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItemInOffHand(ItemStack item) {
|
||||||
|
setItem(EquipmentSlot.OFFHAND, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getHelmet() {
|
||||||
|
return getItem(EquipmentSlot.HELMET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHelmet(ItemStack helmet) {
|
||||||
|
setItem(EquipmentSlot.HELMET, helmet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getChestplate() {
|
||||||
|
return getItem(EquipmentSlot.CHESTPLATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChestplate(ItemStack chestplate) {
|
||||||
|
setItem(EquipmentSlot.CHESTPLATE, chestplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getLeggings() {
|
||||||
|
return getItem(EquipmentSlot.LEGGINGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLeggings(ItemStack leggings) {
|
||||||
|
setItem(EquipmentSlot.LEGGINGS, leggings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getBoots() {
|
||||||
|
return getItem(EquipmentSlot.BOOTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBoots(ItemStack boots) {
|
||||||
|
setItem(EquipmentSlot.BOOTS, boots);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack[] getArmorContents() {
|
||||||
|
return Arrays.stream(EquipmentSlot.values()).filter(EquipmentSlot::isArmorSlot).map(this::getItem).toArray(ItemStack[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setArmorContents(ItemStack[] items) {
|
||||||
|
int i = 0;
|
||||||
|
for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) {
|
||||||
|
if (equipmentSlot.isArmorSlot()) {
|
||||||
|
if (i < items.length) {
|
||||||
|
setItem(equipmentSlot, items[i]);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Location getLocation() {
|
||||||
|
return player.getLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
package com.loohp.limbo.registry;
|
package com.loohp.limbo.registry;
|
||||||
|
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import com.google.common.collect.HashBiMap;
|
||||||
import com.loohp.limbo.Limbo;
|
import com.loohp.limbo.Limbo;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
@ -41,6 +43,8 @@ import java.util.Map.Entry;
|
||||||
public class Registry {
|
public class Registry {
|
||||||
|
|
||||||
public static final BlockEntityRegistry BLOCK_ENTITY_TYPE;
|
public static final BlockEntityRegistry BLOCK_ENTITY_TYPE;
|
||||||
|
public static final ItemRegistry ITEM_REGISTRY;
|
||||||
|
public static final MenuRegistry MENU_REGISTRY;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String name = "registries.json";
|
String name = "registries.json";
|
||||||
|
|
@ -54,19 +58,40 @@ public class Registry {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Key, Integer> blockEntityType = new HashMap<>();
|
Map<Key, Integer> blockEntityType = new HashMap<>();
|
||||||
|
Key defaultItemKey = null;
|
||||||
|
BiMap<Key, Integer> itemIds = HashBiMap.create();
|
||||||
|
Map<Key, Integer> menuIds = new HashMap<>();
|
||||||
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
|
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
|
||||||
JSONObject json = (JSONObject) new JSONParser().parse(reader);
|
JSONObject json = (JSONObject) new JSONParser().parse(reader);
|
||||||
|
|
||||||
JSONObject blockEntityJson = (JSONObject) ((JSONObject) json.get("minecraft:block_entity_type")).get("entries");
|
JSONObject blockEntityJson = (JSONObject) ((JSONObject) json.get("minecraft:block_entity_type")).get("entries");
|
||||||
for (Object obj : blockEntityJson.keySet()) {
|
for (Object obj : blockEntityJson.keySet()) {
|
||||||
String key = obj.toString();
|
String key = obj.toString();
|
||||||
int id = (int) (long) ((JSONObject) blockEntityJson.get(key)).get("protocol_id");
|
int id = ((Number) ((JSONObject) blockEntityJson.get(key)).get("protocol_id")).intValue();
|
||||||
blockEntityType.put(Key.key(key), id);
|
blockEntityType.put(Key.key(key), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSONObject itemJson = (JSONObject) json.get("minecraft:item");
|
||||||
|
defaultItemKey = Key.key((String) itemJson.get("default"));
|
||||||
|
JSONObject itemEntriesJson = (JSONObject) itemJson.get("entries");
|
||||||
|
for (Object obj : itemEntriesJson.keySet()) {
|
||||||
|
String key = obj.toString();
|
||||||
|
int id = ((Number) ((JSONObject) itemEntriesJson.get(key)).get("protocol_id")).intValue();
|
||||||
|
itemIds.put(Key.key(key), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject menuEntriesJson = (JSONObject) ((JSONObject) json.get("minecraft:menu")).get("entries");
|
||||||
|
for (Object obj : menuEntriesJson.keySet()) {
|
||||||
|
String key = obj.toString();
|
||||||
|
int id = ((Number) ((JSONObject) menuEntriesJson.get(key)).get("protocol_id")).intValue();
|
||||||
|
menuIds.put(Key.key(key), id);
|
||||||
|
}
|
||||||
} catch (IOException | ParseException e) {
|
} catch (IOException | ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
BLOCK_ENTITY_TYPE = new BlockEntityRegistry(blockEntityType);
|
BLOCK_ENTITY_TYPE = new BlockEntityRegistry(blockEntityType);
|
||||||
|
ITEM_REGISTRY = new ItemRegistry(defaultItemKey, itemIds);
|
||||||
|
MENU_REGISTRY = new MenuRegistry(menuIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BlockEntityRegistry {
|
public static class BlockEntityRegistry {
|
||||||
|
|
@ -99,4 +124,47 @@ public class Registry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ItemRegistry {
|
||||||
|
|
||||||
|
private final Key defaultKey;
|
||||||
|
private final BiMap<Key, Integer> itemIds;
|
||||||
|
|
||||||
|
private ItemRegistry(Key defaultKey, BiMap<Key, Integer> itemIds) {
|
||||||
|
this.defaultKey = defaultKey;
|
||||||
|
this.itemIds = itemIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key getDefaultKey() {
|
||||||
|
return defaultKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId(Key key) {
|
||||||
|
Integer id = itemIds.get(key);
|
||||||
|
if (id != null) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
if (defaultKey == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return itemIds.getOrDefault(defaultKey, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key fromId(int id) {
|
||||||
|
return itemIds.inverse().getOrDefault(id, defaultKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MenuRegistry {
|
||||||
|
|
||||||
|
private final Map<Key, Integer> menuIds;
|
||||||
|
|
||||||
|
private MenuRegistry(Map<Key, Integer> menuIds) {
|
||||||
|
this.menuIds = menuIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId(Key key) {
|
||||||
|
return menuIds.getOrDefault(key, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,14 @@
|
||||||
|
|
||||||
package com.loohp.limbo.utils;
|
package com.loohp.limbo.utils;
|
||||||
|
|
||||||
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
|
import com.loohp.limbo.location.BlockFace;
|
||||||
|
import com.loohp.limbo.location.MovingObjectPositionBlock;
|
||||||
|
import com.loohp.limbo.location.Vector;
|
||||||
|
import com.loohp.limbo.registry.Registry;
|
||||||
import com.loohp.limbo.world.BlockPosition;
|
import com.loohp.limbo.world.BlockPosition;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.querz.nbt.io.NBTInputStream;
|
||||||
import net.querz.nbt.io.NBTOutputStream;
|
import net.querz.nbt.io.NBTOutputStream;
|
||||||
import net.querz.nbt.tag.CompoundTag;
|
import net.querz.nbt.tag.CompoundTag;
|
||||||
import net.querz.nbt.tag.Tag;
|
import net.querz.nbt.tag.Tag;
|
||||||
|
|
@ -28,6 +35,7 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.PushbackInputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
@ -36,6 +44,52 @@ import java.util.UUID;
|
||||||
|
|
||||||
public class DataTypeIO {
|
public class DataTypeIO {
|
||||||
|
|
||||||
|
public static void writeItemStack(DataOutputStream out, ItemStack itemstack) throws IOException {
|
||||||
|
if (itemstack == null || itemstack.isSimilar(ItemStack.AIR) || itemstack.amount() == 0) {
|
||||||
|
out.writeBoolean(false);
|
||||||
|
} else {
|
||||||
|
out.writeBoolean(true);
|
||||||
|
writeVarInt(out, Registry.ITEM_REGISTRY.getId(itemstack.type()));
|
||||||
|
out.writeByte(itemstack.amount());
|
||||||
|
writeCompoundTag(out, itemstack.nbt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemStack readItemStack(DataInputStream in) throws IOException {
|
||||||
|
if (!in.readBoolean()) {
|
||||||
|
return ItemStack.AIR;
|
||||||
|
} else {
|
||||||
|
Key key = Registry.ITEM_REGISTRY.fromId(readVarInt(in));
|
||||||
|
byte amount = in.readByte();
|
||||||
|
CompoundTag nbt = readCompoundTag(in);
|
||||||
|
return new ItemStack(key, amount, nbt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeBlockHitResult(DataOutputStream out, MovingObjectPositionBlock movingobjectpositionblock) throws IOException {
|
||||||
|
BlockPosition blockposition = movingobjectpositionblock.getBlockPos();
|
||||||
|
|
||||||
|
writeBlockPosition(out, blockposition);
|
||||||
|
writeVarInt(out, movingobjectpositionblock.getDirection().ordinal());
|
||||||
|
Vector vector = movingobjectpositionblock.getLocation();
|
||||||
|
|
||||||
|
out.writeFloat((float) (vector.getX() - (double) blockposition.getX()));
|
||||||
|
out.writeFloat((float) (vector.getY() - (double) blockposition.getY()));
|
||||||
|
out.writeFloat((float) (vector.getZ() - (double) blockposition.getZ()));
|
||||||
|
out.writeBoolean(movingobjectpositionblock.isInside());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MovingObjectPositionBlock readBlockHitResult(DataInputStream in) throws IOException {
|
||||||
|
BlockPosition blockposition = readBlockPosition(in);
|
||||||
|
BlockFace direction = BlockFace.values()[readVarInt(in)];
|
||||||
|
float f = in.readFloat();
|
||||||
|
float f1 = in.readFloat();
|
||||||
|
float f2 = in.readFloat();
|
||||||
|
boolean flag = in.readBoolean();
|
||||||
|
|
||||||
|
return new MovingObjectPositionBlock(new Vector((double) blockposition.getX() + (double) f, (double) blockposition.getY() + (double) f1, (double) blockposition.getZ() + (double) f2), direction, blockposition, flag);
|
||||||
|
}
|
||||||
|
|
||||||
public static <E extends Enum<E>> void writeEnumSet(DataOutputStream out, EnumSet<E> enumset, Class<E> oclass) throws IOException {
|
public static <E extends Enum<E>> void writeEnumSet(DataOutputStream out, EnumSet<E> enumset, Class<E> oclass) throws IOException {
|
||||||
E[] ae = oclass.getEnumConstants();
|
E[] ae = oclass.getEnumConstants();
|
||||||
BitSet bitset = new BitSet(ae.length);
|
BitSet bitset = new BitSet(ae.length);
|
||||||
|
|
@ -81,6 +135,14 @@ public class DataTypeIO {
|
||||||
out.writeLong(((position.getX() & 0x3FFFFFF) << 38) | ((position.getZ() & 0x3FFFFFF) << 12) | (position.getY() & 0xFFF));
|
out.writeLong(((position.getX() & 0x3FFFFFF) << 38) | ((position.getZ() & 0x3FFFFFF) << 12) | (position.getY() & 0xFFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BlockPosition readBlockPosition(DataInputStream in) throws IOException {
|
||||||
|
long value = in.readLong();
|
||||||
|
int x = (int) (value >> 38);
|
||||||
|
int y = (int) (value << 52 >> 52);
|
||||||
|
int z = (int) (value << 26 >> 38);
|
||||||
|
return new BlockPosition(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
public static void writeUUID(DataOutputStream out, UUID uuid) throws IOException {
|
public static void writeUUID(DataOutputStream out, UUID uuid) throws IOException {
|
||||||
out.writeLong(uuid.getMostSignificantBits());
|
out.writeLong(uuid.getMostSignificantBits());
|
||||||
out.writeLong(uuid.getLeastSignificantBits());
|
out.writeLong(uuid.getLeastSignificantBits());
|
||||||
|
|
@ -91,13 +153,21 @@ public class DataTypeIO {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeCompoundTag(DataOutputStream out, CompoundTag tag) throws IOException {
|
public static void writeCompoundTag(DataOutputStream out, CompoundTag tag) throws IOException {
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
if (tag == null) {
|
||||||
|
out.writeByte(0);
|
||||||
|
} else {
|
||||||
|
new NBTOutputStream(out).writeTag(tag, Tag.DEFAULT_MAX_DEPTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
public static CompoundTag readCompoundTag(DataInputStream in) throws IOException {
|
||||||
new NBTOutputStream(output).writeTag(tag, Tag.DEFAULT_MAX_DEPTH);
|
byte b = in.readByte();
|
||||||
|
if (b == 0) {
|
||||||
byte[] b = buffer.toByteArray();
|
return null;
|
||||||
out.write(b);
|
}
|
||||||
|
PushbackInputStream buffered = new PushbackInputStream(in);
|
||||||
|
buffered.unread(b);
|
||||||
|
return (CompoundTag) new NBTInputStream(buffered).readTag(Tag.DEFAULT_MAX_DEPTH).getTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String readString(DataInputStream in, Charset charset) throws IOException {
|
public static String readString(DataInputStream in, Charset charset) throws IOException {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import net.querz.nbt.tag.Tag;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class BlockState {
|
public class BlockState {
|
||||||
|
|
||||||
|
|
@ -79,33 +80,15 @@ public class BlockState {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public boolean equals(Object o) {
|
||||||
final int prime = 31;
|
if (this == o) return true;
|
||||||
int result = 1;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
result = prime * result + ((tag == null) ? 0 : tag.hashCode());
|
BlockState that = (BlockState) o;
|
||||||
return result;
|
return Objects.equals(tag, that.tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public int hashCode() {
|
||||||
if (this == obj) {
|
return Objects.hash(tag);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (getClass() != obj.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
BlockState other = (BlockState) obj;
|
|
||||||
if (tag == null) {
|
|
||||||
if (other.tag != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (!tag.equals(other.tag)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -91,7 +92,7 @@ public class World {
|
||||||
chunk.cleanupPalettesAndBlockStates();
|
chunk.cleanupPalettesAndBlockStates();
|
||||||
chunk.setHeightMaps(HEIGHT_MAP.clone());
|
chunk.setHeightMaps(HEIGHT_MAP.clone());
|
||||||
chunk.setBiomes(new int[256]);
|
chunk.setBiomes(new int[256]);
|
||||||
chunk.setTileEntities(new ListTag<CompoundTag>(CompoundTag.class));
|
chunk.setTileEntities(new ListTag<>(CompoundTag.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -125,6 +126,10 @@ public class World {
|
||||||
chunk.setBlockStateAt(x, y, z, block, false);
|
chunk.setBlockStateAt(x, y, z, block, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockState getBlock(BlockPosition blockPosition) {
|
||||||
|
return getBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
public BlockState getBlock(int x, int y, int z) {
|
public BlockState getBlock(int x, int y, int z) {
|
||||||
Chunk chunk = this.chunks[(x >> 4)][(z >> 4)];
|
Chunk chunk = this.chunks[(x >> 4)][(z >> 4)];
|
||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
|
|
@ -140,6 +145,10 @@ public class World {
|
||||||
return new BlockState(tag);
|
return new BlockState(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBlock(BlockPosition blockPosition, BlockState state) {
|
||||||
|
setBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), state);
|
||||||
|
}
|
||||||
|
|
||||||
public void setBlock(int x, int y, int z, BlockState state) {
|
public void setBlock(int x, int y, int z, BlockState state) {
|
||||||
Chunk chunk = this.chunks[(x >> 4)][(z >> 4)];
|
Chunk chunk = this.chunks[(x >> 4)][(z >> 4)];
|
||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
|
|
@ -300,40 +309,15 @@ public class World {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public boolean equals(Object o) {
|
||||||
final int prime = 31;
|
if (this == o) return true;
|
||||||
int result = 1;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
result = prime * result + Arrays.deepHashCode(chunks);
|
World world = (World) o;
|
||||||
result = prime * result + ((environment == null) ? 0 : environment.hashCode());
|
return Objects.equals(name, world.name);
|
||||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public int hashCode() {
|
||||||
if (this == obj) {
|
return Objects.hash(name);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (getClass() != obj.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
World other = (World) obj;
|
|
||||||
if (!Arrays.deepEquals(chunks, other.chunks)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (environment != other.environment) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (name == null) {
|
|
||||||
if (other.name != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (!name.equals(other.name)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,12 @@
|
||||||
"0x0C": "PacketPlayInPluginMessaging",
|
"0x0C": "PacketPlayInPluginMessaging",
|
||||||
"0x08": "PacketPlayInTabComplete",
|
"0x08": "PacketPlayInTabComplete",
|
||||||
"0x28": "PacketPlayInHeldItemChange",
|
"0x28": "PacketPlayInHeldItemChange",
|
||||||
"0x24": "PacketPlayInResourcePackStatus"
|
"0x24": "PacketPlayInResourcePackStatus",
|
||||||
|
"0x32": "PacketPlayInBlockPlace",
|
||||||
|
"0x31": "PacketPlayInUseItem",
|
||||||
|
"0x2B": "PacketPlayInSetCreativeSlot",
|
||||||
|
"0x0A": "PacketPlayInWindowClick",
|
||||||
|
"0x0B": "PacketPlayInCloseWindow"
|
||||||
},
|
},
|
||||||
"PlayOut": {
|
"PlayOut": {
|
||||||
"PacketPlayOutLogin": "0x24",
|
"PacketPlayOutLogin": "0x24",
|
||||||
|
|
@ -53,7 +58,12 @@
|
||||||
"ClientboundClearTitlesPacket": "0x0C",
|
"ClientboundClearTitlesPacket": "0x0C",
|
||||||
"PacketPlayOutBoss": "0x0A",
|
"PacketPlayOutBoss": "0x0A",
|
||||||
"PacketPlayOutNamedSoundEffect": "0x5E",
|
"PacketPlayOutNamedSoundEffect": "0x5E",
|
||||||
"PacketPlayOutStopSound": "0x5F"
|
"PacketPlayOutStopSound": "0x5F",
|
||||||
|
"PacketPlayOutWindowItems": "0x10",
|
||||||
|
"PacketPlayOutSetSlot": "0x12",
|
||||||
|
"PacketPlayOutOpenWindow": "0x2C",
|
||||||
|
"PacketPlayOutCloseWindow": "0x0F",
|
||||||
|
"PacketPlayOutWindowData": "0x11"
|
||||||
},
|
},
|
||||||
"StatusIn": {
|
"StatusIn": {
|
||||||
"0x01": "PacketStatusInPing",
|
"0x01": "PacketStatusInPing",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue