diff --git a/README.md b/README.md index ddb188b..ca4b182 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Glowing Obsidian heals monsters and hurts everything else. It naturally generate ## Chest Boats -Right-Click a Boat with a Chest to place it in the Boat, you can also use an Ender Chest, Trapped Chest, or Shulker Box. Shift-Right-Click the Boat to open the Chest. You can also open the Chest inside the Boat by opening your inventory. +Right-Click a Boat with a Chest to place it in the Boat, you can also use an Ender Chest, Trapped Chest, Barrel, or Shulker Box. Shift-Right-Click the Boat to open the Chest. You can also open the Chest inside the Boat by opening your inventory. ## Difficulty Stages Each player has a "personal" stage of an area, the highest online player's difficulty stage in an area will be the "effective" difficulty stage of that area. diff --git a/src/main/java/com/thebrokenrail/twine/Twine.java b/src/main/java/com/thebrokenrail/twine/Twine.java index 30c48e1..77f29fc 100644 --- a/src/main/java/com/thebrokenrail/twine/Twine.java +++ b/src/main/java/com/thebrokenrail/twine/Twine.java @@ -1,5 +1,6 @@ package com.thebrokenrail.twine; +import com.thebrokenrail.twine.advancement.BarrelBoatCriterion; import com.thebrokenrail.twine.advancement.ChestBoatCriterion; import com.thebrokenrail.twine.advancement.EnderChestBoatCriterion; import com.thebrokenrail.twine.advancement.ShulkerBoxBoatCriterion; @@ -8,7 +9,7 @@ import com.thebrokenrail.twine.block.GlowingObsidianBlock; import com.thebrokenrail.twine.item.BackpackItem; import com.thebrokenrail.twine.item.DivinerItem; import com.thebrokenrail.twine.mixin.CriteriaHook; -import com.thebrokenrail.twine.util.BackpackScreenHandler; +import com.thebrokenrail.twine.util.backpack.BackpackScreenHandler; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; @@ -49,6 +50,7 @@ public class Twine implements ModInitializer { public static ChestBoatCriterion CHEST_BOAT_CRITERION = CriteriaHook.callRegister(new ChestBoatCriterion()); public static EnderChestBoatCriterion ENDER_CHEST_BOAT_CRITERION = CriteriaHook.callRegister(new EnderChestBoatCriterion()); public static ShulkerBoxBoatCriterion SHULKER_BOX_BOAT_CRITERION = CriteriaHook.callRegister(new ShulkerBoxBoatCriterion()); + public static BarrelBoatCriterion BARREL_BOAT_CRITERION = CriteriaHook.callRegister(new BarrelBoatCriterion()); @Override public void onInitialize() { diff --git a/src/main/java/com/thebrokenrail/twine/advancement/BarrelBoatCriterion.java b/src/main/java/com/thebrokenrail/twine/advancement/BarrelBoatCriterion.java new file mode 100644 index 0000000..0344b00 --- /dev/null +++ b/src/main/java/com/thebrokenrail/twine/advancement/BarrelBoatCriterion.java @@ -0,0 +1,29 @@ +package com.thebrokenrail.twine.advancement; + +import com.google.gson.JsonObject; +import com.thebrokenrail.twine.Twine; +import net.minecraft.advancement.criterion.AbstractCriterion; +import net.minecraft.advancement.criterion.AbstractCriterionConditions; +import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer; +import net.minecraft.predicate.entity.EntityPredicate; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; + +public class BarrelBoatCriterion extends AbstractCriterion { + private static final Identifier ID = new Identifier(Twine.NAMESPACE, "barrel_boat"); + + public void trigger(ServerPlayerEntity player) { + this.test(player, conditions -> true); + } + + @Override + protected AbstractCriterionConditions conditionsFromJson(JsonObject obj, EntityPredicate.Extended playerPredicate, AdvancementEntityPredicateDeserializer predicateDeserializer) { + return new AbstractCriterionConditions(ID, playerPredicate) { + }; + } + + @Override + public Identifier getId() { + return ID; + } +} diff --git a/src/main/java/com/thebrokenrail/twine/item/BackpackItem.java b/src/main/java/com/thebrokenrail/twine/item/BackpackItem.java index 167d6bc..abdbcb9 100644 --- a/src/main/java/com/thebrokenrail/twine/item/BackpackItem.java +++ b/src/main/java/com/thebrokenrail/twine/item/BackpackItem.java @@ -1,7 +1,7 @@ package com.thebrokenrail.twine.item; import com.thebrokenrail.twine.Twine; -import com.thebrokenrail.twine.util.BackpackScreenHandler; +import com.thebrokenrail.twine.util.backpack.BackpackScreenHandler; import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; diff --git a/src/main/java/com/thebrokenrail/twine/mixin/MixinBoatEntity.java b/src/main/java/com/thebrokenrail/twine/mixin/MixinBoatEntity.java index a37da56..9a06c71 100644 --- a/src/main/java/com/thebrokenrail/twine/mixin/MixinBoatEntity.java +++ b/src/main/java/com/thebrokenrail/twine/mixin/MixinBoatEntity.java @@ -1,8 +1,10 @@ package com.thebrokenrail.twine.mixin; -import com.thebrokenrail.twine.util.BoatChestMode; -import com.thebrokenrail.twine.util.BoatInventory; -import com.thebrokenrail.twine.util.BoatUtil; +import com.thebrokenrail.twine.util.boat.BoatChestMode; +import com.thebrokenrail.twine.util.boat.BoatChestModes; +import com.thebrokenrail.twine.util.boat.BoatUtil; +import com.thebrokenrail.twine.util.boat.inventory.BoatInventory; +import com.thebrokenrail.twine.util.boat.inventory.BoatInventoryWrapper; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.enchantment.EnchantmentHelper; @@ -38,19 +40,19 @@ public class MixinBoatEntity implements BoatUtil { @Inject(at = @At("RETURN"), method = "initDataTracker") public void initDataTracker(CallbackInfo info) { - ((BoatEntity) (Object) this).getDataTracker().startTracking(CHEST_MODE, BoatChestMode.NONE.getID()); + ((BoatEntity) (Object) this).getDataTracker().startTracking(CHEST_MODE, BoatChestModes.NONE.getID()); } @Inject(at = @At("HEAD"), method = "canAddPassenger", cancellable = true) public void canAddPassenger(Entity passenger, CallbackInfoReturnable info) { - if (((BoatEntity) (Object) this).getPassengerList().size() > 0 && getChestMode() != BoatChestMode.NONE) { + if (((BoatEntity) (Object) this).getPassengerList().size() > 0 && getChestMode() != BoatChestModes.NONE) { info.setReturnValue(false); } } @Redirect(at = @At(value = "INVOKE", target = "Ljava/util/List;size()I"), method = "updatePassengerPosition", allow = 2, require = 2) public int updatePassengerPosition(List list) { - if (getChestMode() != BoatChestMode.NONE) { + if (getChestMode() != BoatChestModes.NONE) { return list.size() + 1; } else { return list.size(); @@ -64,7 +66,7 @@ public class MixinBoatEntity implements BoatUtil { BoatChestMode newMode = BoatChestMode.valueOf(Block.getBlockFromItem(itemStack.getItem())); - if (newMode != BoatChestMode.NONE && mode == BoatChestMode.NONE) { + if (newMode != BoatChestModes.NONE && mode == BoatChestModes.NONE) { List passengers = ((BoatEntity) (Object) this).getPassengerList(); for (int i = 1; i < passengers.size(); i++) { passengers.get(i).stopRiding(); @@ -129,7 +131,7 @@ public class MixinBoatEntity implements BoatUtil { @Unique private void updateInventory() { BoatChestMode mode = getChestMode(); - items = mode.hasItems() ? new BoatInventory((BoatEntity) (Object) this, mode.getSize(), stack, mode.getOpenSound(), mode.getCloseSound()) : null; + items = mode.hasItems() ? new BoatInventory((BoatEntity) (Object) this, mode.getSize(), stack, mode) : null; } @Unique @@ -194,6 +196,6 @@ public class MixinBoatEntity implements BoatUtil { @Override public void openInventory(PlayerEntity player) { BoatChestMode mode = getChestMode(); - player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, playerInventory, playerEntity) -> mode.getScreenHandlerFactory().createMenu(i, playerInventory, playerEntity, MixinBoatEntity.this), mode.getScreenHandlerName(stack))); + player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, playerInventory, playerEntity) -> mode.getScreenHandlerFactory().createMenu(i, playerInventory, playerEntity, MixinBoatEntity.this, inventory -> new BoatInventoryWrapper((Entity) (Object) this, inventory, mode)), mode.getScreenHandlerName(stack))); } } diff --git a/src/main/java/com/thebrokenrail/twine/mixin/MixinBoatEntityRenderer.java b/src/main/java/com/thebrokenrail/twine/mixin/MixinBoatEntityRenderer.java index 0898d98..429b052 100644 --- a/src/main/java/com/thebrokenrail/twine/mixin/MixinBoatEntityRenderer.java +++ b/src/main/java/com/thebrokenrail/twine/mixin/MixinBoatEntityRenderer.java @@ -1,6 +1,6 @@ package com.thebrokenrail.twine.mixin; -import com.thebrokenrail.twine.util.BoatUtil; +import com.thebrokenrail.twine.util.boat.BoatUtil; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.block.BlockRenderType; diff --git a/src/main/java/com/thebrokenrail/twine/mixin/MixinClientPlayerInteractionManager.java b/src/main/java/com/thebrokenrail/twine/mixin/MixinClientPlayerInteractionManager.java index 3d1627c..8a3a7c7 100644 --- a/src/main/java/com/thebrokenrail/twine/mixin/MixinClientPlayerInteractionManager.java +++ b/src/main/java/com/thebrokenrail/twine/mixin/MixinClientPlayerInteractionManager.java @@ -1,7 +1,7 @@ package com.thebrokenrail.twine.mixin; -import com.thebrokenrail.twine.util.BoatChestMode; -import com.thebrokenrail.twine.util.BoatUtil; +import com.thebrokenrail.twine.util.boat.BoatChestModes; +import com.thebrokenrail.twine.util.boat.BoatUtil; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; @@ -24,7 +24,7 @@ public class MixinClientPlayerInteractionManager { @Inject(at = @At("HEAD"), method = "hasRidingInventory", cancellable = true) public void hasRidingInventory(CallbackInfoReturnable info) { assert client.player != null; - if (client.player.hasVehicle() && client.player.getVehicle() instanceof BoatEntity && ((BoatUtil) client.player.getVehicle()).getChestMode() != BoatChestMode.NONE) { + if (client.player.hasVehicle() && client.player.getVehicle() instanceof BoatEntity && ((BoatUtil) client.player.getVehicle()).getChestMode() != BoatChestModes.NONE) { info.setReturnValue(true); } } diff --git a/src/main/java/com/thebrokenrail/twine/mixin/MixinServerPlayNetworkHandler.java b/src/main/java/com/thebrokenrail/twine/mixin/MixinServerPlayNetworkHandler.java index 9782a6a..80598e3 100644 --- a/src/main/java/com/thebrokenrail/twine/mixin/MixinServerPlayNetworkHandler.java +++ b/src/main/java/com/thebrokenrail/twine/mixin/MixinServerPlayNetworkHandler.java @@ -1,7 +1,7 @@ package com.thebrokenrail.twine.mixin; -import com.thebrokenrail.twine.util.BoatChestMode; -import com.thebrokenrail.twine.util.BoatUtil; +import com.thebrokenrail.twine.util.boat.BoatChestModes; +import com.thebrokenrail.twine.util.boat.BoatUtil; import net.minecraft.entity.vehicle.BoatEntity; import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket; import net.minecraft.server.network.ServerPlayNetworkHandler; @@ -19,7 +19,7 @@ public class MixinServerPlayNetworkHandler { @Inject(at = @At("TAIL"), method = "onClientCommand") public void onClientCommand(ClientCommandC2SPacket packet, CallbackInfo info) { - if (packet.getMode() == ClientCommandC2SPacket.Mode.OPEN_INVENTORY && player.hasVehicle() && player.getVehicle() instanceof BoatEntity && ((BoatUtil) player.getVehicle()).getChestMode() != BoatChestMode.NONE) { + if (packet.getMode() == ClientCommandC2SPacket.Mode.OPEN_INVENTORY && player.hasVehicle() && player.getVehicle() instanceof BoatEntity && ((BoatUtil) player.getVehicle()).getChestMode() != BoatChestModes.NONE) { ((BoatUtil) player.getVehicle()).openInventory(player); } } diff --git a/src/main/java/com/thebrokenrail/twine/mixin/MixinSlot.java b/src/main/java/com/thebrokenrail/twine/mixin/MixinSlot.java index 647fc4f..838e39c 100644 --- a/src/main/java/com/thebrokenrail/twine/mixin/MixinSlot.java +++ b/src/main/java/com/thebrokenrail/twine/mixin/MixinSlot.java @@ -1,7 +1,7 @@ package com.thebrokenrail.twine.mixin; import com.thebrokenrail.twine.item.BackpackItem; -import com.thebrokenrail.twine.util.BackpackInventory; +import com.thebrokenrail.twine.util.backpack.inventory.BackpackInventory; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.screen.slot.Slot; diff --git a/src/main/java/com/thebrokenrail/twine/util/BoatChestMode.java b/src/main/java/com/thebrokenrail/twine/util/BoatChestMode.java deleted file mode 100644 index 9fe50ac..0000000 --- a/src/main/java/com/thebrokenrail/twine/util/BoatChestMode.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.thebrokenrail.twine.util; - -import com.google.common.collect.Lists; -import com.thebrokenrail.twine.Twine; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; -import net.minecraft.block.EnderChestBlock; -import net.minecraft.block.ShulkerBoxBlock; -import net.minecraft.block.entity.ChestBlockEntity; -import net.minecraft.block.entity.ShulkerBoxBlockEntity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.GenericContainerScreenHandler; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.ShulkerBoxScreenHandler; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.sound.SoundEvent; -import net.minecraft.sound.SoundEvents; -import net.minecraft.text.Text; -import net.minecraft.util.DyeColor; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; - -public class BoatChestMode { - public interface BoatScreenHandlerFactory { - ScreenHandler createMenu(int syncId, PlayerInventory inv, PlayerEntity player, BoatUtil boat); - } - - private static final ArrayList values = new ArrayList<>(); - - public static final BoatChestMode NONE = new BoatChestMode(Blocks.AIR, null, null, null); - - static { - BoatScreenHandlerFactory chestScreenHandler = (i, playerInventory, playerEntity, boat) -> GenericContainerScreenHandler.createGeneric9x3(i, playerInventory, boat.getChestInventory()); - ChestBlockEntity chest = new ChestBlockEntity(); - Function chestScreenHandlerName = stack -> stack.hasCustomName() ? stack.getName() : chest.getName(); - - new BoatChestMode(Blocks.ENDER_CHEST, (i, playerInventory, playerEntity, boat) -> GenericContainerScreenHandler.createGeneric9x3(i, playerInventory, new EnderChestInventoryWrapper((Entity) boat, playerEntity.getEnderChestInventory())), stack -> EnderChestBlock.CONTAINER_NAME, player -> Twine.ENDER_CHEST_BOAT_CRITERION.trigger(player)); - new BoatChestMode(Blocks.CHEST, true, false, 27, chestScreenHandler, chestScreenHandlerName, player -> Twine.CHEST_BOAT_CRITERION.trigger(player), SoundEvents.BLOCK_CHEST_OPEN, SoundEvents.BLOCK_CHEST_CLOSE); - new BoatChestMode(Blocks.TRAPPED_CHEST, true, false, 27, chestScreenHandler, chestScreenHandlerName, player -> Twine.CHEST_BOAT_CRITERION.trigger(player), SoundEvents.BLOCK_CHEST_OPEN, SoundEvents.BLOCK_CHEST_CLOSE); - - ShulkerBoxBlockEntity shulker = new ShulkerBoxBlockEntity(); - List colors = Lists.asList(null, DyeColor.values()); - for (DyeColor value : colors) { - new BoatChestMode(ShulkerBoxBlock.get(value), true, true, 27, (i, playerInventory, playerEntity, boat) -> new ShulkerBoxScreenHandler(i, playerInventory, boat.getChestInventory()), stack -> stack.hasCustomName() ? stack.getName() : shulker.getName(), player -> Twine.SHULKER_BOX_BOAT_CRITERION.trigger(player), SoundEvents.BLOCK_SHULKER_BOX_OPEN, SoundEvents.BLOCK_SHULKER_BOX_CLOSE); - } - } - - private final Block block; - private final boolean hasItems; - private final boolean containsItems; - - private final int size; - - private final BoatScreenHandlerFactory screenHandlerFactory; - private final Function screenHandlerNameFactory; - - private final Consumer advancementTrigger; - - private final int id; - - private final SoundEvent openSound; - private final SoundEvent closeSound; - - private BoatChestMode(Block block, boolean hasItems, boolean containsItems, int size, BoatScreenHandlerFactory screenHandlerFactory, Function screenHandlerNameFactory, Consumer advancementTrigger, SoundEvent openSound, SoundEvent closeSound) { - this.screenHandlerFactory = screenHandlerFactory; - this.size = size; - this.screenHandlerNameFactory = screenHandlerNameFactory; - this.advancementTrigger = advancementTrigger; - this.openSound = openSound; - this.closeSound = closeSound; - this.id = values.size(); - this.block = block; - this.hasItems = hasItems; - this.containsItems = containsItems; - values.add(this); - } - - private BoatChestMode(Block block, BoatScreenHandlerFactory screenHandlerFactory, Function screenHandlerNameFactory, Consumer advancementTrigger) { - this(block,false, false, 0, screenHandlerFactory, screenHandlerNameFactory, advancementTrigger, null, null); - } - - public int getSize() { - return size; - } - - public BoatScreenHandlerFactory getScreenHandlerFactory() { - return screenHandlerFactory; - } - - public Text getScreenHandlerName(ItemStack stack) { - return screenHandlerNameFactory.apply(stack); - } - - public void triggerAdvancement(ServerPlayerEntity player) { - if (advancementTrigger != null) { - advancementTrigger.accept(player); - } - } - - public SoundEvent getOpenSound() { - return openSound; - } - - public SoundEvent getCloseSound() { - return closeSound; - } - - public Block getBlock() { - return block; - } - - public boolean hasItems() { - return hasItems; - } - - public boolean containsItems() { - return containsItems; - } - - public int getID() { - return id; - } - - public static BoatChestMode valueOf(Block block) { - for (BoatChestMode mode : values) { - if (mode.getBlock() == block) { - return mode; - } - } - return NONE; - } - - public static BoatChestMode valueOf(int index) { - BoatChestMode mode = values.get(index); - return mode != null ? mode : NONE; - } -} diff --git a/src/main/java/com/thebrokenrail/twine/util/BoatInventory.java b/src/main/java/com/thebrokenrail/twine/util/BoatInventory.java deleted file mode 100644 index 6c5aa7e..0000000 --- a/src/main/java/com/thebrokenrail/twine/util/BoatInventory.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.thebrokenrail.twine.util; - -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.sound.SoundEvent; - -public class BoatInventory extends ItemInventory { - private final Entity entity; - - private final SoundEvent openSound; - private final SoundEvent closeSound; - - public BoatInventory(Entity entity, int size, ItemStack stack, SoundEvent openSound, SoundEvent closeSound) { - super(size, stack); - this.entity = entity; - this.openSound = openSound; - this.closeSound = closeSound; - } - - @Override - public boolean canPlayerUse(PlayerEntity player) { - return BoatUtil.canReachEntity(player, entity) && entity.isAlive() && ((BoatUtil) entity).getChestMode().hasItems(); - } - - @Override - public void onOpen(PlayerEntity player) { - if (openSound != null) { - BoatUtil.playSound(entity, openSound); - } - } - - @Override - public void onClose(PlayerEntity player) { - if (closeSound != null) { - BoatUtil.playSound(entity, closeSound); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/thebrokenrail/twine/util/BackpackScreenHandler.java b/src/main/java/com/thebrokenrail/twine/util/backpack/BackpackScreenHandler.java similarity index 89% rename from src/main/java/com/thebrokenrail/twine/util/BackpackScreenHandler.java rename to src/main/java/com/thebrokenrail/twine/util/backpack/BackpackScreenHandler.java index 7ed7759..8286e62 100644 --- a/src/main/java/com/thebrokenrail/twine/util/BackpackScreenHandler.java +++ b/src/main/java/com/thebrokenrail/twine/util/backpack/BackpackScreenHandler.java @@ -1,6 +1,7 @@ -package com.thebrokenrail.twine.util; +package com.thebrokenrail.twine.util.backpack; import com.thebrokenrail.twine.Twine; +import com.thebrokenrail.twine.util.backpack.inventory.BackpackInventory; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; import net.minecraft.network.PacketByteBuf; diff --git a/src/main/java/com/thebrokenrail/twine/util/BackpackInventory.java b/src/main/java/com/thebrokenrail/twine/util/backpack/inventory/BackpackInventory.java similarity index 79% rename from src/main/java/com/thebrokenrail/twine/util/BackpackInventory.java rename to src/main/java/com/thebrokenrail/twine/util/backpack/inventory/BackpackInventory.java index aee63ab..be5a628 100644 --- a/src/main/java/com/thebrokenrail/twine/util/BackpackInventory.java +++ b/src/main/java/com/thebrokenrail/twine/util/backpack/inventory/BackpackInventory.java @@ -1,5 +1,6 @@ -package com.thebrokenrail.twine.util; +package com.thebrokenrail.twine.util.backpack.inventory; +import com.thebrokenrail.twine.util.inventory.ItemInventory; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.Hand; diff --git a/src/main/java/com/thebrokenrail/twine/util/boat/BoatChestMode.java b/src/main/java/com/thebrokenrail/twine/util/boat/BoatChestMode.java new file mode 100644 index 0000000..ecda8bf --- /dev/null +++ b/src/main/java/com/thebrokenrail/twine/util/boat/BoatChestMode.java @@ -0,0 +1,117 @@ +package com.thebrokenrail.twine.util.boat; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.sound.SoundEvent; +import net.minecraft.text.Text; + +import java.util.ArrayList; +import java.util.function.Consumer; +import java.util.function.Function; + +public class BoatChestMode { + public interface BoatScreenHandlerFactory { + ScreenHandler createMenu(int syncId, PlayerInventory inv, PlayerEntity player, BoatUtil boat, Function inventoryWrapper); + } + + private static final ArrayList values = new ArrayList<>(); + + private final Block block; + private final boolean hasItems; + private final boolean containsItems; + + private final int size; + + private final BoatScreenHandlerFactory screenHandlerFactory; + private final Function screenHandlerNameFactory; + + private final Consumer advancementTrigger; + + private final int id; + + private final SoundEvent openSound; + private final SoundEvent closeSound; + + BoatChestMode(Block block, boolean hasItems, boolean containsItems, int size, BoatScreenHandlerFactory screenHandlerFactory, Function screenHandlerNameFactory, Consumer advancementTrigger, SoundEvent openSound, SoundEvent closeSound) { + this.screenHandlerFactory = screenHandlerFactory; + this.size = size; + this.screenHandlerNameFactory = screenHandlerNameFactory; + this.advancementTrigger = advancementTrigger; + this.openSound = openSound; + this.closeSound = closeSound; + this.id = values.size(); + this.block = block; + this.hasItems = hasItems; + this.containsItems = containsItems; + values.add(this); + } + + public BoatChestMode(Block block, BoatScreenHandlerFactory screenHandlerFactory, Function screenHandlerNameFactory, Consumer advancementTrigger, SoundEvent openSound, SoundEvent closeSound) { + this(block, false, false, 0, screenHandlerFactory, screenHandlerNameFactory, advancementTrigger, openSound, closeSound); + } + + public int getSize() { + return size; + } + + public BoatScreenHandlerFactory getScreenHandlerFactory() { + return screenHandlerFactory; + } + + public Text getScreenHandlerName(ItemStack stack) { + return screenHandlerNameFactory.apply(stack); + } + + public void triggerAdvancement(ServerPlayerEntity player) { + if (advancementTrigger != null) { + advancementTrigger.accept(player); + } + } + + public SoundEvent getOpenSound() { + return openSound; + } + + public SoundEvent getCloseSound() { + return closeSound; + } + + public Block getBlock() { + return block; + } + + public boolean hasItems() { + return hasItems; + } + + public boolean containsItems() { + return containsItems; + } + + public int getID() { + return id; + } + + public static BoatChestMode valueOf(Block block) { + for (BoatChestMode mode : values) { + if (mode.getBlock() == block) { + return mode; + } + } + return BoatChestModes.NONE; + } + + public static BoatChestMode valueOf(int index) { + BoatChestMode mode = values.get(index); + return mode != null ? mode : BoatChestModes.NONE; + } + + static { + BoatChestModes.register(); + } +} diff --git a/src/main/java/com/thebrokenrail/twine/util/boat/BoatChestModes.java b/src/main/java/com/thebrokenrail/twine/util/boat/BoatChestModes.java new file mode 100644 index 0000000..90b041f --- /dev/null +++ b/src/main/java/com/thebrokenrail/twine/util/boat/BoatChestModes.java @@ -0,0 +1,45 @@ +package com.thebrokenrail.twine.util.boat; + +import com.google.common.collect.Lists; +import com.thebrokenrail.twine.Twine; +import net.minecraft.block.Blocks; +import net.minecraft.block.EnderChestBlock; +import net.minecraft.block.ShulkerBoxBlock; +import net.minecraft.block.entity.BarrelBlockEntity; +import net.minecraft.block.entity.ChestBlockEntity; +import net.minecraft.block.entity.ShulkerBoxBlockEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.GenericContainerScreenHandler; +import net.minecraft.screen.ShulkerBoxScreenHandler; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; +import net.minecraft.util.DyeColor; + +import java.util.List; +import java.util.function.Function; + +public class BoatChestModes { + public static final BoatChestMode NONE = new BoatChestMode(Blocks.AIR, null, null, null, null, null); + + static void register() { + new BoatChestMode(Blocks.ENDER_CHEST, (i, playerInventory, playerEntity, boat, inventoryWrapper) -> GenericContainerScreenHandler.createGeneric9x3(i, playerInventory, inventoryWrapper.apply(playerEntity.getEnderChestInventory())), stack -> EnderChestBlock.CONTAINER_NAME, player -> Twine.ENDER_CHEST_BOAT_CRITERION.trigger(player), SoundEvents.BLOCK_ENDER_CHEST_OPEN, SoundEvents.BLOCK_ENDER_CHEST_CLOSE); + + BoatChestMode.BoatScreenHandlerFactory chestScreenHandler = (i, playerInventory, playerEntity, boat, inventoryWrapper) -> GenericContainerScreenHandler.createGeneric9x3(i, playerInventory, boat.getChestInventory()); + ChestBlockEntity chest = new ChestBlockEntity(); + Function chestScreenHandlerName = stack -> stack.hasCustomName() ? stack.getName() : chest.getName(); + + new BoatChestMode(Blocks.CHEST, true, false, 27, chestScreenHandler, chestScreenHandlerName, player -> Twine.CHEST_BOAT_CRITERION.trigger(player), SoundEvents.BLOCK_CHEST_OPEN, SoundEvents.BLOCK_CHEST_CLOSE); + new BoatChestMode(Blocks.TRAPPED_CHEST, true, false, 27, chestScreenHandler, chestScreenHandlerName, player -> Twine.CHEST_BOAT_CRITERION.trigger(player), SoundEvents.BLOCK_CHEST_OPEN, SoundEvents.BLOCK_CHEST_CLOSE); + + BarrelBlockEntity barrel = new BarrelBlockEntity(); + Function barrelScreenHandlerName = stack -> stack.hasCustomName() ? stack.getName() : barrel.getName(); + + new BoatChestMode(Blocks.BARREL, true, false, 27, chestScreenHandler, barrelScreenHandlerName, player -> Twine.BARREL_BOAT_CRITERION.trigger(player), SoundEvents.BLOCK_BARREL_OPEN, SoundEvents.BLOCK_BARREL_CLOSE); + + ShulkerBoxBlockEntity shulker = new ShulkerBoxBlockEntity(); + List colors = Lists.asList(null, DyeColor.values()); + for (DyeColor value : colors) { + new BoatChestMode(ShulkerBoxBlock.get(value), true, true, 27, (i, playerInventory, playerEntity, boat, inventoryWrapper) -> new ShulkerBoxScreenHandler(i, playerInventory, boat.getChestInventory()), stack -> stack.hasCustomName() ? stack.getName() : shulker.getName(), player -> Twine.SHULKER_BOX_BOAT_CRITERION.trigger(player), SoundEvents.BLOCK_SHULKER_BOX_OPEN, SoundEvents.BLOCK_SHULKER_BOX_CLOSE); + } + } +} diff --git a/src/main/java/com/thebrokenrail/twine/util/BoatUtil.java b/src/main/java/com/thebrokenrail/twine/util/boat/BoatUtil.java similarity index 95% rename from src/main/java/com/thebrokenrail/twine/util/BoatUtil.java rename to src/main/java/com/thebrokenrail/twine/util/boat/BoatUtil.java index 573dcf5..4fbe092 100644 --- a/src/main/java/com/thebrokenrail/twine/util/BoatUtil.java +++ b/src/main/java/com/thebrokenrail/twine/util/boat/BoatUtil.java @@ -1,4 +1,4 @@ -package com.thebrokenrail.twine.util; +package com.thebrokenrail.twine.util.boat; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; diff --git a/src/main/java/com/thebrokenrail/twine/util/boat/inventory/BoatInventory.java b/src/main/java/com/thebrokenrail/twine/util/boat/inventory/BoatInventory.java new file mode 100644 index 0000000..9f7100d --- /dev/null +++ b/src/main/java/com/thebrokenrail/twine/util/boat/inventory/BoatInventory.java @@ -0,0 +1,12 @@ +package com.thebrokenrail.twine.util.boat.inventory; + +import com.thebrokenrail.twine.util.boat.BoatChestMode; +import com.thebrokenrail.twine.util.inventory.ItemInventory; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; + +public class BoatInventory extends BoatInventoryWrapper { + public BoatInventory(Entity entity, int size, ItemStack stack, BoatChestMode mode) { + super(entity, new ItemInventory(size, stack), mode); + } +} \ No newline at end of file diff --git a/src/main/java/com/thebrokenrail/twine/util/EnderChestInventoryWrapper.java b/src/main/java/com/thebrokenrail/twine/util/boat/inventory/BoatInventoryWrapper.java similarity index 65% rename from src/main/java/com/thebrokenrail/twine/util/EnderChestInventoryWrapper.java rename to src/main/java/com/thebrokenrail/twine/util/boat/inventory/BoatInventoryWrapper.java index 3fc9234..9b02dd4 100644 --- a/src/main/java/com/thebrokenrail/twine/util/EnderChestInventoryWrapper.java +++ b/src/main/java/com/thebrokenrail/twine/util/boat/inventory/BoatInventoryWrapper.java @@ -1,20 +1,21 @@ -package com.thebrokenrail.twine.util; +package com.thebrokenrail.twine.util.boat.inventory; -import net.minecraft.block.Blocks; +import com.thebrokenrail.twine.util.boat.BoatChestMode; +import com.thebrokenrail.twine.util.boat.BoatUtil; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.EnderChestInventory; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; -import net.minecraft.sound.SoundEvents; -public class EnderChestInventoryWrapper implements Inventory { - private final EnderChestInventory inventory; +public class BoatInventoryWrapper implements Inventory { + private final Inventory inventory; private final Entity entity; + private final BoatChestMode mode; - public EnderChestInventoryWrapper(Entity entity, EnderChestInventory inventory) { + public BoatInventoryWrapper(Entity entity, Inventory inventory, BoatChestMode mode) { this.entity = entity; this.inventory = inventory; + this.mode = mode; } @Override @@ -54,17 +55,21 @@ public class EnderChestInventoryWrapper implements Inventory { @Override public boolean canPlayerUse(PlayerEntity player) { - return BoatUtil.canReachEntity(player, entity) && entity.isAlive() && ((BoatUtil) entity).getChestMode().getBlock() == Blocks.ENDER_CHEST; + return BoatUtil.canReachEntity(player, entity) && entity.isAlive() && ((BoatUtil) entity).getChestMode() == mode; } @Override public void onOpen(PlayerEntity player) { - BoatUtil.playSound(entity, SoundEvents.BLOCK_ENDER_CHEST_OPEN); + if (mode.getOpenSound() != null) { + BoatUtil.playSound(entity, mode.getOpenSound()); + } } @Override public void onClose(PlayerEntity player) { - BoatUtil.playSound(entity, SoundEvents.BLOCK_ENDER_CHEST_CLOSE); + if (mode.getCloseSound() != null) { + BoatUtil.playSound(entity, mode.getCloseSound()); + } } @Override diff --git a/src/main/java/com/thebrokenrail/twine/util/ItemInventory.java b/src/main/java/com/thebrokenrail/twine/util/inventory/ItemInventory.java similarity index 91% rename from src/main/java/com/thebrokenrail/twine/util/ItemInventory.java rename to src/main/java/com/thebrokenrail/twine/util/inventory/ItemInventory.java index 7048aea..cf72253 100644 --- a/src/main/java/com/thebrokenrail/twine/util/ItemInventory.java +++ b/src/main/java/com/thebrokenrail/twine/util/inventory/ItemInventory.java @@ -1,4 +1,4 @@ -package com.thebrokenrail.twine.util; +package com.thebrokenrail.twine.util.inventory; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.Inventories; @@ -6,7 +6,7 @@ import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.util.collection.DefaultedList; -public abstract class ItemInventory implements Inventory { +public class ItemInventory implements Inventory { private final int size; private final ItemStack stack; private final DefaultedList inv; @@ -73,7 +73,9 @@ public abstract class ItemInventory implements Inventory { } @Override - public abstract boolean canPlayerUse(PlayerEntity player); + public boolean canPlayerUse(PlayerEntity player) { + return true; + } @Override public void clear() { diff --git a/src/main/resources/assets/twine/lang/en_us.json b/src/main/resources/assets/twine/lang/en_us.json index 24e166f..2131e6f 100644 --- a/src/main/resources/assets/twine/lang/en_us.json +++ b/src/main/resources/assets/twine/lang/en_us.json @@ -26,6 +26,9 @@ "advancements.twine.large_backpack.title": "Go big or go home!", "advancements.twine.large_backpack.description": "Construct a Large Backpack by combing a Small Backpack and a Gold Ingot in a Smithing Table", + "advancements.twine.barrel_boat.title": "Off-Brand Chest-Boat", + "advancements.twine.barrel_boat.description": "Put a Barrel in a Boat", + "advancements.twine.diviner.title": "Divination", "advancements.twine.diviner.description": "Construct a Diviner with a Crafting Table", diff --git a/src/main/resources/data/twine/advancements/barrel_boat.json b/src/main/resources/data/twine/advancements/barrel_boat.json new file mode 100644 index 0000000..c374be8 --- /dev/null +++ b/src/main/resources/data/twine/advancements/barrel_boat.json @@ -0,0 +1,19 @@ +{ + "display": { + "icon": { + "item": "minecraft:oak_boat" + }, + "title": { + "translate": "advancements.twine.barrel_boat.title" + }, + "description": { + "translate": "advancements.twine.barrel_boat.description" + } + }, + "parent": "twine:chest_boat", + "criteria": { + "chest_boat": { + "trigger": "twine:barrel_boat" + } + } +} \ No newline at end of file