-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixed bugs / code adjusted to match vanilla: BaseContainerBlockEntity.readNbt: recreate item list before reading
- Loading branch information
Showing
37 changed files
with
908 additions
and
690 deletions.
There are no files selected for viewing
46 changes: 46 additions & 0 deletions
46
common/src/main/java/juuxel/adorn/block/AdornBlockEntities.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package juuxel.adorn.block; | ||
|
||
import juuxel.adorn.block.entity.AdornBlockEntityType; | ||
import juuxel.adorn.block.entity.BrewerBlockEntity; | ||
import juuxel.adorn.block.entity.DrawerBlockEntity; | ||
import juuxel.adorn.block.entity.KitchenCupboardBlockEntity; | ||
import juuxel.adorn.block.entity.KitchenSinkBlockEntity; | ||
import juuxel.adorn.block.entity.ShelfBlockEntity; | ||
import juuxel.adorn.block.entity.TradingStationBlockEntity; | ||
import juuxel.adorn.lib.registry.Registered; | ||
import juuxel.adorn.lib.registry.Registrar; | ||
import juuxel.adorn.lib.registry.RegistrarFactory; | ||
import juuxel.adorn.platform.PlatformBridges; | ||
import net.minecraft.block.Block; | ||
import net.minecraft.block.entity.BlockEntity; | ||
import net.minecraft.block.entity.BlockEntityType; | ||
import net.minecraft.block.entity.BlockEntityType.BlockEntityFactory; | ||
import net.minecraft.registry.RegistryKeys; | ||
|
||
import java.util.function.Supplier; | ||
|
||
public final class AdornBlockEntities { | ||
public static final Registrar<BlockEntityType<?>> BLOCK_ENTITIES = RegistrarFactory.get().create(RegistryKeys.BLOCK_ENTITY_TYPE); | ||
|
||
public static final Registered<BlockEntityType<ShelfBlockEntity>> SHELF = register("shelf", ShelfBlockEntity::new, ShelfBlock.class); | ||
public static final Registered<BlockEntityType<DrawerBlockEntity>> DRAWER = register("drawer", DrawerBlockEntity::new, DrawerBlock.class); | ||
public static final Registered<BlockEntityType<KitchenCupboardBlockEntity>> KITCHEN_CUPBOARD = | ||
register("kitchen_cupboard", KitchenCupboardBlockEntity::new, KitchenCupboardBlock.class); | ||
public static final Registered<BlockEntityType<KitchenSinkBlockEntity>> KITCHEN_SINK = | ||
register("kitchen_sink", PlatformBridges.Companion.getBlockEntities()::createKitchenSink, KitchenSinkBlock.class); | ||
public static final Registered<BlockEntityType<TradingStationBlockEntity>> TRADING_STATION = | ||
register("trading_station", TradingStationBlockEntity::new, AdornBlocks.INSTANCE::getTRADING_STATION); | ||
public static final Registered<BlockEntityType<BrewerBlockEntity>> BREWER = | ||
register("brewer", PlatformBridges.Companion.getBlockEntities()::createBrewer, AdornBlocks.INSTANCE::getBREWER); | ||
|
||
private static <E extends BlockEntity> Registered<BlockEntityType<E>> register(String name, BlockEntityFactory<E> factory, Supplier<? extends Block> block) { | ||
return BLOCK_ENTITIES.register(name, () -> BlockEntityType.Builder.create(factory, block.get()).build(null)); | ||
} | ||
|
||
private static <E extends BlockEntity> Registered<BlockEntityType<E>> register(String name, BlockEntityFactory<E> factory, Class<? extends Block> blockClass) { | ||
return BLOCK_ENTITIES.register(name, () -> new AdornBlockEntityType<>(factory, blockClass::isInstance)); | ||
} | ||
|
||
public static void init() { | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
common/src/main/java/juuxel/adorn/block/entity/AdornBlockEntityType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package juuxel.adorn.block.entity; | ||
|
||
import net.minecraft.block.Block; | ||
import net.minecraft.block.BlockState; | ||
import net.minecraft.block.entity.BlockEntity; | ||
import net.minecraft.block.entity.BlockEntityType; | ||
|
||
import java.util.Set; | ||
import java.util.function.Predicate; | ||
|
||
public final class AdornBlockEntityType<E extends BlockEntity> extends BlockEntityType<E> { | ||
private final Predicate<Block> blockPredicate; | ||
|
||
public AdornBlockEntityType(BlockEntityFactory<? extends E> factory, Predicate<Block> blockPredicate) { | ||
super(factory, Set.of(), null); | ||
this.blockPredicate = blockPredicate; | ||
} | ||
|
||
@Override | ||
public boolean supports(BlockState state) { | ||
return blockPredicate.test(state.getBlock()); | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
common/src/main/java/juuxel/adorn/block/entity/BaseContainerBlockEntity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package juuxel.adorn.block.entity; | ||
|
||
import net.minecraft.block.BlockState; | ||
import net.minecraft.block.entity.BlockEntityType; | ||
import net.minecraft.block.entity.LootableContainerBlockEntity; | ||
import net.minecraft.inventory.Inventories; | ||
import net.minecraft.item.ItemStack; | ||
import net.minecraft.nbt.NbtCompound; | ||
import net.minecraft.text.Text; | ||
import net.minecraft.util.collection.DefaultedList; | ||
import net.minecraft.util.math.BlockPos; | ||
|
||
/** | ||
* A container block entity that might not have a menu. | ||
* This class handles the serialisation and the container logic. | ||
*/ | ||
public abstract class BaseContainerBlockEntity extends LootableContainerBlockEntity { | ||
private final int size; | ||
private DefaultedList<ItemStack> items; | ||
|
||
public BaseContainerBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state, int size) { | ||
super(type, pos, state); | ||
items = DefaultedList.ofSize(size, ItemStack.EMPTY); | ||
this.size = size; | ||
} | ||
|
||
@Override | ||
protected void writeNbt(NbtCompound nbt) { | ||
super.writeNbt(nbt); | ||
if (!writeLootTable(nbt)) { | ||
Inventories.writeNbt(nbt, items); | ||
} | ||
} | ||
|
||
@Override | ||
public void readNbt(NbtCompound nbt) { | ||
super.readNbt(nbt); | ||
items = DefaultedList.ofSize(size, ItemStack.EMPTY); | ||
if (!readLootTable(nbt)) { | ||
Inventories.readNbt(nbt, items); | ||
} | ||
} | ||
|
||
@Override | ||
protected DefaultedList<ItemStack> method_11282() { | ||
return items; | ||
} | ||
|
||
@Override | ||
protected void setInvStackList(DefaultedList<ItemStack> list) { | ||
items = list; | ||
} | ||
|
||
@Override | ||
public int size() { | ||
return size; | ||
} | ||
|
||
@Override | ||
protected Text getContainerName() { | ||
return getCachedState().getBlock().getName(); | ||
} | ||
} |
193 changes: 193 additions & 0 deletions
193
common/src/main/java/juuxel/adorn/block/entity/BrewerBlockEntity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
package juuxel.adorn.block.entity; | ||
|
||
import juuxel.adorn.block.AdornBlockEntities; | ||
import juuxel.adorn.block.BrewerBlock; | ||
import juuxel.adorn.item.AdornItems; | ||
import juuxel.adorn.menu.BrewerMenu; | ||
import juuxel.adorn.recipe.AdornRecipes; | ||
import juuxel.adorn.recipe.BrewerInventory; | ||
import juuxel.adorn.recipe.FluidBrewingRecipe; | ||
import net.minecraft.block.BlockState; | ||
import net.minecraft.entity.player.PlayerInventory; | ||
import net.minecraft.inventory.SidedInventory; | ||
import net.minecraft.item.ItemStack; | ||
import net.minecraft.menu.Menu; | ||
import net.minecraft.menu.property.PropertyDelegate; | ||
import net.minecraft.nbt.NbtCompound; | ||
import net.minecraft.recipe.RecipeEntry; | ||
import net.minecraft.util.ItemScatterer; | ||
import net.minecraft.util.math.BlockPos; | ||
import net.minecraft.util.math.Direction; | ||
import net.minecraft.util.math.MathHelper; | ||
import net.minecraft.world.World; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public abstract class BrewerBlockEntity extends BaseContainerBlockEntity implements SidedInventory, BrewerInventory { | ||
private static final String NBT_PROGRESS = "Progress"; | ||
public static final int CONTAINER_SIZE = 4; | ||
public static final int INPUT_SLOT = 0; | ||
public static final int LEFT_INGREDIENT_SLOT = 1; | ||
public static final int RIGHT_INGREDIENT_SLOT = 2; | ||
public static final int FLUID_CONTAINER_SLOT = 3; | ||
public static final int MAX_PROGRESS = 200; | ||
public static final int FLUID_CAPACITY_IN_BUCKETS = 2; | ||
|
||
private int progress = 0; | ||
private final PropertyDelegate propertyDelegate = new PropertyDelegate() { | ||
@Override | ||
public int get(int index) { | ||
return switch (index) { | ||
case 0 -> progress; | ||
default -> throw new IllegalArgumentException("Unknown property: " + index); | ||
}; | ||
} | ||
|
||
@Override | ||
public void set(int index, int value) { | ||
switch (index) { | ||
case 0 -> progress = value; | ||
default -> throw new IllegalArgumentException("Unknown property: " + index); | ||
} | ||
} | ||
|
||
@Override | ||
public int size() { | ||
return 1; | ||
} | ||
}; | ||
|
||
public BrewerBlockEntity(BlockPos pos, BlockState state) { | ||
super(AdornBlockEntities.BREWER.get(), pos, state, CONTAINER_SIZE); | ||
} | ||
|
||
@Override | ||
protected Menu createMenu(int syncId, PlayerInventory inv) { | ||
return new BrewerMenu(syncId, inv, this, propertyDelegate, getFluidReference()); | ||
} | ||
|
||
@Override | ||
protected void writeNbt(NbtCompound nbt) { | ||
super.writeNbt(nbt); | ||
nbt.putInt(NBT_PROGRESS, progress); | ||
} | ||
|
||
@Override | ||
public void readNbt(NbtCompound nbt) { | ||
super.readNbt(nbt); | ||
progress = nbt.getInt(NBT_PROGRESS); | ||
} | ||
|
||
@Override | ||
public int[] getAvailableSlots(Direction side) { | ||
var facing = getCachedState().get(BrewerBlock.Companion.getFACING()); | ||
|
||
if (side == facing.rotateYClockwise()) { | ||
return new int[] { LEFT_INGREDIENT_SLOT }; | ||
} else if (side == facing.rotateYCounterclockwise()) { | ||
return new int[] { RIGHT_INGREDIENT_SLOT }; | ||
} else if (side == facing.getOpposite()) { | ||
return new int[] { FLUID_CONTAINER_SLOT }; | ||
} else if (side == Direction.UP) { | ||
return new int[] { INPUT_SLOT }; | ||
} else if (side == Direction.DOWN) { | ||
return new int[] { INPUT_SLOT, FLUID_CONTAINER_SLOT }; | ||
} else { | ||
return new int[0]; | ||
} | ||
} | ||
|
||
@Override | ||
public boolean isValid(int slot, ItemStack stack) { | ||
if (slot == INPUT_SLOT && !(stack.isOf(AdornItems.INSTANCE.getMUG()) && getStack(slot).isEmpty())) return false; | ||
if (slot == FLUID_CONTAINER_SLOT && !getStack(slot).isEmpty()) return false; | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean canInsert(int slot, ItemStack stack, @Nullable Direction dir) { | ||
return dir != Direction.DOWN && isValid(slot, stack); | ||
} | ||
|
||
@Override | ||
public boolean canExtract(int slot, ItemStack stack, Direction dir) { | ||
return dir == Direction.DOWN && (slot != FLUID_CONTAINER_SLOT || canExtractFluidContainer()); | ||
} | ||
|
||
public int calculateComparatorOutput() { | ||
// If brewing has finished | ||
var mugStack = getStack(INPUT_SLOT); | ||
if (!mugStack.isEmpty() && !mugStack.isOf(AdornItems.INSTANCE.getMUG())) { | ||
return 15; | ||
} | ||
|
||
var progressFraction = (float) progress / MAX_PROGRESS; | ||
var level = progressFraction * 14; | ||
return MathHelper.ceil(level); | ||
} | ||
|
||
protected abstract boolean canExtractFluidContainer(); | ||
protected abstract void tryExtractFluidContainer(); | ||
|
||
private boolean isActive() { | ||
return progress != 0; | ||
} | ||
|
||
private static void decrementIngredient(BrewerBlockEntity brewer, int slot) { | ||
var stack = brewer.getStack(slot); | ||
// TODO: Use stack-aware version on Fabric (and Neo if available) | ||
var remainder = stack.getItem().getRecipeRemainder(); | ||
stack.decrement(1); | ||
|
||
if (remainder != null) { | ||
if (stack.isEmpty()) { | ||
brewer.setStack(slot, new ItemStack(remainder)); | ||
} else { | ||
ItemScatterer.spawn(brewer.world, brewer.pos.getX() + 0.5, brewer.pos.getY() + 0.5, brewer.pos.getZ() + 0.5, new ItemStack(remainder)); | ||
} | ||
} | ||
} | ||
|
||
public static void tick(World world, BlockPos pos, BlockState state, BrewerBlockEntity brewer) { | ||
var originallyActive = brewer.isActive(); | ||
brewer.tryExtractFluidContainer(); | ||
|
||
var dirty = false; | ||
var hasMug = !brewer.getStack(INPUT_SLOT).isEmpty(); | ||
|
||
if (hasMug != state.get(BrewerBlock.Companion.getHAS_MUG())) { | ||
world.setBlockState(pos, state.with(BrewerBlock.Companion.getHAS_MUG(), hasMug)); | ||
} | ||
|
||
var recipe = world.getRecipeManager().getFirstMatch(AdornRecipes.BREWING_TYPE.get(), brewer, world).map(RecipeEntry::value).orElse(null); | ||
|
||
if (recipe != null && brewer.getStack(INPUT_SLOT).isOf(AdornItems.INSTANCE.getMUG())) { | ||
if (brewer.progress++ >= MAX_PROGRESS) { | ||
decrementIngredient(brewer, LEFT_INGREDIENT_SLOT); | ||
decrementIngredient(brewer, RIGHT_INGREDIENT_SLOT); | ||
brewer.setStack(INPUT_SLOT, recipe.craft(brewer, world.getRegistryManager())); | ||
|
||
if (recipe instanceof FluidBrewingRecipe fluidRecipe) { | ||
brewer.getFluidReference().decrement(fluidRecipe.fluid().amount(), fluidRecipe.fluid().unit()); | ||
} | ||
} | ||
|
||
dirty = true; | ||
} else { | ||
if (brewer.progress != 0) { | ||
brewer.progress = 0; | ||
dirty = true; | ||
} | ||
} | ||
|
||
var activeNow = brewer.isActive(); | ||
if (originallyActive != activeNow) { | ||
dirty = true; | ||
var newState = state.with(BrewerBlock.Companion.getACTIVE(), activeNow); | ||
world.setBlockState(pos, newState); | ||
} | ||
|
||
if (dirty) { | ||
markDirty(world, pos, state); | ||
} | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
common/src/main/java/juuxel/adorn/block/entity/DrawerBlockEntity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package juuxel.adorn.block.entity; | ||
|
||
import juuxel.adorn.block.AdornBlockEntities; | ||
import juuxel.adorn.menu.DrawerMenu; | ||
import juuxel.adorn.util.ExtensionsKt; | ||
import net.minecraft.block.BlockState; | ||
import net.minecraft.entity.player.PlayerInventory; | ||
import net.minecraft.menu.Menu; | ||
import net.minecraft.util.math.BlockPos; | ||
|
||
public final class DrawerBlockEntity extends SimpleContainerBlockEntity { | ||
public DrawerBlockEntity(BlockPos pos, BlockState state) { | ||
super(AdornBlockEntities.DRAWER.get(), pos, state, 15); | ||
} | ||
|
||
@Override | ||
protected Menu createMenu(int syncId, PlayerInventory inv) { | ||
return new DrawerMenu(syncId, inv, this, ExtensionsKt.menuContextOf(this)); | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
common/src/main/java/juuxel/adorn/block/entity/KitchenCupboardBlockEntity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package juuxel.adorn.block.entity; | ||
|
||
import juuxel.adorn.block.AdornBlockEntities; | ||
import juuxel.adorn.menu.KitchenCupboardMenu; | ||
import juuxel.adorn.util.ExtensionsKt; | ||
import net.minecraft.block.BlockState; | ||
import net.minecraft.entity.player.PlayerInventory; | ||
import net.minecraft.menu.Menu; | ||
import net.minecraft.util.math.BlockPos; | ||
|
||
public final class KitchenCupboardBlockEntity extends SimpleContainerBlockEntity { | ||
public KitchenCupboardBlockEntity(BlockPos pos, BlockState state) { | ||
super(AdornBlockEntities.KITCHEN_CUPBOARD.get(), pos, state, 15); | ||
} | ||
|
||
@Override | ||
protected Menu createMenu(int syncId, PlayerInventory inv) { | ||
return new KitchenCupboardMenu(syncId, inv, this, ExtensionsKt.menuContextOf(this)); | ||
} | ||
} |
Oops, something went wrong.