Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5e7ef98
commit 5060e71
Showing
12 changed files
with
1,186 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
plugins { | ||
id("io.papermc.paperweight.userdev") version "1.3.8" | ||
} | ||
|
||
java { | ||
toolchain { | ||
languageVersion.set(JavaLanguageVersion.of(17)) | ||
} | ||
} | ||
|
||
group 'NMS:v1_20_2' | ||
|
||
dependencies { | ||
paperweightDevelopmentBundle("io.papermc.paper:dev-bundle:1.20.2-R0.1-SNAPSHOT") | ||
compileOnly project(":API") | ||
compileOnly rootProject | ||
} | ||
|
||
shadowJar { | ||
archiveFileName = "${project.name}-exclude.jar" | ||
} | ||
|
||
assemble { | ||
dependsOn(reobfJar) | ||
} | ||
|
||
tasks { | ||
reobfJar { | ||
File outputFile = new File(rootProject.archiveFolder, "reobf/${project.name}.jar") | ||
outputJar.set(layout.buildDirectory.file(outputFile.getPath())) | ||
} | ||
} | ||
|
||
if (project.hasProperty('nms.compile_v1_20') && !Boolean.valueOf(project.findProperty("nms.compile_v1_20").toString())) { | ||
project.tasks.all { task -> task.enabled = false } | ||
} |
212 changes: 212 additions & 0 deletions
212
NMS/v1_20_2/src/main/java/com/bgsoftware/wildchests/nms/v1_20_2/NMSAdapter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
package com.bgsoftware.wildchests.nms.v1_20_2; | ||
|
||
import com.bgsoftware.wildchests.api.objects.ChestType; | ||
import com.bgsoftware.wildchests.objects.inventory.InventoryHolder; | ||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.nbt.CompoundTag; | ||
import net.minecraft.nbt.ListTag; | ||
import net.minecraft.nbt.NbtIo; | ||
import net.minecraft.server.level.ServerLevel; | ||
import net.minecraft.world.entity.player.Player; | ||
import net.minecraft.world.item.ItemStack; | ||
import net.minecraft.world.level.block.entity.BlockEntity; | ||
import net.minecraft.world.level.block.entity.ChestBlockEntity; | ||
import org.bukkit.Location; | ||
import org.bukkit.Material; | ||
import org.bukkit.World; | ||
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; | ||
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftHumanEntity; | ||
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; | ||
import org.bukkit.entity.HumanEntity; | ||
import org.bukkit.inventory.Inventory; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.DataInputStream; | ||
import java.io.DataOutput; | ||
import java.io.DataOutputStream; | ||
import java.math.BigInteger; | ||
import java.util.Base64; | ||
|
||
public final class NMSAdapter implements com.bgsoftware.wildchests.nms.NMSAdapter { | ||
|
||
@Override | ||
public String serialize(org.bukkit.inventory.ItemStack bukkitItem) { | ||
ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); | ||
|
||
if (itemStack.isEmpty()) | ||
return ""; | ||
|
||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | ||
DataOutput dataOutput = new DataOutputStream(outputStream); | ||
|
||
CompoundTag compoundTag = new CompoundTag(); | ||
|
||
itemStack.setCount(1); | ||
itemStack.save(compoundTag); | ||
|
||
try { | ||
NbtIo.write(compoundTag, dataOutput); | ||
} catch (Exception ex) { | ||
return null; | ||
} | ||
|
||
return "*" + new String(Base64.getEncoder().encode(outputStream.toByteArray())); | ||
} | ||
|
||
@Override | ||
public String serialize(Inventory[] inventories) { | ||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | ||
DataOutput dataOutput = new DataOutputStream(outputStream); | ||
|
||
CompoundTag compoundTag = new CompoundTag(); | ||
compoundTag.putInt("Length", inventories.length); | ||
|
||
for (int slot = 0; slot < inventories.length; slot++) { | ||
CompoundTag inventoryCompound = new CompoundTag(); | ||
serialize(inventories[slot], inventoryCompound); | ||
compoundTag.put(slot + "", inventoryCompound); | ||
} | ||
|
||
try { | ||
NbtIo.write(compoundTag, dataOutput); | ||
} catch (Exception ex) { | ||
return null; | ||
} | ||
|
||
return "*" + new String(Base64.getEncoder().encode(outputStream.toByteArray())); | ||
} | ||
|
||
@Override | ||
public InventoryHolder[] deserialze(String serialized) { | ||
byte[] buff; | ||
|
||
if (serialized.toCharArray()[0] == '*') { | ||
buff = Base64.getDecoder().decode(serialized.substring(1)); | ||
} else { | ||
buff = new BigInteger(serialized, 32).toByteArray(); | ||
} | ||
|
||
ByteArrayInputStream inputStream = new ByteArrayInputStream(buff); | ||
InventoryHolder[] inventories = new InventoryHolder[0]; | ||
|
||
try { | ||
CompoundTag compoundTag = NbtIo.read(new DataInputStream(inputStream)); | ||
int length = compoundTag.getInt("Length"); | ||
inventories = new InventoryHolder[length]; | ||
|
||
for (int i = 0; i < length; i++) { | ||
if (compoundTag.contains(i + "")) { | ||
CompoundTag itemCompound = compoundTag.getCompound(i + ""); | ||
inventories[i] = deserialize(itemCompound); | ||
} | ||
} | ||
|
||
} catch (Exception ex) { | ||
ex.printStackTrace(); | ||
} | ||
|
||
return inventories; | ||
} | ||
|
||
@Override | ||
public org.bukkit.inventory.ItemStack deserialzeItem(String serialized) { | ||
if (serialized.isEmpty()) | ||
return new org.bukkit.inventory.ItemStack(Material.AIR); | ||
|
||
byte[] buff; | ||
|
||
if (serialized.toCharArray()[0] == '*') { | ||
buff = Base64.getDecoder().decode(serialized.substring(1)); | ||
} else { | ||
buff = new BigInteger(serialized, 32).toByteArray(); | ||
} | ||
|
||
ByteArrayInputStream inputStream = new ByteArrayInputStream(buff); | ||
|
||
try { | ||
CompoundTag compoundTag = NbtIo.read(new DataInputStream(inputStream)); | ||
ItemStack itemStack = ItemStack.of(compoundTag); | ||
return CraftItemStack.asBukkitCopy(itemStack); | ||
} catch (Exception ex) { | ||
return null; | ||
} | ||
} | ||
|
||
@Override | ||
public void playChestAction(Location location, boolean open) { | ||
World bukkitWorld = location.getWorld(); | ||
|
||
if (bukkitWorld == null) | ||
return; | ||
|
||
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); | ||
BlockPos blockPos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); | ||
BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos); | ||
if (blockEntity instanceof ChestBlockEntity) | ||
serverLevel.blockEvent(blockPos, blockEntity.getBlockState().getBlock(), 1, open ? 1 : 0); | ||
} | ||
|
||
@Override | ||
public org.bukkit.inventory.ItemStack setChestType(org.bukkit.inventory.ItemStack itemStack, ChestType chestType) { | ||
return setItemTag(itemStack, "chest-type", chestType.name()); | ||
} | ||
|
||
@Override | ||
public org.bukkit.inventory.ItemStack setChestName(org.bukkit.inventory.ItemStack itemStack, String chestName) { | ||
return setItemTag(itemStack, "chest-name", chestName); | ||
} | ||
|
||
@Override | ||
public String getChestName(org.bukkit.inventory.ItemStack bukkitItem) { | ||
ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); | ||
CompoundTag compoundTag = itemStack.getTag(); | ||
return compoundTag == null || !compoundTag.contains("chest-name") ? null : | ||
compoundTag.getString("chest-name"); | ||
} | ||
|
||
@Override | ||
public void dropItemAsPlayer(HumanEntity humanEntity, org.bukkit.inventory.ItemStack bukkitItem) { | ||
Player player = ((CraftHumanEntity) humanEntity).getHandle(); | ||
ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); | ||
player.drop(itemStack, false); | ||
} | ||
|
||
private org.bukkit.inventory.ItemStack setItemTag(org.bukkit.inventory.ItemStack bukkitItem, String key, String value) { | ||
ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); | ||
CompoundTag compoundTag = itemStack.getOrCreateTag(); | ||
compoundTag.putString(key, value); | ||
return CraftItemStack.asCraftMirror(itemStack); | ||
} | ||
|
||
private static void serialize(Inventory inventory, CompoundTag compoundTag) { | ||
ListTag itemsList = new ListTag(); | ||
org.bukkit.inventory.ItemStack[] items = inventory.getContents(); | ||
|
||
for (int i = 0; i < items.length; ++i) { | ||
if (items[i] != null) { | ||
ItemStack itemStack = CraftItemStack.asNMSCopy(items[i]); | ||
CompoundTag itemTag = new CompoundTag(); | ||
itemTag.putByte("Slot", (byte) i); | ||
itemStack.save(itemTag); | ||
itemsList.add(itemTag); | ||
} | ||
} | ||
|
||
compoundTag.putInt("Size", inventory.getSize()); | ||
compoundTag.put("Items", itemsList); | ||
} | ||
|
||
private static InventoryHolder deserialize(CompoundTag compoundTag) { | ||
InventoryHolder inventory = new InventoryHolder(compoundTag.getInt("Size"), "Chest"); | ||
ListTag itemsList = compoundTag.getList("Items", 10); | ||
|
||
for (int i = 0; i < itemsList.size(); i++) { | ||
CompoundTag itemTag = itemsList.getCompound(i); | ||
inventory.setItem(itemTag.getByte("Slot"), CraftItemStack.asBukkitCopy(ItemStack.of(itemTag))); | ||
} | ||
|
||
return inventory; | ||
} | ||
|
||
} |
137 changes: 137 additions & 0 deletions
137
NMS/v1_20_2/src/main/java/com/bgsoftware/wildchests/nms/v1_20_2/NMSInventory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
package com.bgsoftware.wildchests.nms.v1_20_2; | ||
|
||
import com.bgsoftware.common.reflection.ReflectMethod; | ||
import com.bgsoftware.wildchests.api.objects.chests.Chest; | ||
import com.bgsoftware.wildchests.api.objects.chests.StorageChest; | ||
import com.bgsoftware.wildchests.nms.v1_20_2.inventory.CraftWildInventoryImpl; | ||
import com.bgsoftware.wildchests.nms.v1_20_2.inventory.WildChestBlockEntity; | ||
import com.bgsoftware.wildchests.nms.v1_20_2.inventory.WildChestMenu; | ||
import com.bgsoftware.wildchests.nms.v1_20_2.inventory.WildContainer; | ||
import com.bgsoftware.wildchests.nms.v1_20_2.inventory.WildContainerItemImpl; | ||
import com.bgsoftware.wildchests.nms.v1_20_2.inventory.WildHopperMenu; | ||
import com.bgsoftware.wildchests.objects.chests.WChest; | ||
import com.bgsoftware.wildchests.objects.inventory.CraftWildInventory; | ||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.nbt.ByteTag; | ||
import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; | ||
import net.minecraft.server.level.ServerLevel; | ||
import net.minecraft.server.level.ServerPlayer; | ||
import net.minecraft.world.entity.player.Inventory; | ||
import net.minecraft.world.inventory.AbstractContainerMenu; | ||
import net.minecraft.world.item.ItemStack; | ||
import net.minecraft.world.level.block.entity.BlockEntity; | ||
import net.minecraft.world.level.block.entity.BlockEntityTicker; | ||
import net.minecraft.world.level.block.entity.TickingBlockEntity; | ||
import net.minecraft.world.level.chunk.LevelChunk; | ||
import org.bukkit.Location; | ||
import org.bukkit.Material; | ||
import org.bukkit.World; | ||
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; | ||
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; | ||
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; | ||
import org.bukkit.craftbukkit.v1_20_R2.util.CraftChatMessage; | ||
import org.bukkit.entity.Player; | ||
|
||
public final class NMSInventory implements com.bgsoftware.wildchests.nms.NMSInventory { | ||
|
||
private static final ReflectMethod<TickingBlockEntity> CREATE_TICKING_BLOCK = new ReflectMethod<>( | ||
LevelChunk.class, "a", BlockEntity.class, BlockEntityTicker.class); | ||
|
||
@Override | ||
public void updateTileEntity(Chest chest) { | ||
Location location = chest.getLocation(); | ||
World bukkitWorld = location.getWorld(); | ||
|
||
if (bukkitWorld == null) | ||
throw new IllegalArgumentException("Cannot update tile entity of chests in null world."); | ||
|
||
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); | ||
BlockPos blockPos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); | ||
BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos); | ||
|
||
if (blockEntity instanceof WildChestBlockEntity wildChestBlockEntity) { | ||
((WChest) chest).setTileEntityContainer(wildChestBlockEntity); | ||
} else { | ||
WildChestBlockEntity wildChestBlockEntity = new WildChestBlockEntity(chest, serverLevel, blockPos); | ||
serverLevel.removeBlockEntity(blockPos); | ||
serverLevel.setBlockEntity(wildChestBlockEntity); | ||
LevelChunk levelChunk = serverLevel.getChunkAt(blockPos); | ||
serverLevel.addBlockEntityTicker(CREATE_TICKING_BLOCK.invoke(levelChunk, wildChestBlockEntity, wildChestBlockEntity)); | ||
} | ||
} | ||
|
||
@Override | ||
public void removeTileEntity(Chest chest) { | ||
Location location = chest.getLocation(); | ||
World bukkitWorld = location.getWorld(); | ||
|
||
if (bukkitWorld == null) | ||
throw new IllegalArgumentException("Cannot update tile entity of chests in null world."); | ||
|
||
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); | ||
BlockPos blockPos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); | ||
BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos); | ||
if (blockEntity instanceof WildChestBlockEntity) | ||
serverLevel.removeBlockEntity(blockPos); | ||
} | ||
|
||
@Override | ||
public WildContainerItemImpl createItemStack(org.bukkit.inventory.ItemStack bukkitItem) { | ||
return new WildContainerItemImpl(CraftItemStack.asNMSCopy(bukkitItem)); | ||
} | ||
|
||
@Override | ||
public CraftWildInventory createInventory(Chest chest, int size, String title, int index) { | ||
WildContainer wildContainer = new WildContainer(size, title, chest, index); | ||
|
||
if (chest instanceof StorageChest) | ||
wildContainer.setItemFunction = (slot, itemStack) -> chest.setItem(slot, CraftItemStack.asCraftMirror(itemStack)); | ||
|
||
return new CraftWildInventoryImpl(wildContainer); | ||
} | ||
|
||
@Override | ||
public void openPage(Player player, CraftWildInventory inventory) { | ||
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); | ||
String title = inventory.getTitle(); | ||
|
||
AbstractContainerMenu containerMenu = createMenu(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(), inventory); | ||
containerMenu.setTitle(CraftChatMessage.fromStringOrNull(title)); | ||
|
||
// Cursor item is not updated, so we need to update it manually | ||
org.bukkit.inventory.ItemStack cursorItem = player.getItemOnCursor(); | ||
|
||
ClientboundOpenScreenPacket openScreenPacket = new ClientboundOpenScreenPacket(containerMenu.containerId, | ||
containerMenu.getType(), containerMenu.getTitle()); | ||
|
||
serverPlayer.connection.send(openScreenPacket); | ||
serverPlayer.containerMenu = containerMenu; | ||
serverPlayer.initMenu(containerMenu); | ||
|
||
player.setItemOnCursor(cursorItem); | ||
} | ||
|
||
@Override | ||
public void createDesignItem(CraftWildInventory craftWildInventory, | ||
org.bukkit.inventory.ItemStack itemStack) { | ||
ItemStack designItem = CraftItemStack.asNMSCopy(itemStack == null || itemStack.getType() == Material.AIR ? | ||
new org.bukkit.inventory.ItemStack(Material.BLACK_STAINED_GLASS_PANE) : itemStack.clone()); | ||
|
||
designItem.setCount(1); | ||
designItem.addTagElement("DesignItem", ByteTag.valueOf(true)); | ||
|
||
WildContainer container = ((CraftWildInventoryImpl) craftWildInventory).getInventory(); | ||
container.setItem(0, designItem, false); | ||
container.setItem(1, designItem, false); | ||
container.setItem(3, designItem, false); | ||
container.setItem(4, designItem, false); | ||
} | ||
|
||
public static AbstractContainerMenu createMenu(int id, Inventory playerInventory, | ||
CraftWildInventory craftWildInventory) { | ||
WildContainer container = ((CraftWildInventoryImpl) craftWildInventory).getInventory(); | ||
return container.getContainerSize() == 5 ? WildHopperMenu.of(id, playerInventory, container) : | ||
WildChestMenu.of(id, playerInventory, container); | ||
} | ||
|
||
} |
Oops, something went wrong.