143 lines
6.5 KiB
Java
143 lines
6.5 KiB
Java
package wtf.hak.survivalfabric.features.sharedenderchest;
|
|
|
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
|
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
|
import net.minecraft.block.Blocks;
|
|
import net.minecraft.block.EnderChestBlock;
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
import net.minecraft.inventory.Inventories;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.nbt.NbtCompound;
|
|
import net.minecraft.nbt.NbtIo;
|
|
import net.minecraft.nbt.NbtSizeTracker;
|
|
import net.minecraft.screen.GenericContainerScreenHandler;
|
|
import net.minecraft.screen.SimpleNamedScreenHandlerFactory;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.sound.SoundCategory;
|
|
import net.minecraft.sound.SoundEvents;
|
|
import net.minecraft.text.Text;
|
|
import net.minecraft.util.ActionResult;
|
|
import net.minecraft.util.WorldSavePath;
|
|
import net.minecraft.util.collection.DefaultedList;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.world.World;
|
|
|
|
import java.io.*;
|
|
|
|
import static wtf.hak.survivalfabric.SurvivalFabric.LOGGER;
|
|
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
|
|
|
|
public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, ServerLifecycleEvents.ServerStarted, ServerTickEvents.EndTick {
|
|
|
|
private static SharedInventory sharedInventory;
|
|
|
|
private long ticksUntilSave = -20;
|
|
|
|
public static void saveInventory(MinecraftServer server) {
|
|
File inventoryFile = getFile(server);
|
|
NbtCompound nbt = new NbtCompound();
|
|
DefaultedList<ItemStack> inventoryItemStacks = DefaultedList.ofSize(getConfig().sharedEnderChestRows * 9, ItemStack.EMPTY);
|
|
Inventories.writeNbt(nbt, sharedInventory.getList(inventoryItemStacks), server.getRegistryManager());
|
|
try (FileOutputStream inventoryFileOutputStream = new FileOutputStream(inventoryFile);
|
|
DataOutputStream inventoryFileDataOutput = new DataOutputStream(inventoryFileOutputStream)) {
|
|
inventoryFile.createNewFile();
|
|
NbtIo.writeCompressed(nbt, inventoryFileDataOutput);
|
|
} catch (Exception e) {
|
|
LOGGER.error("Error while saving Shared Ender Chest: " + e);
|
|
}
|
|
}
|
|
|
|
public static void openSharedEnderChest(PlayerEntity player, World world, BlockPos pos) {
|
|
fakeEnderChestOpen(world, pos, true);
|
|
sharedInventory.openedEnderChests.put(player, pos);
|
|
player.openHandledScreen(new SimpleNamedScreenHandlerFactory((int_1, playerInventory, playerEntity) ->
|
|
new GenericContainerScreenHandler(getConfig().screenHandlerType(), int_1, playerInventory, sharedInventory, getConfig().sharedEnderChestRows), Text.of(getConfig().sharedEnderChestName)));
|
|
}
|
|
|
|
public static void playEnderChestOpenSound(World world, BlockPos pos) {
|
|
world.playSound(null, pos, SoundEvents.BLOCK_ENDER_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F);
|
|
}
|
|
|
|
public static void playEnderChestCloseSound(World world, BlockPos pos) {
|
|
world.playSound(null, pos, SoundEvents.BLOCK_ENDER_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F);
|
|
}
|
|
|
|
public static void fakeEnderChestOpen(World world, BlockPos pos, boolean open) {
|
|
if (!(world.getBlockState(pos).getBlock() instanceof EnderChestBlock)) {
|
|
return;
|
|
}
|
|
|
|
if (open)
|
|
playEnderChestOpenSound(world, pos);
|
|
else
|
|
playEnderChestCloseSound(world, pos);
|
|
world.addSyncedBlockEvent(pos, Blocks.ENDER_CHEST, 1, open ? 1 : 0);
|
|
}
|
|
|
|
private static File getFile(MinecraftServer server) {
|
|
return server.getSavePath(WorldSavePath.ROOT).resolve("sharedenderchest.sav").toFile();
|
|
}
|
|
|
|
public void onServerStarted(MinecraftServer server) {
|
|
File inventoryFile = getFile(server);
|
|
if (inventoryFile.exists()) {
|
|
try (FileInputStream inventoryFileInputStream = new FileInputStream(inventoryFile);
|
|
DataInputStream inventoryFileDataInput = new DataInputStream(inventoryFileInputStream)) {
|
|
NbtCompound nbt = NbtIo.readCompressed(inventoryFileDataInput, NbtSizeTracker.ofUnlimitedBytes());
|
|
DefaultedList<ItemStack> inventoryItemStacks = DefaultedList.ofSize(getConfig().sharedEnderChestRows * 9, ItemStack.EMPTY);
|
|
Inventories.readNbt(nbt, inventoryItemStacks, server.getRegistryManager());
|
|
sharedInventory = new SharedInventory(inventoryItemStacks);
|
|
} catch (Exception e) {
|
|
LOGGER.error("Error while loading Shared Ender Chest: " + e);
|
|
sharedInventory = new SharedInventory(getConfig().sharedEnderChestRows);
|
|
}
|
|
} else {
|
|
sharedInventory = new SharedInventory(getConfig().sharedEnderChestRows);
|
|
}
|
|
}
|
|
|
|
public void onServerStopping(MinecraftServer server) {
|
|
saveInventory(server);
|
|
}
|
|
|
|
public void onEndTick(MinecraftServer server) {
|
|
if (ticksUntilSave != -20 && --ticksUntilSave <= 0L) {
|
|
saveInventory(server);
|
|
ticksUntilSave = 20L;
|
|
}
|
|
}
|
|
|
|
public void onInitialize() {
|
|
ticksUntilSave = 20L;
|
|
|
|
UseBlockCallback listenerUseBlock = (player, world, hand, hitResult) -> {
|
|
|
|
if (world.getBlockState(hitResult.getBlockPos()).getBlock() instanceof EnderChestBlock) {
|
|
if (!player.isSpectator()) {
|
|
if (!getConfig().sharedEnderChestLimitedAccess) {
|
|
if (world.isClient()) return ActionResult.SUCCESS;
|
|
openSharedEnderChest(player, world, hitResult.getBlockPos());
|
|
return ActionResult.SUCCESS;
|
|
} else {
|
|
for (String name : getConfig().sharedEnderChestNames) {
|
|
if (name.toLowerCase().strip().equalsIgnoreCase(player.getNameForScoreboard().toLowerCase())) {
|
|
if (world.isClient()) return ActionResult.SUCCESS;
|
|
openSharedEnderChest(player, world, hitResult.getBlockPos());
|
|
return ActionResult.SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ActionResult.PASS;
|
|
};
|
|
|
|
UseBlockCallback.EVENT.register(listenerUseBlock);
|
|
ServerLifecycleEvents.SERVER_STARTED.register(this);
|
|
ServerLifecycleEvents.SERVER_STOPPING.register(this);
|
|
ServerTickEvents.END_SERVER_TICK.register(this);
|
|
|
|
}
|
|
|
|
} |