From 07a8312fd5e03c9dc6352901d2d1135ccd7cdc67 Mon Sep 17 00:00:00 2001 From: Dmitry Luk Date: Sun, 12 Jan 2025 22:05:11 +0400 Subject: [PATCH] feat: brewing stand refactor: recipe --- .../interfaces/BlockBrewingStandBehavior.java | 4 +- .../BlockEntityBrewingStandBaseComponent.java | 18 ++ .../interfaces/BlockEntityBrewingStand.java | 10 + .../blockentity/type/BlockEntityTypes.java | 1 + .../api/container/FullContainerType.java | 42 +++- .../container/impl/BrewingStandContainer.java | 41 ++++ .../java/org/allaymc/api/i18n/TrKeys.java | 30 ++- .../item/descriptor/DefaultDescriptor.java | 22 +++ .../api/item/recipe/IdentifiedRecipe.java | 3 +- .../api/item/recipe/NetworkRecipe.java | 4 +- .../org/allaymc/api/item/recipe/Recipe.java | 13 +- .../allaymc/api/item/recipe/TaggedRecipe.java | 4 +- .../allaymc/api/item/recipe/UniqueRecipe.java | 4 +- .../api/item/recipe/impl/BaseRecipe.java | 17 ++ .../recipe/{ => impl}/CraftingRecipe.java | 10 +- .../item/recipe/{ => impl}/FurnaceRecipe.java | 8 +- .../api/item/recipe/impl/PotionMixRecipe.java | 76 ++++++++ .../item/recipe/{ => impl}/ShapedRecipe.java | 2 +- .../recipe/{ => impl}/ShapelessRecipe.java | 2 +- .../api/item/recipe/input/PotionMixInput.java | 15 ++ .../org/allaymc/api/registry/Registries.java | 6 +- .../java/org/allaymc/api/world/Dimension.java | 63 ++++-- data/resources/lang/en_US.json | 6 +- .../unpacked/lang_raw/allay/en_US.json | 6 +- .../unpacked/lang_raw/allay/zh_CN.json | 6 +- .../main/java/org/allaymc/server/Allay.java | 1 + .../BlockBeaconBaseComponentImpl.java | 2 +- .../BlockBrewingStandBaseComponentImpl.java | 35 ++++ .../impl/BlockBrewingStandBehaviorImpl.java | 9 +- .../block/type/BlockTypeInitializer.java | 10 + ...ckEntityBrewingStandBaseComponentImpl.java | 180 ++++++++++++++++++ ...ckEntityEnchantTableBaseComponentImpl.java | 2 +- ...ckEntityBlastFurnaceBaseComponentImpl.java | 2 +- .../BlockEntityFurnaceBaseComponentImpl.java | 3 +- ...kEntitySmokerFurnaceBaseComponentImpl.java | 2 +- .../impl/BlockEntityBrewingStandImpl.java | 25 +++ .../type/BlockEntityTypeInitializer.java | 9 + .../EntityPlayerNetworkComponentImpl.java | 10 +- .../loader/FurnaceRecipeRegistryLoader.java | 6 +- .../loader/PotionMixRecipeRegistryLoader.java | 49 +++++ .../registry/loader/RecipeRegistryLoader.java | 4 +- .../allaymc/api/item/recipe/RecipeTest.java | 3 + 42 files changed, 684 insertions(+), 81 deletions(-) create mode 100644 api/src/main/java/org/allaymc/api/blockentity/component/BlockEntityBrewingStandBaseComponent.java create mode 100644 api/src/main/java/org/allaymc/api/blockentity/interfaces/BlockEntityBrewingStand.java create mode 100644 api/src/main/java/org/allaymc/api/container/impl/BrewingStandContainer.java create mode 100644 api/src/main/java/org/allaymc/api/item/recipe/impl/BaseRecipe.java rename api/src/main/java/org/allaymc/api/item/recipe/{ => impl}/CraftingRecipe.java (78%) rename api/src/main/java/org/allaymc/api/item/recipe/{ => impl}/FurnaceRecipe.java (90%) create mode 100644 api/src/main/java/org/allaymc/api/item/recipe/impl/PotionMixRecipe.java rename api/src/main/java/org/allaymc/api/item/recipe/{ => impl}/ShapedRecipe.java (99%) rename api/src/main/java/org/allaymc/api/item/recipe/{ => impl}/ShapelessRecipe.java (98%) create mode 100644 api/src/main/java/org/allaymc/api/item/recipe/input/PotionMixInput.java create mode 100644 server/src/main/java/org/allaymc/server/block/component/BlockBrewingStandBaseComponentImpl.java create mode 100644 server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityBrewingStandBaseComponentImpl.java create mode 100644 server/src/main/java/org/allaymc/server/blockentity/impl/BlockEntityBrewingStandImpl.java create mode 100644 server/src/main/java/org/allaymc/server/registry/loader/PotionMixRecipeRegistryLoader.java diff --git a/api/src/main/java/org/allaymc/api/block/interfaces/BlockBrewingStandBehavior.java b/api/src/main/java/org/allaymc/api/block/interfaces/BlockBrewingStandBehavior.java index 81229c10b5..d3f086540e 100644 --- a/api/src/main/java/org/allaymc/api/block/interfaces/BlockBrewingStandBehavior.java +++ b/api/src/main/java/org/allaymc/api/block/interfaces/BlockBrewingStandBehavior.java @@ -1,6 +1,8 @@ package org.allaymc.api.block.interfaces; import org.allaymc.api.block.BlockBehavior; +import org.allaymc.api.block.component.BlockEntityHolderComponent; +import org.allaymc.api.blockentity.interfaces.BlockEntityBrewingStand; -public interface BlockBrewingStandBehavior extends BlockBehavior { +public interface BlockBrewingStandBehavior extends BlockBehavior, BlockEntityHolderComponent { } diff --git a/api/src/main/java/org/allaymc/api/blockentity/component/BlockEntityBrewingStandBaseComponent.java b/api/src/main/java/org/allaymc/api/blockentity/component/BlockEntityBrewingStandBaseComponent.java new file mode 100644 index 0000000000..8c7870052c --- /dev/null +++ b/api/src/main/java/org/allaymc/api/blockentity/component/BlockEntityBrewingStandBaseComponent.java @@ -0,0 +1,18 @@ +package org.allaymc.api.blockentity.component; + +/** + * @author IWareQ + */ +public interface BlockEntityBrewingStandBaseComponent extends BlockEntityBaseComponent { + int getBrewTime(); + + void setBrewTime(int time); + + int getFuelAmount(); + + void setFuelAmount(int amount); + + int getFuelTotal(); + + void setFuelTotal(int amount); +} diff --git a/api/src/main/java/org/allaymc/api/blockentity/interfaces/BlockEntityBrewingStand.java b/api/src/main/java/org/allaymc/api/blockentity/interfaces/BlockEntityBrewingStand.java new file mode 100644 index 0000000000..e75aef1575 --- /dev/null +++ b/api/src/main/java/org/allaymc/api/blockentity/interfaces/BlockEntityBrewingStand.java @@ -0,0 +1,10 @@ +package org.allaymc.api.blockentity.interfaces; + +import org.allaymc.api.blockentity.BlockEntity; +import org.allaymc.api.blockentity.component.BlockEntityBrewingStandBaseComponent; + +/** + * @author IWareQ + */ +public interface BlockEntityBrewingStand extends BlockEntity, BlockEntityBrewingStandBaseComponent { +} diff --git a/api/src/main/java/org/allaymc/api/blockentity/type/BlockEntityTypes.java b/api/src/main/java/org/allaymc/api/blockentity/type/BlockEntityTypes.java index a2348267ed..4d4f88adf0 100644 --- a/api/src/main/java/org/allaymc/api/blockentity/type/BlockEntityTypes.java +++ b/api/src/main/java/org/allaymc/api/blockentity/type/BlockEntityTypes.java @@ -17,4 +17,5 @@ public final class BlockEntityTypes { public static BlockEntityType ENCHANT_TABLE; public static BlockEntityType JUKEBOX; public static BlockEntityType BEACON; + public static BlockEntityType BREWING_STAND; } diff --git a/api/src/main/java/org/allaymc/api/container/FullContainerType.java b/api/src/main/java/org/allaymc/api/container/FullContainerType.java index 5863f25c83..136876fd60 100644 --- a/api/src/main/java/org/allaymc/api/container/FullContainerType.java +++ b/api/src/main/java/org/allaymc/api/container/FullContainerType.java @@ -129,6 +129,14 @@ public record FullContainerType( .mapNetworkSlotIndex(27, BeaconContainer.BEACON_PAYMENT_SLOT) .build(); + public static final FullContainerType BREWING_STAND = builder() + .id(ContainerType.BREWING_STAND) + .size(5) + .mapSlotToType(BrewingStandContainer.REAGENT_SLOT, ContainerSlotType.BREWING_INPUT) + .mapRangedSlotToType(1, 3, ContainerSlotType.BREWING_RESULT) + .mapSlotToType(BrewingStandContainer.FUEL_SLOT, ContainerSlotType.BREWING_FUEL) + .build(); + public FullContainerType(int id, ContainerSlotType[] slotTypeTable, Set heldSlotTypes, BiMap networkSlotIndexMapper) { this.id = id; this.slotTypeTable = slotTypeTable; @@ -179,25 +187,38 @@ public FullContainerTypeBuilder size(int size) { } public FullContainerTypeBuilder mapRangedSlotToType(int left, int right, ContainerSlotType type) { - if (slotTypeTable == null) throw new IllegalStateException("The size must be set firstly!"); - if (left > right) throw new IllegalArgumentException("Left must smaller than right!"); - if (left > slotTypeTable.length || right > slotTypeTable.length) + if (slotTypeTable == null) { + throw new IllegalStateException("The size must be set firstly!"); + } + if (left > right) { + throw new IllegalArgumentException("Left must smaller than right!"); + } + if (left > slotTypeTable.length || right > slotTypeTable.length) { throw new IllegalArgumentException("Left or right bigger than size!"); + } heldSlotTypes.add(type); - for (int i = left; i <= right; i++) slotTypeTable[i] = type; + for (int i = left; i <= right; i++) { + slotTypeTable[i] = type; + } return this; } public FullContainerTypeBuilder mapAllSlotToType(ContainerSlotType type) { - if (slotTypeTable == null) throw new IllegalStateException("The size must be set firstly!"); + if (slotTypeTable == null) { + throw new IllegalStateException("The size must be set firstly!"); + } + heldSlotTypes.add(type); Arrays.fill(slotTypeTable, type); return this; } public FullContainerTypeBuilder mapSlotToType(int slot, ContainerSlotType type) { - if (slotTypeTable == null) throw new IllegalStateException("The size must be set firstly!"); + if (slotTypeTable == null) { + throw new IllegalStateException("The size must be set firstly!"); + } + heldSlotTypes.add(type); slotTypeTable[slot] = type; return this; @@ -214,8 +235,13 @@ public FullContainerTypeBuilder mapNetworkSlotIndex(int networkSlotIndex, int sl } public FullContainerTypeBuilder mapRangedNetworkSlotIndex(int left, int right, int slot) { - if (left > right) throw new IllegalArgumentException("Left must smaller than right!"); - for (int i = left, j = 0; i <= right; i++, j++) networkSlotIndexMapper.put(i, slot + j); + if (left > right) { + throw new IllegalArgumentException("Left must smaller than right!"); + } + + for (int i = left, j = 0; i <= right; i++, j++) { + networkSlotIndexMapper.put(i, slot + j); + } return this; } diff --git a/api/src/main/java/org/allaymc/api/container/impl/BrewingStandContainer.java b/api/src/main/java/org/allaymc/api/container/impl/BrewingStandContainer.java new file mode 100644 index 0000000000..53fbed052b --- /dev/null +++ b/api/src/main/java/org/allaymc/api/container/impl/BrewingStandContainer.java @@ -0,0 +1,41 @@ +package org.allaymc.api.container.impl; + +import org.allaymc.api.container.FullContainerType; +import org.allaymc.api.item.ItemStack; +import org.jetbrains.annotations.Range; + +/** + * @author IWareQ + */ +public class BrewingStandContainer extends BlockContainer { + public static final int REAGENT_SLOT = 0; + public static final int FUEL_SLOT = 4; + + public BrewingStandContainer() { + super(FullContainerType.BREWING_STAND); + } + + public ItemStack getReagent() { + return getItemStack(REAGENT_SLOT); + } + + public void setReagent(ItemStack itemStack) { + setItemStack(REAGENT_SLOT, itemStack); + } + + public ItemStack getFuel() { + return getItemStack(FUEL_SLOT); + } + + public void setFuel(ItemStack itemStack) { + setItemStack(FUEL_SLOT, itemStack); + } + + public ItemStack getResult(@Range(from = 0, to = 2) int slot) { + return getItemStack(slot + 1); + } + + public void setResult(@Range(from = 0, to = 2) int slot, ItemStack itemStack) { + setItemStack(slot + 1, itemStack); + } +} diff --git a/api/src/main/java/org/allaymc/api/i18n/TrKeys.java b/api/src/main/java/org/allaymc/api/i18n/TrKeys.java index f02558d89e..9c9e9ef236 100644 --- a/api/src/main/java/org/allaymc/api/i18n/TrKeys.java +++ b/api/src/main/java/org/allaymc/api/i18n/TrKeys.java @@ -227,16 +227,6 @@ public interface TrKeys { */ String A_EXTENSION_MAINCLASS_TYPEINVALID = "allay:extension.mainclass.typeinvalid"; - /** - * Loaded %1 furnace recipes - */ - String A_FURNACERECIPE_LOADED = "allay:furnacerecipe.loaded"; - - /** - * Loading furnace recipes... - */ - String A_FURNACERECIPE_LOADING = "allay:furnacerecipe.loading"; - /** * Chunk */ @@ -562,6 +552,26 @@ public interface TrKeys { */ String A_RECIPE_LOADING = "allay:recipe.loading"; + /** + * Loading furnace recipes... + */ + String A_RECIPE_FURNACE_LOADING = "allay:recipe.furnace.loading"; + + /** + * Loaded %1 furnace recipes + */ + String A_RECIPE_FURNACE_LOADED = "allay:recipe.furnace.loaded"; + + /** + * Loading potion mix recipes... + */ + String A_RECIPE_POTIONMIX_LOADING = "allay:recipe.potionmix.loading"; + + /** + * Loaded %1 potion mix recipes + */ + String A_RECIPE_POTIONMIX_LOADED = "allay:recipe.potionmix.loaded"; + /** * §eYou are running a development version. The development version may have unexpected bugs, please do not use it in a production environment! */ diff --git a/api/src/main/java/org/allaymc/api/item/descriptor/DefaultDescriptor.java b/api/src/main/java/org/allaymc/api/item/descriptor/DefaultDescriptor.java index ce1a6df40f..dc446d0fae 100644 --- a/api/src/main/java/org/allaymc/api/item/descriptor/DefaultDescriptor.java +++ b/api/src/main/java/org/allaymc/api/item/descriptor/DefaultDescriptor.java @@ -5,6 +5,8 @@ import org.allaymc.api.item.ItemStack; import org.allaymc.api.item.type.ItemType; +import java.util.Objects; + /** * Represents a default item descriptor. *

@@ -31,6 +33,10 @@ public boolean match(ItemStack itemStack) { (meta == WILDCARD_META || itemStack.getMeta() == meta); } + public ItemStack createItemStack() { + return itemType.createItemStack(1, meta); + } + @Override public org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptor toNetwork() { return new org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.DefaultDescriptor( @@ -38,4 +44,20 @@ public org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescripto meta ); } + + @Override + public String toString() { + return itemType.getIdentifier() + ":" + meta; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof DefaultDescriptor that)) return false; + return meta == that.meta && Objects.equals(itemType, that.itemType); + } + + @Override + public int hashCode() { + return Objects.hash(itemType, meta); + } } diff --git a/api/src/main/java/org/allaymc/api/item/recipe/IdentifiedRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/IdentifiedRecipe.java index c86d81eeaf..a02a09b0e1 100644 --- a/api/src/main/java/org/allaymc/api/item/recipe/IdentifiedRecipe.java +++ b/api/src/main/java/org/allaymc/api/item/recipe/IdentifiedRecipe.java @@ -1,5 +1,6 @@ package org.allaymc.api.item.recipe; +import org.allaymc.api.item.recipe.impl.BaseRecipe; import org.allaymc.api.utils.Identified; /** @@ -7,5 +8,5 @@ * * @author daoge_cmd */ -public interface IdentifiedRecipe extends Recipe, Identified { +public interface IdentifiedRecipe extends BaseRecipe, Identified { } diff --git a/api/src/main/java/org/allaymc/api/item/recipe/NetworkRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/NetworkRecipe.java index 9fcbf42c59..29f0b20775 100644 --- a/api/src/main/java/org/allaymc/api/item/recipe/NetworkRecipe.java +++ b/api/src/main/java/org/allaymc/api/item/recipe/NetworkRecipe.java @@ -1,5 +1,7 @@ package org.allaymc.api.item.recipe; +import org.allaymc.api.item.recipe.impl.BaseRecipe; + import java.util.concurrent.atomic.AtomicInteger; /** @@ -7,7 +9,7 @@ * * @author daoge_cmd */ -public interface NetworkRecipe extends Recipe { +public interface NetworkRecipe extends BaseRecipe { AtomicInteger NETWORK_ID_COUNTER = new AtomicInteger(1); static int assignNetworkId() { diff --git a/api/src/main/java/org/allaymc/api/item/recipe/Recipe.java b/api/src/main/java/org/allaymc/api/item/recipe/Recipe.java index e3ec74d959..33c2710295 100644 --- a/api/src/main/java/org/allaymc/api/item/recipe/Recipe.java +++ b/api/src/main/java/org/allaymc/api/item/recipe/Recipe.java @@ -2,15 +2,13 @@ import org.allaymc.api.item.ItemStack; import org.allaymc.api.item.recipe.input.Input; -import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.CraftingDataType; -import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData; /** * Represents a recipe. * * @author daoge_cmd */ -public interface Recipe { +public interface Recipe { /** * Check if the input matches the recipe. * @@ -27,17 +25,10 @@ public interface Recipe { */ ItemStack[] getOutputs(); - /** - * Get the type of this recipe. - * - * @return the type of this recipe. - */ - CraftingDataType getType(); - /** * Create the network data of this recipe. * * @return the network data of this recipe. */ - RecipeData toNetworkRecipeData(); + T toNetworkData(); } diff --git a/api/src/main/java/org/allaymc/api/item/recipe/TaggedRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/TaggedRecipe.java index 48462501af..43cba174a6 100644 --- a/api/src/main/java/org/allaymc/api/item/recipe/TaggedRecipe.java +++ b/api/src/main/java/org/allaymc/api/item/recipe/TaggedRecipe.java @@ -1,11 +1,13 @@ package org.allaymc.api.item.recipe; +import org.allaymc.api.item.recipe.impl.BaseRecipe; + /** * Represents a tagged recipe. * * @author daoge_cmd */ -public interface TaggedRecipe extends Recipe { +public interface TaggedRecipe extends BaseRecipe { /** * Get the tag indicating the crafting type applicable to this recipe. *

diff --git a/api/src/main/java/org/allaymc/api/item/recipe/UniqueRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/UniqueRecipe.java index debd43e227..3503faaaaa 100644 --- a/api/src/main/java/org/allaymc/api/item/recipe/UniqueRecipe.java +++ b/api/src/main/java/org/allaymc/api/item/recipe/UniqueRecipe.java @@ -1,5 +1,7 @@ package org.allaymc.api.item.recipe; +import org.allaymc.api.item.recipe.impl.BaseRecipe; + import java.util.UUID; /** @@ -7,7 +9,7 @@ * * @author daoge_cmd */ -public interface UniqueRecipe extends Recipe { +public interface UniqueRecipe extends BaseRecipe { /** * Get the UUID of the recipe. * diff --git a/api/src/main/java/org/allaymc/api/item/recipe/impl/BaseRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/impl/BaseRecipe.java new file mode 100644 index 0000000000..8577fa7709 --- /dev/null +++ b/api/src/main/java/org/allaymc/api/item/recipe/impl/BaseRecipe.java @@ -0,0 +1,17 @@ +package org.allaymc.api.item.recipe.impl; + +import org.allaymc.api.item.recipe.Recipe; +import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.CraftingDataType; +import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData; + +/** + * @author IWareQ + */ +public interface BaseRecipe extends Recipe { + /** + * Get the type of this recipe. + * + * @return the type of this recipe. + */ + CraftingDataType getType(); +} diff --git a/api/src/main/java/org/allaymc/api/item/recipe/CraftingRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/impl/CraftingRecipe.java similarity index 78% rename from api/src/main/java/org/allaymc/api/item/recipe/CraftingRecipe.java rename to api/src/main/java/org/allaymc/api/item/recipe/impl/CraftingRecipe.java index 7d5af2c75b..efbd94b782 100644 --- a/api/src/main/java/org/allaymc/api/item/recipe/CraftingRecipe.java +++ b/api/src/main/java/org/allaymc/api/item/recipe/impl/CraftingRecipe.java @@ -1,9 +1,13 @@ -package org.allaymc.api.item.recipe; +package org.allaymc.api.item.recipe.impl; import lombok.AccessLevel; import lombok.Getter; import org.allaymc.api.item.ItemStack; import org.allaymc.api.item.component.ItemBaseComponent; +import org.allaymc.api.item.recipe.IdentifiedRecipe; +import org.allaymc.api.item.recipe.NetworkRecipe; +import org.allaymc.api.item.recipe.TaggedRecipe; +import org.allaymc.api.item.recipe.UniqueRecipe; import org.allaymc.api.utils.Identifier; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData; @@ -18,7 +22,7 @@ * @author daoge_cmd */ @Getter -public abstract class CraftingRecipe implements Recipe, TaggedRecipe, UniqueRecipe, IdentifiedRecipe, NetworkRecipe { +public abstract class CraftingRecipe implements BaseRecipe, TaggedRecipe, UniqueRecipe, IdentifiedRecipe, NetworkRecipe { protected Identifier identifier; protected ItemStack[] outputs; protected String tag; @@ -40,7 +44,7 @@ protected CraftingRecipe(Identifier identifier, ItemStack[] outputs, String tag, } @Override - public RecipeData toNetworkRecipeData() { + public RecipeData toNetworkData() { return networkRecipeDataCache; } diff --git a/api/src/main/java/org/allaymc/api/item/recipe/FurnaceRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/impl/FurnaceRecipe.java similarity index 90% rename from api/src/main/java/org/allaymc/api/item/recipe/FurnaceRecipe.java rename to api/src/main/java/org/allaymc/api/item/recipe/impl/FurnaceRecipe.java index c6be247d71..ae56fba210 100644 --- a/api/src/main/java/org/allaymc/api/item/recipe/FurnaceRecipe.java +++ b/api/src/main/java/org/allaymc/api/item/recipe/impl/FurnaceRecipe.java @@ -1,9 +1,11 @@ -package org.allaymc.api.item.recipe; +package org.allaymc.api.item.recipe.impl; import lombok.Builder; import lombok.Getter; import org.allaymc.api.item.ItemStack; import org.allaymc.api.item.descriptor.DefaultDescriptor; +import org.allaymc.api.item.recipe.IdentifiedRecipe; +import org.allaymc.api.item.recipe.TaggedRecipe; import org.allaymc.api.item.recipe.input.FurnaceInput; import org.allaymc.api.item.recipe.input.Input; import org.allaymc.api.item.type.ItemType; @@ -17,7 +19,7 @@ * * @author daoge_cmd */ -public class FurnaceRecipe implements Recipe, TaggedRecipe, IdentifiedRecipe { +public class FurnaceRecipe implements BaseRecipe, TaggedRecipe, IdentifiedRecipe { public static final String FURNACE_TAG = "furnace"; public static final String BLAST_FURNACE_TAG = "blast_furnace"; public static final String SMOKER_TAG = "smoker"; @@ -76,7 +78,7 @@ public CraftingDataType getType() { } @Override - public RecipeData toNetworkRecipeData() { + public RecipeData toNetworkData() { return FurnaceRecipeData.of( getType(), ingredient.getItemType().getRuntimeId(), 0, output.toNetworkItemData(), tag diff --git a/api/src/main/java/org/allaymc/api/item/recipe/impl/PotionMixRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/impl/PotionMixRecipe.java new file mode 100644 index 0000000000..5f7f80768a --- /dev/null +++ b/api/src/main/java/org/allaymc/api/item/recipe/impl/PotionMixRecipe.java @@ -0,0 +1,76 @@ +package org.allaymc.api.item.recipe.impl; + +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; +import org.allaymc.api.item.ItemStack; +import org.allaymc.api.item.descriptor.DefaultDescriptor; +import org.allaymc.api.item.recipe.Recipe; +import org.allaymc.api.item.recipe.input.Input; +import org.allaymc.api.item.recipe.input.PotionMixInput; +import org.allaymc.api.utils.Identified; +import org.allaymc.api.utils.Identifier; +import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData; + +/** + * @author IWareQ + */ +@ToString +@Getter +public class PotionMixRecipe implements Recipe, Identified { + protected DefaultDescriptor ingredient; + protected DefaultDescriptor output; + protected DefaultDescriptor reagent; + + /** + * NOTICE: Potion mix recipe does not have identifier in runtime + * We give each potion mix recipe an identifier server-side to make it possible + * to be registered into registry + * The identifier is simply ingredient + reagent + */ + @Getter + protected Identifier identifier; + + @Builder + public PotionMixRecipe(DefaultDescriptor ingredient, DefaultDescriptor output, DefaultDescriptor reagent) { + this.ingredient = ingredient; + this.output = output; + this.reagent = reagent; + this.identifier = buildIdentifier(ingredient.createItemStack(), reagent.createItemStack()); + } + + public static Identifier buildIdentifier(ItemStack ingredient, ItemStack reagent) { + return new Identifier( + ingredient.getItemType().getIdentifier().path() + "_" + ingredient.getMeta() + + "_" + + reagent.getItemType().getIdentifier().path() + "_" + reagent.getMeta() + ); + } + + @Override + public boolean match(Input input) { + if (input instanceof PotionMixInput potionMixInput) { + return ingredient.match(potionMixInput.getIngredient()) && reagent.match(potionMixInput.getReagent()); + } + + return false; + } + + @Override + public ItemStack[] getOutputs() { + return new ItemStack[]{getOutput()}; + } + + public ItemStack getOutput() { + return output.createItemStack(); + } + + @Override + public PotionMixData toNetworkData() { + return new PotionMixData( + ingredient.getItemType().getRuntimeId(), ingredient.getMeta(), + reagent.getItemType().getRuntimeId(), reagent.getMeta(), + output.getItemType().getRuntimeId(), output.getMeta() + ); + } +} diff --git a/api/src/main/java/org/allaymc/api/item/recipe/ShapedRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/impl/ShapedRecipe.java similarity index 99% rename from api/src/main/java/org/allaymc/api/item/recipe/ShapedRecipe.java rename to api/src/main/java/org/allaymc/api/item/recipe/impl/ShapedRecipe.java index 45a21cc883..93236b331b 100644 --- a/api/src/main/java/org/allaymc/api/item/recipe/ShapedRecipe.java +++ b/api/src/main/java/org/allaymc/api/item/recipe/impl/ShapedRecipe.java @@ -1,4 +1,4 @@ -package org.allaymc.api.item.recipe; +package org.allaymc.api.item.recipe.impl; import lombok.Builder; import lombok.Getter; diff --git a/api/src/main/java/org/allaymc/api/item/recipe/ShapelessRecipe.java b/api/src/main/java/org/allaymc/api/item/recipe/impl/ShapelessRecipe.java similarity index 98% rename from api/src/main/java/org/allaymc/api/item/recipe/ShapelessRecipe.java rename to api/src/main/java/org/allaymc/api/item/recipe/impl/ShapelessRecipe.java index fdbc37492e..fd7327c815 100644 --- a/api/src/main/java/org/allaymc/api/item/recipe/ShapelessRecipe.java +++ b/api/src/main/java/org/allaymc/api/item/recipe/impl/ShapelessRecipe.java @@ -1,4 +1,4 @@ -package org.allaymc.api.item.recipe; +package org.allaymc.api.item.recipe.impl; import lombok.Builder; import lombok.Getter; diff --git a/api/src/main/java/org/allaymc/api/item/recipe/input/PotionMixInput.java b/api/src/main/java/org/allaymc/api/item/recipe/input/PotionMixInput.java new file mode 100644 index 0000000000..49b6d49df6 --- /dev/null +++ b/api/src/main/java/org/allaymc/api/item/recipe/input/PotionMixInput.java @@ -0,0 +1,15 @@ +package org.allaymc.api.item.recipe.input; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.allaymc.api.item.ItemStack; + +/** + * @author IWareQ + */ +@Getter +@AllArgsConstructor +public class PotionMixInput implements Input { + private final ItemStack ingredient; + private final ItemStack reagent; +} diff --git a/api/src/main/java/org/allaymc/api/registry/Registries.java b/api/src/main/java/org/allaymc/api/registry/Registries.java index 31b5269040..5a36d9bc18 100644 --- a/api/src/main/java/org/allaymc/api/registry/Registries.java +++ b/api/src/main/java/org/allaymc/api/registry/Registries.java @@ -12,8 +12,9 @@ import org.allaymc.api.item.component.data.ItemData; import org.allaymc.api.item.data.ItemId; import org.allaymc.api.item.enchantment.EnchantmentType; -import org.allaymc.api.item.recipe.FurnaceRecipe; import org.allaymc.api.item.recipe.NetworkRecipe; +import org.allaymc.api.item.recipe.impl.FurnaceRecipe; +import org.allaymc.api.item.recipe.impl.PotionMixRecipe; import org.allaymc.api.item.type.ItemType; import org.allaymc.api.pack.Pack; import org.allaymc.api.utils.Identifier; @@ -22,6 +23,7 @@ import java.nio.file.Path; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.function.Function; @@ -60,7 +62,7 @@ public final class Registries { // Recipe public static IntMappedRegistry RECIPES; public static SimpleMappedRegistry FURNACE_RECIPES; - // TODO: PotionMixData + public static SimpleMappedRegistry POTION_MIX_RECIPES; // TODO: ContainerMixData // TODO: MaterialReducer diff --git a/api/src/main/java/org/allaymc/api/world/Dimension.java b/api/src/main/java/org/allaymc/api/world/Dimension.java index 1edf5b3fca..ae321e97a8 100644 --- a/api/src/main/java/org/allaymc/api/world/Dimension.java +++ b/api/src/main/java/org/allaymc/api/world/Dimension.java @@ -11,7 +11,6 @@ import org.allaymc.api.block.property.type.BlockPropertyType; import org.allaymc.api.block.tag.BlockCustomTags; import org.allaymc.api.block.type.BlockState; -import org.allaymc.api.block.type.BlockTypes; import org.allaymc.api.blockentity.BlockEntity; import org.allaymc.api.entity.Entity; import org.allaymc.api.entity.initinfo.EntityInitInfo; @@ -33,6 +32,7 @@ import org.jetbrains.annotations.Range; import org.jetbrains.annotations.Unmodifiable; import org.jetbrains.annotations.UnmodifiableView; +import org.joml.Vector3f; import org.joml.Vector3fc; import org.joml.Vector3i; import org.joml.Vector3ic; @@ -53,6 +53,8 @@ */ public interface Dimension { + IntObjectPair PAIR_LIQUID_NOT_FOUND = new IntObjectImmutablePair<>(-1, null); + /** * Create a block update packet. * @@ -195,7 +197,7 @@ default void setBlockState(Vector3fc pos, BlockState blockState) { } default void setBlockState(Vector3fc pos, BlockState blockState, int layer) { - pos = pos.floor(new org.joml.Vector3f()); + pos = pos.floor(new Vector3f()); setBlockState((int) pos.x(), (int) pos.y(), (int) pos.z(), blockState, layer); } @@ -287,7 +289,7 @@ default BlockState getBlockState(Vector3fc pos) { } default BlockState getBlockState(Vector3fc pos, int layer) { - pos = pos.floor(new org.joml.Vector3f()); + pos = pos.floor(new Vector3f()); return getBlockState((int) pos.x(), (int) pos.y(), (int) pos.z(), layer); } @@ -671,7 +673,7 @@ default void addLevelSoundEvent(float x, float y, float z, SoundEvent soundEvent } default void updateAroundIgnoreFace(int x, int y, int z, BlockFace... ignoreFaces) { - updateAroundIgnoreFace(new org.joml.Vector3i(x, y, z), ignoreFaces); + updateAroundIgnoreFace(new Vector3i(x, y, z), ignoreFaces); } /** @@ -720,7 +722,7 @@ default void updateAround(Vector3ic pos) { * @param face the face of the block. */ default void updateAtFace(int x, int y, int z, BlockFace face) { - updateAtFace(new org.joml.Vector3i(x, y, z), face); + updateAtFace(new Vector3i(x, y, z), face); } /** @@ -885,11 +887,44 @@ default void broadcastPacket(BedrockPacket packet) { } default void addSound(Vector3fc pos, String sound) { - addSound(pos.x(), pos.y(), pos.z(), sound); + addSound(pos, sound, 1); + } + + default void addSound(Vector3fc pos, String sound, float volume) { + addSound(pos, sound, volume, 1); + } + + default void addSound(Vector3fc pos, String sound, float volume, float pitch) { + addSound(pos.x(), pos.y(), pos.z(), sound, volume, pitch); + } + + default void addSound(Vector3ic pos, String sound) { + addSound(pos, sound, 1); + } + + default void addSound(Vector3ic pos, String sound, float volume) { + addSound(pos, sound, volume, 1); + } + + default void addSound(Vector3ic pos, String sound, float volume, float pitch) { + addSound(pos.x(), pos.y(), pos.z(), sound, volume, pitch); } default void addSound(float x, float y, float z, String sound) { - addSound(x, y, z, sound, 1, 1); + addSound(x, y, z, sound, 1); + } + + /** + * Add a sound at the specified pos. + * + * @param x the x coordinate of the pos. + * @param y the y coordinate of the pos. + * @param z the z coordinate of the pos. + * @param sound the sound. + * @param volume the volume of the sound. + */ + default void addSound(float x, float y, float z, String sound, float volume) { + addSound(x, y, z, sound, volume, 1); } /** @@ -925,7 +960,7 @@ default void addSound(float x, float y, float z, String sound, float volume, flo */ default void dropItem(ItemStack itemStack, Vector3fc pos) { var rand = ThreadLocalRandom.current(); - dropItem(itemStack, pos, new org.joml.Vector3f(rand.nextFloat(0.2f) - 0.1f, 0.2f, rand.nextFloat(0.2f) - 0.1f)); + dropItem(itemStack, pos, new Vector3f(rand.nextFloat(0.2f) - 0.1f, 0.2f, rand.nextFloat(0.2f) - 0.1f)); } default void dropItem(ItemStack itemStack, Vector3fc pos, Vector3fc motion) { @@ -978,7 +1013,7 @@ default void splitAndDropXpOrb(Vector3fc pos, int xp) { */ default void dropXpOrb(Vector3fc pos, int xp) { var rand = ThreadLocalRandom.current(); - var motion = new org.joml.Vector3f( + var motion = new Vector3f( (rand.nextFloat() * 0.2f - 0.1f) * 2f, rand.nextFloat() * 0.4f, (rand.nextFloat() * 0.2f - 0.1f) * 2f @@ -1097,7 +1132,7 @@ default Vector3ic findSuitableGroundPosAround(Predicate predicate, var pz = z + rand.nextInt(-range, range + 1); var py = getHeight(px, pz) + 1; if (predicate.test(new Position3i(px, py, pz, this))) { - return new org.joml.Vector3i(px, py, pz); + return new Vector3i(px, py, pz); } } return null; @@ -1186,8 +1221,6 @@ default void setBiome(int x, int y, int z, BiomeType biome) { chunk.setBiome(x & 15, y, z & 15, biome); } - IntObjectPair PAIR_LIQUID_NOT_FOUND = new IntObjectImmutablePair<>(-1, null); - /** * @see #getLiquid(Vector3ic) */ @@ -1283,19 +1316,19 @@ default boolean removeLiquid(int x, int y, int z) { */ default boolean removeLiquid(Vector3ic pos) { var layer0 = getBlockState(pos); - if (layer0.getBlockType() == BlockTypes.AIR) { + if (layer0.getBlockType() == AIR) { return true; } if (layer0.getBehavior() instanceof BlockLiquidBaseComponent) { - setBlockState(pos, BlockTypes.AIR.getDefaultState()); + setBlockState(pos, AIR.getDefaultState()); return true; } if (layer0.getBlockStateData().canContainLiquid()) { var layer1 = getBlockState(pos, 1); if (layer1.getBehavior() instanceof BlockLiquidBaseComponent) { - setBlockState(pos, BlockTypes.AIR.getDefaultState(), 1); + setBlockState(pos, AIR.getDefaultState(), 1); return false; } } diff --git a/data/resources/lang/en_US.json b/data/resources/lang/en_US.json index 823c6a2c7c..59de262065 100644 --- a/data/resources/lang/en_US.json +++ b/data/resources/lang/en_US.json @@ -43,8 +43,6 @@ "allay:extension.entrance.missing": "Can't find the entrance of extension %1", "allay:extension.loading": "loading extension %1", "allay:extension.mainclass.typeinvalid": "The entrance class of extension %1 is not a subclass of PluginExtension", - "allay:furnacerecipe.loaded": "Loaded %1 furnace recipes", - "allay:furnacerecipe.loading": "Loading furnace recipes...", "allay:gui.chunk": "Chunk", "allay:gui.chunk.label": "Loaded Chunk Count: %1", "allay:gui.console": "Console", @@ -110,6 +108,10 @@ "allay:plugin.loading": "Loading plugin %1", "allay:recipe.loaded": "Loaded %1 recipes", "allay:recipe.loading": "Loading recipes...", + "allay:recipe.furnace.loading": "Loading furnace recipes...", + "allay:recipe.furnace.loaded": "Loaded %1 furnace recipes", + "allay:recipe.potionmix.loading": "Loading potion mix recipes...", + "allay:recipe.potionmix.loaded": "Loaded %1 potion mix recipes", "allay:server.is_dev_version": "§eYou are running a development version. The development version may have unexpected bugs, please do not use it in a production environment!", "allay:server.starting": "Starting up Minecraft: Bedrock Edition server, version §a%1§r (protocol version §a%2§r)", "allay:server.stopped": "Server stopped", diff --git a/data/resources/unpacked/lang_raw/allay/en_US.json b/data/resources/unpacked/lang_raw/allay/en_US.json index 94f5f40a7d..ad981d3c25 100644 --- a/data/resources/unpacked/lang_raw/allay/en_US.json +++ b/data/resources/unpacked/lang_raw/allay/en_US.json @@ -23,8 +23,10 @@ "creativeitem.loaded": "Creative items is loaded", "recipe.loading": "Loading recipes...", "recipe.loaded": "Loaded %1 recipes", - "furnacerecipe.loading": "Loading furnace recipes...", - "furnacerecipe.loaded": "Loaded %1 furnace recipes", + "recipe.furnace.loading": "Loading furnace recipes...", + "recipe.furnace.loaded": "Loaded %1 furnace recipes", + "recipe.potionmix.loading": "Loading potion mix recipes...", + "recipe.potionmix.loaded": "Loaded %1 potion mix recipes", "command.generic.sender.notServer": "This command can only be executed by the server!", "command.generic.sender.notPlayer": "This command can only be executed by a player!", "command.generic.sender.notEntity": "This command can only be executed by an entity!", diff --git a/data/resources/unpacked/lang_raw/allay/zh_CN.json b/data/resources/unpacked/lang_raw/allay/zh_CN.json index 9ed004e461..bf9101fd0a 100644 --- a/data/resources/unpacked/lang_raw/allay/zh_CN.json +++ b/data/resources/unpacked/lang_raw/allay/zh_CN.json @@ -24,8 +24,10 @@ "creativeitem.loaded": "加载创造模式物品完成", "recipe.loading": "正在加载配方...", "recipe.loaded": "加载完成 %1 个配方", - "furnacerecipe.loading": "正在加载熔炉配方...", - "furnacerecipe.loaded": "加载完成 %1 个熔炉配方", + "recipe.furnace.loading": "正在加载熔炉配方...", + "recipe.furnace.loaded": "加载完成 %1 个熔炉配方", + "recipe.potionmix.loading": "加载药水混合食谱。..", + "recipe.potionmix.loaded": "加载 % 1药水混合配方", "command.generic.sender.notServer": "这个命令只能被服务器执行!", "command.generic.sender.notPlayer": "这个命令只能被玩家执行!", "command.generic.sender.notEntity": "这个命令只能被实体执行!", diff --git a/server/src/main/java/org/allaymc/server/Allay.java b/server/src/main/java/org/allaymc/server/Allay.java index a200978d7f..d2042ea107 100644 --- a/server/src/main/java/org/allaymc/server/Allay.java +++ b/server/src/main/java/org/allaymc/server/Allay.java @@ -223,6 +223,7 @@ private static void initRegistries() { // Recipe Registries.RECIPES = IntMappedRegistry.create(new RecipeRegistryLoader()); Registries.FURNACE_RECIPES = SimpleMappedRegistry.create(new FurnaceRecipeRegistryLoader()); + Registries.POTION_MIX_RECIPES = SimpleMappedRegistry.create(new PotionMixRecipeRegistryLoader()); // Pack Registries.PACKS = SimpleMappedRegistry.create(new PackRegistryLoader()); diff --git a/server/src/main/java/org/allaymc/server/block/component/BlockBeaconBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/block/component/BlockBeaconBaseComponentImpl.java index 7a5b3a6cda..652bb9ba63 100644 --- a/server/src/main/java/org/allaymc/server/block/component/BlockBeaconBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/block/component/BlockBeaconBaseComponentImpl.java @@ -26,7 +26,7 @@ public boolean onInteract(ItemStack itemStack, Dimension dimension, PlayerIntera if (player.isSneaking()) { return false; } - + var beaconContainer = player.getContainer(FullContainerType.BEACON); beaconContainer.setBlockPos(new Position3i(interactInfo.clickedBlockPos(), interactInfo.player().getDimension())); beaconContainer.addViewer(player); diff --git a/server/src/main/java/org/allaymc/server/block/component/BlockBrewingStandBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/block/component/BlockBrewingStandBaseComponentImpl.java new file mode 100644 index 0000000000..f5df6d77d1 --- /dev/null +++ b/server/src/main/java/org/allaymc/server/block/component/BlockBrewingStandBaseComponentImpl.java @@ -0,0 +1,35 @@ +package org.allaymc.server.block.component; + +import org.allaymc.api.block.BlockBehavior; +import org.allaymc.api.block.dto.PlayerInteractInfo; +import org.allaymc.api.block.type.BlockType; +import org.allaymc.api.container.FullContainerType; +import org.allaymc.api.item.ItemStack; +import org.allaymc.api.math.position.Position3i; +import org.allaymc.api.world.Dimension; + +/** + * @author IWareQ + */ +public class BlockBrewingStandBaseComponentImpl extends BlockBaseComponentImpl { + public BlockBrewingStandBaseComponentImpl(BlockType blockType) { + super(blockType); + } + + @Override + public boolean onInteract(ItemStack itemStack, Dimension dimension, PlayerInteractInfo interactInfo) { + if (super.onInteract(itemStack, dimension, interactInfo)) { + return true; + } + + var player = interactInfo.player(); + if (player.isSneaking()) { + return false; + } + + var brewingStandContainer = player.getContainer(FullContainerType.BREWING_STAND); + brewingStandContainer.setBlockPos(new Position3i(interactInfo.clickedBlockPos(), interactInfo.player().getDimension())); + brewingStandContainer.addViewer(player); + return true; + } +} diff --git a/server/src/main/java/org/allaymc/server/block/impl/BlockBrewingStandBehaviorImpl.java b/server/src/main/java/org/allaymc/server/block/impl/BlockBrewingStandBehaviorImpl.java index ec3a9843db..d3df12d6d8 100644 --- a/server/src/main/java/org/allaymc/server/block/impl/BlockBrewingStandBehaviorImpl.java +++ b/server/src/main/java/org/allaymc/server/block/impl/BlockBrewingStandBehaviorImpl.java @@ -1,14 +1,19 @@ package org.allaymc.server.block.impl; +import lombok.experimental.Delegate; +import org.allaymc.api.block.component.BlockEntityHolderComponent; import org.allaymc.api.block.interfaces.BlockBrewingStandBehavior; +import org.allaymc.api.blockentity.interfaces.BlockEntityBrewingStand; import org.allaymc.api.component.interfaces.Component; import org.allaymc.server.component.interfaces.ComponentProvider; import java.util.List; public class BlockBrewingStandBehaviorImpl extends BlockBehaviorImpl implements BlockBrewingStandBehavior { - public BlockBrewingStandBehaviorImpl( - List> componentProviders) { + @Delegate + protected BlockEntityHolderComponent blockEntityHolderComponent; + + public BlockBrewingStandBehaviorImpl(List> componentProviders) { super(componentProviders); } } diff --git a/server/src/main/java/org/allaymc/server/block/type/BlockTypeInitializer.java b/server/src/main/java/org/allaymc/server/block/type/BlockTypeInitializer.java index c199e2d3a6..30f7b5e193 100644 --- a/server/src/main/java/org/allaymc/server/block/type/BlockTypeInitializer.java +++ b/server/src/main/java/org/allaymc/server/block/type/BlockTypeInitializer.java @@ -1118,4 +1118,14 @@ public static void initBeacon() { .setBaseComponentSupplier(BlockBeaconBaseComponentImpl::new) .build(); } + + public static void initBrewingStand() { + BlockTypes.BREWING_STAND = AllayBlockType + .builder(BlockBrewingStandBehaviorImpl.class) + .vanillaBlock(BlockId.BREWING_STAND) + .bindBlockEntity(BlockEntityTypes.BREWING_STAND) + .setBaseComponentSupplier(BlockBrewingStandBaseComponentImpl::new) + .setProperties(BlockPropertyTypes.BREWING_STAND_SLOT_A_BIT, BlockPropertyTypes.BREWING_STAND_SLOT_B_BIT, BlockPropertyTypes.BREWING_STAND_SLOT_C_BIT) + .build(); + } } diff --git a/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityBrewingStandBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityBrewingStandBaseComponentImpl.java new file mode 100644 index 0000000000..41734153a0 --- /dev/null +++ b/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityBrewingStandBaseComponentImpl.java @@ -0,0 +1,180 @@ +package org.allaymc.server.blockentity.component; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import org.allaymc.api.block.property.type.BlockPropertyType; +import org.allaymc.api.blockentity.component.BlockEntityBrewingStandBaseComponent; +import org.allaymc.api.blockentity.component.BlockEntityContainerHolderComponent; +import org.allaymc.api.blockentity.initinfo.BlockEntityInitInfo; +import org.allaymc.api.blockentity.interfaces.BlockEntityBrewingStand; +import org.allaymc.api.container.impl.BrewingStandContainer; +import org.allaymc.api.item.ItemStack; +import org.allaymc.api.item.interfaces.ItemAirStack; +import org.allaymc.api.item.recipe.impl.PotionMixRecipe; +import org.allaymc.api.item.type.ItemTypes; +import org.allaymc.api.registry.Registries; +import org.allaymc.api.world.Sound; +import org.allaymc.server.component.annotation.ComponentObject; +import org.allaymc.server.component.annotation.Dependency; +import org.allaymc.server.component.annotation.OnInitFinish; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.protocol.bedrock.packet.ContainerSetDataPacket; + +/** + * @author IWareQ + */ +@Getter +@Setter +public class BlockEntityBrewingStandBaseComponentImpl extends BlockEntityBaseComponentImpl implements BlockEntityBrewingStandBaseComponent { + protected static final String TAG_COOK_TIME = "CookTime"; + protected static final String TAG_FUEL_AMOUNT = "FuelAmount"; + protected static final String TAG_FUEL_TOTAL = "FuelTotal"; + + protected static final int MAX_BREW_TIME = 400; + + @Dependency + @Setter(AccessLevel.NONE) + protected BlockEntityContainerHolderComponent containerHolderComponent; + @ComponentObject + protected BlockEntityBrewingStand thisBlockEntity; + + protected int brewTime; + protected int fuelAmount; + protected int fuelTotal; + + public BlockEntityBrewingStandBaseComponentImpl(BlockEntityInitInfo initInfo) { + super(initInfo); + } + + @OnInitFinish + @Override + public void onInitFinish(BlockEntityInitInfo initInfo) { + super.onInitFinish(initInfo); + BrewingStandContainer container = containerHolderComponent.getContainer(); + for (int i = 1; i < 4; i++) { + int finalI = i; + container.addOnSlotChangeListener(finalI, item -> { + var currentBlockState = getDimension().getBlockState(position); + var values = currentBlockState.getBlockType().getProperties().values(); + currentBlockState = currentBlockState.setProperty(values.toArray(new BlockPropertyType[0])[finalI - 1], item != ItemAirStack.AIR_STACK); + getDimension().setBlockState( + position, currentBlockState, + 0, true, true, false + ); + }); + } + + container.addOnSlotChangeListener(BrewingStandContainer.REAGENT_SLOT, item -> { + brewTime = item == ItemAirStack.AIR_STACK ? 0 : MAX_BREW_TIME; + sendContainerData(true); + }); + } + + @Override + public void tick(long currentTick) { + tick0(); + sendContainerData(brewTime % 40 == 0); + } + + protected void tick0() { + if (!checkFuel()) { + return; + } + + BrewingStandContainer container = containerHolderComponent.getContainer(); + var reagent = container.getReagent(); + var a = findRecipe(container.getResult(0), reagent); + var b = findRecipe(container.getResult(1), reagent); + var c = findRecipe(container.getResult(2), reagent); + + if (a == null && b == null && c == null) { + brewTime = 0; + return; + } + + if (brewTime > 0) { + brewTime--; + return; + } + + if (container.isEmpty(BrewingStandContainer.REAGENT_SLOT)) { + return; + } + + if (a != null) { + container.setResult(0, a.getOutput().copy()); + } + if (b != null) { + container.setResult(1, b.getOutput().copy()); + } + if (c != null) { + container.setResult(2, c.getOutput().copy()); + } + + if (reagent.getCount() > 1) { + reagent.reduceCount(1); + container.notifySlotChange(BrewingStandContainer.REAGENT_SLOT); + } else { + container.clearSlot(BrewingStandContainer.REAGENT_SLOT); + } + + fuelAmount--; + getDimension().addSound(position, Sound.RANDOM_POTION_BREWED); + } + + protected boolean checkFuel() { + if (fuelAmount > 0) { + return true; + } + + BrewingStandContainer container = containerHolderComponent.getContainer(); + + var fuel = container.getFuel(); + if (fuel.getItemType() != ItemTypes.BLAZE_POWDER) { + return false; + } + + if (fuel.getCount() > 1) { + fuel.reduceCount(1); + container.notifySlotChange(BrewingStandContainer.FUEL_SLOT); + } else { + container.clearSlot(BrewingStandContainer.FUEL_SLOT); + } + + fuelAmount = 20; + fuelTotal = fuelAmount; + return true; + } + + protected PotionMixRecipe findRecipe(ItemStack ingredient, ItemStack reagent) { + return Registries.POTION_MIX_RECIPES.get(PotionMixRecipe.buildIdentifier(ingredient, reagent)); + } + + protected void sendContainerData(boolean sendBrewTime) { + var container = containerHolderComponent.getContainer(); + if (sendBrewTime) { + container.sendContainerData(ContainerSetDataPacket.BREWING_STAND_BREW_TIME, brewTime); + } + container.sendContainerData(ContainerSetDataPacket.BREWING_STAND_FUEL_AMOUNT, fuelAmount); + container.sendContainerData(ContainerSetDataPacket.BREWING_STAND_FUEL_TOTAL, fuelTotal); + } + + @Override + public NbtMap saveNBT() { + return super.saveNBT() + .toBuilder() + .putShort(TAG_COOK_TIME, (short) brewTime) + .putShort(TAG_FUEL_AMOUNT, (short) fuelAmount) + .putShort(TAG_FUEL_TOTAL, (short) fuelTotal) + .build(); + } + + @Override + public void loadNBT(NbtMap nbt) { + super.loadNBT(nbt); + nbt.listenForShort(TAG_COOK_TIME, value -> brewTime = value); + nbt.listenForShort(TAG_FUEL_AMOUNT, value -> fuelAmount = value); + nbt.listenForShort(TAG_FUEL_TOTAL, value -> fuelTotal = value); + } +} diff --git a/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityEnchantTableBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityEnchantTableBaseComponentImpl.java index 76843382c6..743e521eb4 100644 --- a/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityEnchantTableBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityEnchantTableBaseComponentImpl.java @@ -29,6 +29,6 @@ public NbtMap saveNBT() { @Override public void loadNBT(NbtMap nbt) { super.loadNBT(nbt); - nbt.listenForFloat("rott", value -> bookRot = value); + nbt.listenForFloat(TAG_ROTT, value -> bookRot = value); } } diff --git a/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityBlastFurnaceBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityBlastFurnaceBaseComponentImpl.java index e0341eb1c4..0e277a58cb 100644 --- a/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityBlastFurnaceBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityBlastFurnaceBaseComponentImpl.java @@ -3,7 +3,7 @@ import org.allaymc.api.block.type.BlockType; import org.allaymc.api.block.type.BlockTypes; import org.allaymc.api.blockentity.initinfo.BlockEntityInitInfo; -import org.allaymc.api.item.recipe.FurnaceRecipe; +import org.allaymc.api.item.recipe.impl.FurnaceRecipe; /** * @author daoge_cmd diff --git a/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityFurnaceBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityFurnaceBaseComponentImpl.java index a94a473865..bb0d47434f 100644 --- a/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityFurnaceBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityFurnaceBaseComponentImpl.java @@ -15,7 +15,7 @@ import org.allaymc.api.eventbus.event.container.FurnaceSmeltEvent; import org.allaymc.api.item.ItemStack; import org.allaymc.api.item.interfaces.ItemAirStack; -import org.allaymc.api.item.recipe.FurnaceRecipe; +import org.allaymc.api.item.recipe.impl.FurnaceRecipe; import org.allaymc.api.item.recipe.input.FurnaceInput; import org.allaymc.api.item.type.ItemTypes; import org.allaymc.api.registry.Registries; @@ -242,7 +242,6 @@ public boolean sendToClient() { protected void sendFurnaceContainerData() { var container = containerHolderComponent.getContainer(); - if (container.getViewers().isEmpty()) return; // NOTICE: This is not an error, ask mojang for the reason why you should "/ getIdealSpeed()" container.sendContainerData(ContainerSetDataPacket.FURNACE_TICK_COUNT, (int) (cookTime / getIdealSpeed())); container.sendContainerData(ContainerSetDataPacket.FURNACE_LIT_TIME, burnTime); diff --git a/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntitySmokerFurnaceBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntitySmokerFurnaceBaseComponentImpl.java index e39ebe1ecd..2b9ca52b9f 100644 --- a/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntitySmokerFurnaceBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntitySmokerFurnaceBaseComponentImpl.java @@ -3,7 +3,7 @@ import org.allaymc.api.block.type.BlockType; import org.allaymc.api.block.type.BlockTypes; import org.allaymc.api.blockentity.initinfo.BlockEntityInitInfo; -import org.allaymc.api.item.recipe.FurnaceRecipe; +import org.allaymc.api.item.recipe.impl.FurnaceRecipe; /** * @author daoge_cmd diff --git a/server/src/main/java/org/allaymc/server/blockentity/impl/BlockEntityBrewingStandImpl.java b/server/src/main/java/org/allaymc/server/blockentity/impl/BlockEntityBrewingStandImpl.java new file mode 100644 index 0000000000..b4da6842b1 --- /dev/null +++ b/server/src/main/java/org/allaymc/server/blockentity/impl/BlockEntityBrewingStandImpl.java @@ -0,0 +1,25 @@ +package org.allaymc.server.blockentity.impl; + +import lombok.experimental.Delegate; +import org.allaymc.api.blockentity.component.BlockEntityBrewingStandBaseComponent; +import org.allaymc.api.blockentity.initinfo.BlockEntityInitInfo; +import org.allaymc.api.blockentity.interfaces.BlockEntityBrewingStand; +import org.allaymc.api.component.interfaces.Component; +import org.allaymc.server.component.interfaces.ComponentProvider; + +import java.util.List; + +/** + * @author IWareQ + */ +public class BlockEntityBrewingStandImpl extends BlockEntityImpl implements BlockEntityBrewingStand { + public BlockEntityBrewingStandImpl(BlockEntityInitInfo initInfo, List> componentProviders) { + super(initInfo, componentProviders); + } + + @Delegate + @Override + public BlockEntityBrewingStandBaseComponent getBaseComponent() { + return (BlockEntityBrewingStandBaseComponent) super.getBaseComponent(); + } +} diff --git a/server/src/main/java/org/allaymc/server/blockentity/type/BlockEntityTypeInitializer.java b/server/src/main/java/org/allaymc/server/blockentity/type/BlockEntityTypeInitializer.java index e5c2320199..bc3758e736 100644 --- a/server/src/main/java/org/allaymc/server/blockentity/type/BlockEntityTypeInitializer.java +++ b/server/src/main/java/org/allaymc/server/blockentity/type/BlockEntityTypeInitializer.java @@ -102,4 +102,13 @@ public static void initBeacon() { .addComponent(BlockEntityBeaconBaseComponentImpl::new, BlockEntityBeaconBaseComponentImpl.class) .build(); } + + public static void initBrewingStand() { + BlockEntityTypes.BREWING_STAND = AllayBlockEntityType + .builder(BlockEntityBrewingStandImpl.class) + .name(BlockEntityId.BREWING_STAND) + .addComponent(BlockEntityBrewingStandBaseComponentImpl::new, BlockEntityBrewingStandBaseComponentImpl.class) + .addComponent(() -> new BlockEntityContainerHolderComponentImpl(BrewingStandContainer::new), BlockEntityContainerHolderComponentImpl.class) + .build(); + } } diff --git a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java index 37450dab0b..e1bcd52a8a 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java @@ -439,15 +439,19 @@ public static CraftingDataPacket getCraftingDataPacket() { CRAFTING_DATA_PACKET = new CraftingDataPacket(); CRAFTING_DATA_PACKET.getCraftingData().addAll( Registries.RECIPES.getContent().values().stream() - .map(Recipe::toNetworkRecipeData) + .map(Recipe::toNetworkData) .toList() ); CRAFTING_DATA_PACKET.getCraftingData().addAll( Registries.FURNACE_RECIPES.getContent().values().stream() - .map(Recipe::toNetworkRecipeData) + .map(Recipe::toNetworkData) + .toList() + ); + CRAFTING_DATA_PACKET.getPotionMixData().addAll( + Registries.POTION_MIX_RECIPES.getContent().values().stream() + .map(Recipe::toNetworkData) .toList() ); - // TODO: packet.getPotionMixData().addAll(); // TODO: packet.getContainerMixData().addAll(); // TODO: packet.getMaterialReducers().addAll(); CRAFTING_DATA_PACKET.setCleanRecipes(true); diff --git a/server/src/main/java/org/allaymc/server/registry/loader/FurnaceRecipeRegistryLoader.java b/server/src/main/java/org/allaymc/server/registry/loader/FurnaceRecipeRegistryLoader.java index 8bbed1aa9e..1d8c73dc6e 100644 --- a/server/src/main/java/org/allaymc/server/registry/loader/FurnaceRecipeRegistryLoader.java +++ b/server/src/main/java/org/allaymc/server/registry/loader/FurnaceRecipeRegistryLoader.java @@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.allaymc.api.i18n.I18n; import org.allaymc.api.i18n.TrKeys; -import org.allaymc.api.item.recipe.FurnaceRecipe; +import org.allaymc.api.item.recipe.impl.FurnaceRecipe; import org.allaymc.api.registry.RegistryLoader; import org.allaymc.api.utils.Identifier; import org.allaymc.api.utils.Utils; @@ -22,7 +22,7 @@ public class FurnaceRecipeRegistryLoader implements RegistryLoader> { @Override public Map load(Void $) { - log.info(I18n.get().tr(TrKeys.A_FURNACERECIPE_LOADING)); + log.info(I18n.get().tr(TrKeys.A_RECIPE_FURNACE_LOADING)); var furnaceRecipes = new Object2ObjectOpenHashMap(); var stream = Objects.requireNonNull(Utils.getResource("recipes.json")); @@ -34,7 +34,7 @@ public Map load(Void $) { furnaceRecipes.put(recipe.getIdentifier(), recipe); } - log.info(I18n.get().tr(TrKeys.A_FURNACERECIPE_LOADED, furnaceRecipes.size())); + log.info(I18n.get().tr(TrKeys.A_RECIPE_FURNACE_LOADED, furnaceRecipes.size())); return furnaceRecipes; } diff --git a/server/src/main/java/org/allaymc/server/registry/loader/PotionMixRecipeRegistryLoader.java b/server/src/main/java/org/allaymc/server/registry/loader/PotionMixRecipeRegistryLoader.java new file mode 100644 index 0000000000..e356dc7726 --- /dev/null +++ b/server/src/main/java/org/allaymc/server/registry/loader/PotionMixRecipeRegistryLoader.java @@ -0,0 +1,49 @@ +package org.allaymc.server.registry.loader; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import lombok.extern.slf4j.Slf4j; +import org.allaymc.api.i18n.I18n; +import org.allaymc.api.i18n.TrKeys; +import org.allaymc.api.item.recipe.impl.PotionMixRecipe; +import org.allaymc.api.registry.RegistryLoader; +import org.allaymc.api.utils.Identifier; +import org.allaymc.api.utils.Utils; + +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * @author IWareQ + */ +@Slf4j +public class PotionMixRecipeRegistryLoader implements RegistryLoader> { + @Override + public Map load(Void $) { + log.info(TrKeys.A_RECIPE_POTIONMIX_LOADING); + var stream = Objects.requireNonNull(Utils.getResource("recipes.json")); + + var obj = JsonParser.parseReader(new InputStreamReader(stream)).getAsJsonObject(); + var potionMixRecipes = obj.getAsJsonArray("potionMixes"); + + Map recipes = new HashMap<>(potionMixRecipes.size()); + for (var potionMixRecipe : potionMixRecipes) { + var recipe = parseRecipe(potionMixRecipe.getAsJsonObject()); + recipes.put(recipe.getIdentifier(), recipe); + } + + log.info(I18n.get().tr(TrKeys.A_RECIPE_POTIONMIX_LOADED, recipes.size())); + return recipes; + } + + protected PotionMixRecipe parseRecipe(JsonObject obj) { + return PotionMixRecipe + .builder() + .ingredient(RecipeJsonUtils.parseDefaultItemDescriptor(obj.getAsJsonObject("input"))) + .output(RecipeJsonUtils.parseDefaultItemDescriptor(obj.getAsJsonObject("output"))) + .reagent(RecipeJsonUtils.parseDefaultItemDescriptor(obj.getAsJsonObject("reagent"))) + .build(); + } +} diff --git a/server/src/main/java/org/allaymc/server/registry/loader/RecipeRegistryLoader.java b/server/src/main/java/org/allaymc/server/registry/loader/RecipeRegistryLoader.java index e88bbbc993..c68e6e1509 100644 --- a/server/src/main/java/org/allaymc/server/registry/loader/RecipeRegistryLoader.java +++ b/server/src/main/java/org/allaymc/server/registry/loader/RecipeRegistryLoader.java @@ -10,8 +10,8 @@ import org.allaymc.api.item.ItemStack; import org.allaymc.api.item.descriptor.ItemDescriptor; import org.allaymc.api.item.recipe.NetworkRecipe; -import org.allaymc.api.item.recipe.ShapedRecipe; -import org.allaymc.api.item.recipe.ShapelessRecipe; +import org.allaymc.api.item.recipe.impl.ShapedRecipe; +import org.allaymc.api.item.recipe.impl.ShapelessRecipe; import org.allaymc.api.registry.RegistryLoader; import org.allaymc.api.utils.Identifier; import org.allaymc.api.utils.Utils; diff --git a/server/src/test/java/org/allaymc/api/item/recipe/RecipeTest.java b/server/src/test/java/org/allaymc/api/item/recipe/RecipeTest.java index 52181d168c..f83fee4be6 100644 --- a/server/src/test/java/org/allaymc/api/item/recipe/RecipeTest.java +++ b/server/src/test/java/org/allaymc/api/item/recipe/RecipeTest.java @@ -7,6 +7,9 @@ import org.allaymc.api.item.interfaces.ItemAirStack; import org.allaymc.api.item.interfaces.ItemDiamondStack; import org.allaymc.api.item.interfaces.ItemGrassBlockStack; +import org.allaymc.api.item.recipe.impl.FurnaceRecipe; +import org.allaymc.api.item.recipe.impl.ShapedRecipe; +import org.allaymc.api.item.recipe.impl.ShapelessRecipe; import org.allaymc.api.item.recipe.input.CraftingInput; import org.allaymc.api.item.recipe.input.FurnaceInput; import org.allaymc.api.utils.Identifier;