first commit
This commit is contained in:
commit
e5bdff9721
32 changed files with 2100 additions and 0 deletions
67
src/main/java/ovh/sad/growglobe/GrowGlobeBlock.java
Normal file
67
src/main/java/ovh/sad/growglobe/GrowGlobeBlock.java
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package ovh.sad.growglobe;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockEntityProvider;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.BlockWithEntity;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.entity.ItemEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class GrowGlobeBlock extends BlockWithEntity {
|
||||
public GrowGlobeBlock(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
public static final MapCodec<GrowGlobeBlock> CODEC = createCodec(GrowGlobeBlock::new);
|
||||
|
||||
@Override
|
||||
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
|
||||
if (!world.isClient) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
System.out.println("one");
|
||||
|
||||
if (blockEntity instanceof GrowGlobeBlockEntity screenHandlerFactory) {
|
||||
System.out.println("two");
|
||||
if (player instanceof ServerPlayerEntity serverPlayer) {
|
||||
System.out.println("three");
|
||||
serverPlayer.openHandledScreen(screenHandlerFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BlockWithEntity> getCodec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new GrowGlobeBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
|
||||
return world.isClient ? null :
|
||||
(type == GrowGlobeBlockEntities.GROW_GLOBE
|
||||
? (world1, pos, state1, be) -> GrowGlobeBlockEntity.tick(world1, pos, state1, (GrowGlobeBlockEntity)be)
|
||||
: null);
|
||||
}
|
||||
}
|
||||
22
src/main/java/ovh/sad/growglobe/GrowGlobeBlockEntities.java
Normal file
22
src/main/java/ovh/sad/growglobe/GrowGlobeBlockEntities.java
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package ovh.sad.growglobe;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
import team.reborn.energy.api.EnergyStorage;
|
||||
|
||||
public class GrowGlobeBlockEntities {
|
||||
public static BlockEntityType<GrowGlobeBlockEntity> GROW_GLOBE;
|
||||
|
||||
public static void register() {
|
||||
GROW_GLOBE = Registry.register(
|
||||
Registries.BLOCK_ENTITY_TYPE,
|
||||
Identifier.of(Growglobe.MOD_ID, "growglobe"),
|
||||
FabricBlockEntityTypeBuilder.create(GrowGlobeBlockEntity::new, GrowGlobeBlocks.GROW_GLOBE_BLOCK).build()
|
||||
);
|
||||
|
||||
EnergyStorage.SIDED.registerForBlockEntity((be, dir) -> be.energyStorage, GROW_GLOBE);
|
||||
}
|
||||
}
|
||||
235
src/main/java/ovh/sad/growglobe/GrowGlobeBlockEntity.java
Normal file
235
src/main/java/ovh/sad/growglobe/GrowGlobeBlockEntity.java
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
package ovh.sad.growglobe;
|
||||
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
||||
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.Inventories;
|
||||
import net.minecraft.inventory.SidedInventory;
|
||||
import net.minecraft.inventory.SimpleInventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.screen.ArrayPropertyDelegate;
|
||||
import net.minecraft.screen.PropertyDelegate;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.storage.ReadView;
|
||||
import net.minecraft.storage.WriteView;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.ItemScatterer;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import team.reborn.energy.api.EnergyStorage;
|
||||
import team.reborn.energy.api.base.SimpleEnergyStorage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static ovh.sad.growglobe.HarvestUtil.harvestBlock;
|
||||
|
||||
public class GrowGlobeBlockEntity extends BlockEntity implements ExtendedScreenHandlerFactory, SidedInventory {
|
||||
public static final long CAPACITY = 10000;
|
||||
public static final long MAX_INSERT = 200;
|
||||
public static final long MAX_EXTRACT = 0;
|
||||
|
||||
public final SimpleEnergyStorage energyStorage = new SimpleEnergyStorage(CAPACITY, MAX_INSERT, MAX_EXTRACT) {
|
||||
@Override
|
||||
protected void onFinalCommit() {
|
||||
markDirty();
|
||||
}
|
||||
};
|
||||
|
||||
// Inventory: slot 9 = input (sapling), slots 0–8 = outputs
|
||||
private final SimpleInventory inventory = new SimpleInventory(10);
|
||||
|
||||
// [0]=currentEnergy, [1]=maxEnergy, [2]=progress, [3]=maxProgress
|
||||
private final PropertyDelegate propertyDelegate;
|
||||
|
||||
private int progress = 0;
|
||||
private static final int MAX_PROGRESS = 80;
|
||||
private static final int ENERGY_PER_TICK = 65;
|
||||
|
||||
public GrowGlobeBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(GrowGlobeBlockEntities.GROW_GLOBE, pos, state);
|
||||
this.propertyDelegate = new ArrayPropertyDelegate(4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockReplaced(BlockPos pos, BlockState oldState) {
|
||||
if (this.world != null) {
|
||||
ItemScatterer.spawn(this.world, pos, this.inventory);
|
||||
}
|
||||
}
|
||||
private static final int[] INPUT_SLOTS = {9};
|
||||
private static final int[] OUTPUT_SLOTS = {0,1,2,3,4,5,6,7,8};
|
||||
|
||||
@Override
|
||||
public int[] getAvailableSlots(Direction side) {
|
||||
if (side == Direction.UP) return INPUT_SLOTS; // hopper can insert sapling
|
||||
if (side == Direction.DOWN) return OUTPUT_SLOTS; // hopper can extract outputs
|
||||
return new int[0]; // sides cannot access
|
||||
}
|
||||
|
||||
public static void tick(World world, BlockPos pos, BlockState state, GrowGlobeBlockEntity blockEntity) {
|
||||
if (world.isClient) return;
|
||||
|
||||
for (Direction dir : Direction.values()) {
|
||||
@Nullable EnergyStorage adjacent = EnergyStorage.SIDED.find(world, pos.offset(dir), dir.getOpposite());
|
||||
if (adjacent == null) continue;
|
||||
try (Transaction tx = Transaction.openOuter()) {
|
||||
long moved = adjacent.extract(50, tx);
|
||||
long inserted = blockEntity.energyStorage.insert(moved, tx);
|
||||
if (inserted > 0) tx.commit();
|
||||
}
|
||||
}
|
||||
|
||||
blockEntity.propertyDelegate.set(0, (int) Math.min(Integer.MAX_VALUE, blockEntity.energyStorage.amount));
|
||||
blockEntity.propertyDelegate.set(1, (int) Math.min(Integer.MAX_VALUE, blockEntity.energyStorage.capacity));
|
||||
blockEntity.propertyDelegate.set(2, blockEntity.progress);
|
||||
blockEntity.propertyDelegate.set(3, MAX_PROGRESS);
|
||||
|
||||
ItemStack input = blockEntity.inventory.getStack(9);
|
||||
if (input.isEmpty()) {
|
||||
blockEntity.progress = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (blockEntity.energyStorage.amount >= ENERGY_PER_TICK) {
|
||||
blockEntity.energyStorage.amount -= ENERGY_PER_TICK;
|
||||
blockEntity.progress++;
|
||||
|
||||
if (blockEntity.progress >= MAX_PROGRESS) {
|
||||
blockEntity.progress = 0;
|
||||
|
||||
Item toolItem = input.getItem();
|
||||
List<ItemStack> drops = harvestBlock((ServerWorld) world, toolItem, new BlockPos(0, 200, 0));
|
||||
|
||||
outer:
|
||||
for (ItemStack drop : drops) {
|
||||
for (int i = 0; i <= 8; i++) {
|
||||
ItemStack slot = blockEntity.inventory.getStack(i);
|
||||
if (slot.isEmpty()) {
|
||||
blockEntity.inventory.setStack(i, drop);
|
||||
continue outer;
|
||||
} else if (canCombine(slot, drop)) {
|
||||
int combined = Math.min(slot.getMaxCount(), slot.getCount() + drop.getCount());
|
||||
drop.setCount(drop.getCount() - (combined - slot.getCount()));
|
||||
slot.setCount(combined);
|
||||
blockEntity.inventory.setStack(i, slot);
|
||||
if (drop.isEmpty()) continue outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
blockEntity.markDirty();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean canCombine(ItemStack a, ItemStack b) {
|
||||
if (a.getItem() != b.getItem()) return false;
|
||||
|
||||
if (a.hasEnchantments() != b.hasEnchantments()) return false;
|
||||
if (a.hasEnchantments() && !a.getEnchantments().equals(b.getEnchantments())) return false;
|
||||
|
||||
return a.getCount() < a.getMaxCount();
|
||||
}
|
||||
|
||||
public PropertyDelegate getPropertyDelegate() {
|
||||
return propertyDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getDisplayName() {
|
||||
return Text.literal("Grow Globe");
|
||||
}
|
||||
@Override
|
||||
public boolean canInsert(int slot, ItemStack stack, @Nullable Direction dir) {
|
||||
return dir == Direction.UP && slot == 9; // only top can insert into slot 9
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract(int slot, ItemStack stack, Direction dir) {
|
||||
return dir == Direction.DOWN && slot >= 0 && slot <= 8; // only bottom can extract outputs
|
||||
}
|
||||
@Override
|
||||
public ScreenHandler createMenu(int syncId, PlayerInventory inv, PlayerEntity player) {
|
||||
return new GrowGlobeScreenHandler(syncId, inv, inventory, propertyDelegate);
|
||||
}
|
||||
|
||||
public SimpleInventory getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readData(ReadView view) {
|
||||
energyStorage.amount = view.getLong("Energy", 0L);
|
||||
progress = view.getInt("Progress", 0);
|
||||
DefaultedList<ItemStack> list = this.inventory.getHeldStacks();
|
||||
Inventories.readData(view, list);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
inventory.setStack(i, list.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeData(WriteView view) {
|
||||
view.putLong("Energy", energyStorage.amount);
|
||||
view.putInt("Progress", progress);
|
||||
Inventories.writeData(view, this.inventory.getHeldStacks());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getScreenOpeningData(ServerPlayerEntity player) {
|
||||
return this.getPos();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// --- Inventory delegation ---
|
||||
@Override
|
||||
public int size() {
|
||||
return inventory.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return inventory.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStack(int slot) {
|
||||
return inventory.getStack(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot, int amount) {
|
||||
return inventory.removeStack(slot, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot) {
|
||||
return inventory.removeStack(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStack(int slot, ItemStack stack) {
|
||||
inventory.setStack(slot, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayerUse(PlayerEntity player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
inventory.clear();
|
||||
}
|
||||
}
|
||||
58
src/main/java/ovh/sad/growglobe/GrowGlobeBlocks.java
Normal file
58
src/main/java/ovh/sad/growglobe/GrowGlobeBlocks.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package ovh.sad.growglobe;
|
||||
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroups;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class GrowGlobeBlocks {
|
||||
private static Block register(String name, Function<AbstractBlock.Settings, Block> blockFactory, AbstractBlock.Settings settings, boolean shouldRegisterItem) {
|
||||
// Create a registry key for the block
|
||||
RegistryKey<Block> blockKey = keyOfBlock(name);
|
||||
// Create the block instance
|
||||
Block block = blockFactory.apply(settings.registryKey(blockKey));
|
||||
|
||||
// Sometimes, you may not want to register an item for the block.
|
||||
// Eg: if it's a technical block like `minecraft:moving_piston` or `minecraft:end_gateway`
|
||||
if (shouldRegisterItem) {
|
||||
// Items need to be registered with a different type of registry key, but the ID
|
||||
// can be the same.
|
||||
RegistryKey<Item> itemKey = keyOfItem(name);
|
||||
|
||||
BlockItem blockItem = new BlockItem(block, new Item.Settings().registryKey(itemKey).useBlockPrefixedTranslationKey());
|
||||
Registry.register(Registries.ITEM, itemKey, blockItem);
|
||||
}
|
||||
|
||||
return Registry.register(Registries.BLOCK, blockKey, block);
|
||||
}
|
||||
|
||||
private static RegistryKey<Block> keyOfBlock(String name) {
|
||||
return RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(Growglobe.MOD_ID, name));
|
||||
}
|
||||
|
||||
private static RegistryKey<Item> keyOfItem(String name) {
|
||||
return RegistryKey.of(RegistryKeys.ITEM, Identifier.of(Growglobe.MOD_ID, name));
|
||||
}
|
||||
public static final Block GROW_GLOBE_BLOCK = register(
|
||||
"growglobe",
|
||||
GrowGlobeBlock::new,
|
||||
AbstractBlock.Settings.create().sounds(BlockSoundGroup.GLASS).nonOpaque(),
|
||||
true
|
||||
);
|
||||
|
||||
public static void initialize() {
|
||||
ItemGroupEvents.modifyEntriesEvent(ItemGroups.FUNCTIONAL).register((itemGroup) -> {
|
||||
itemGroup.add(GrowGlobeBlocks.GROW_GLOBE_BLOCK.asItem());
|
||||
});
|
||||
}
|
||||
}
|
||||
119
src/main/java/ovh/sad/growglobe/GrowGlobeScreenHandler.java
Normal file
119
src/main/java/ovh/sad/growglobe/GrowGlobeScreenHandler.java
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
package ovh.sad.growglobe;
|
||||
|
||||
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.PropertyDelegate;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
|
||||
public class GrowGlobeScreenHandler extends ScreenHandler {
|
||||
private final Inventory inventory;
|
||||
private final PropertyDelegate energyProperty;
|
||||
|
||||
public GrowGlobeScreenHandler(int syncId, PlayerInventory playerInv, Inventory inventory, PropertyDelegate propertyDelegate) {
|
||||
super(GrowGlobeScreenHandlers.GROW_GLOBE, syncId);
|
||||
this.inventory = inventory;
|
||||
this.energyProperty = propertyDelegate;
|
||||
addProperties(propertyDelegate);
|
||||
|
||||
// Custom 3x3 machine grid slots (indices 0-8)
|
||||
int startX = 81;
|
||||
int startY = 15;
|
||||
int[][] machinePositions = {
|
||||
{startX, startY}, {startX + 18, startY}, {startX + 36, startY}, // row 1
|
||||
{startX, startY + 18}, {startX + 18, startY + 18}, {startX + 36, startY + 18}, // row 2
|
||||
{startX, startY + 36}, {startX + 18, startY + 36}, {startX + 36, startY + 36} // row 3
|
||||
};
|
||||
for (int i = 0; i < 9; i++) {
|
||||
this.addSlot(new Slot(inventory, i, machinePositions[i][0], machinePositions[i][1]));
|
||||
}
|
||||
|
||||
// Extra slot to the right (index 9)
|
||||
this.addSlot(new Slot(inventory, 9, 38, 33));
|
||||
|
||||
// Player inventory slots
|
||||
int playerStartY = startY + 65; // space below machine slots
|
||||
for (int row = 0; row < 3; row++) {
|
||||
for (int col = 0; col < 9; col++) {
|
||||
this.addSlot(new Slot(playerInv, col + row * 9 + 9, 8 + col * 18, playerStartY + row * 18));
|
||||
}
|
||||
}
|
||||
// Player hotbar
|
||||
for (int col = 0; col < 9; col++) {
|
||||
this.addSlot(new Slot(playerInv, col, 8 + col * 18, playerStartY + 58));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack quickMove(PlayerEntity player, int index) {
|
||||
ItemStack newStack = ItemStack.EMPTY;
|
||||
Slot slot = this.slots.get(index);
|
||||
if (slot != null && slot.hasStack()) {
|
||||
ItemStack original = slot.getStack();
|
||||
newStack = original.copy();
|
||||
|
||||
// Number of machine slots (must match block entity SimpleInventory size)
|
||||
int machineSlotCount = 10; // slots 0..9 (0=input, 1..9 outputs)
|
||||
|
||||
// Slot indexes in this.slots:
|
||||
int playerInvStart = machineSlotCount; // start of player inventory in the slots list
|
||||
int playerMainEnd = playerInvStart + 27; // end (exclusive) of main inventory
|
||||
int hotbarStart = playerMainEnd; // start of hotbar
|
||||
int hotbarEnd = hotbarStart + 9; // end (exclusive) of hotbar
|
||||
|
||||
if (index < machineSlotCount) {
|
||||
// from machine -> try to move into player (first main then hotbar)
|
||||
if (!this.insertItem(original, playerInvStart, hotbarEnd, true)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (index >= playerInvStart && index < playerMainEnd) {
|
||||
// from player main inventory -> try machine input first, then hotbar
|
||||
if (!this.insertItem(original, 0, 1, false)) {
|
||||
if (!this.insertItem(original, playerMainEnd, hotbarEnd, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
} else if (index >= hotbarStart && index < hotbarEnd) {
|
||||
// from hotbar -> try machine input first, then main inventory
|
||||
if (!this.insertItem(original, 0, 1, false)) {
|
||||
if (!this.insertItem(original, playerInvStart, playerMainEnd, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (original.isEmpty()) {
|
||||
slot.setStack(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.markDirty();
|
||||
}
|
||||
}
|
||||
return newStack;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canUse(PlayerEntity player) {
|
||||
return inventory.canPlayerUse(player);
|
||||
}
|
||||
|
||||
public int getEnergy() {
|
||||
return energyProperty.get(0);
|
||||
}
|
||||
|
||||
public int getMaxEnergy() {
|
||||
return energyProperty.get(1);
|
||||
}
|
||||
public int getProgress() {
|
||||
return energyProperty.get(2);
|
||||
}
|
||||
|
||||
public int getMaxProgress() {
|
||||
return energyProperty.get(3);
|
||||
}
|
||||
}
|
||||
36
src/main/java/ovh/sad/growglobe/GrowGlobeScreenHandlers.java
Normal file
36
src/main/java/ovh/sad/growglobe/GrowGlobeScreenHandlers.java
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package ovh.sad.growglobe;
|
||||
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
// ModScreenHandlers.java
|
||||
public class GrowGlobeScreenHandlers {
|
||||
public static ScreenHandlerType<GrowGlobeScreenHandler> GROW_GLOBE;
|
||||
|
||||
public static void register() {
|
||||
GROW_GLOBE = Registry.register(
|
||||
Registries.SCREEN_HANDLER,
|
||||
Identifier.of(Growglobe.MOD_ID, "growglobe"),
|
||||
new ExtendedScreenHandlerType<>(
|
||||
// Decoder: called on client
|
||||
(syncId, playerInv, buf) -> {
|
||||
BlockPos pos = buf;
|
||||
|
||||
var be = playerInv.player.getWorld().getBlockEntity(pos);
|
||||
if (be instanceof GrowGlobeBlockEntity blockEntity) {
|
||||
return new GrowGlobeScreenHandler(syncId, playerInv, blockEntity.getInventory(), blockEntity.getPropertyDelegate());
|
||||
}
|
||||
// Fallback if BE missing
|
||||
return new GrowGlobeScreenHandler(syncId, playerInv, new net.minecraft.inventory.SimpleInventory(7), new net.minecraft.screen.ArrayPropertyDelegate(2));
|
||||
},
|
||||
// PacketCodec to sync BlockPos
|
||||
BlockPos.PACKET_CODEC
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
14
src/main/java/ovh/sad/growglobe/Growglobe.java
Normal file
14
src/main/java/ovh/sad/growglobe/Growglobe.java
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package ovh.sad.growglobe;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class Growglobe implements ModInitializer {
|
||||
public static String MOD_ID = "growglobe";
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
GrowGlobeBlocks.initialize();
|
||||
GrowGlobeBlockEntities.register();
|
||||
}
|
||||
}
|
||||
92
src/main/java/ovh/sad/growglobe/HarvestUtil.java
Normal file
92
src/main/java/ovh/sad/growglobe/HarvestUtil.java
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
package ovh.sad.growglobe;
|
||||
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.registry.tag.BlockTags;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.gen.feature.TreeFeatureConfig;
|
||||
import net.minecraft.world.gen.foliage.SpruceFoliagePlacer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class HarvestUtil {
|
||||
|
||||
/**
|
||||
* Dynamically harvests any block or item and returns the resulting drops.
|
||||
* Works with vanilla and modded blocks.
|
||||
*
|
||||
* @param world the world
|
||||
* @param item the Item (usually BlockItem) to harvest
|
||||
* @param pos the position (optional for context; can be BlockPos.ORIGIN)
|
||||
* @return List of ItemStacks that would drop
|
||||
*/
|
||||
public static List<ItemStack> harvestBlock(ServerWorld world, Item item, BlockPos pos) {
|
||||
List<ItemStack> drops = new ArrayList<>();
|
||||
|
||||
if (!(item instanceof BlockItem blockItem)) return drops;
|
||||
|
||||
Block block = blockItem.getBlock();
|
||||
BlockState state = block.getDefaultState();
|
||||
|
||||
BlockEntityProvider blockEntityProvider = block instanceof BlockEntityProvider bep ? bep : null;
|
||||
|
||||
// CropBlock: drop crop + seeds
|
||||
if (block instanceof CropBlock crop) {
|
||||
state = crop.withAge(crop.getMaxAge());
|
||||
}
|
||||
// Stackable plants like sugar cane or bamboo
|
||||
else if (block instanceof SugarCaneBlock) {
|
||||
int height = 3; // or dynamically detect in world
|
||||
for (int i = 0; i < height; i++) drops.add(new ItemStack(block));
|
||||
return drops;
|
||||
}
|
||||
else if (state.isIn(BlockTags.SAPLINGS)) {
|
||||
SaplingBlock sapling = (SaplingBlock) block;
|
||||
SaplingGenerator generator = sapling.generator;
|
||||
|
||||
RegistryKey<ConfiguredFeature<?, ?>> featureKey =
|
||||
generator.getSmallTreeFeature(world.random, true);
|
||||
if (featureKey == null)
|
||||
featureKey = generator.getMegaTreeFeature(world.random);
|
||||
|
||||
if (featureKey != null) {
|
||||
var featureRegistry = world.getRegistryManager().getOrThrow(RegistryKeys.CONFIGURED_FEATURE);
|
||||
|
||||
var configured = featureRegistry.getOrThrow(featureKey);
|
||||
|
||||
if (configured.value().config() instanceof TreeFeatureConfig treeConfig) {
|
||||
BlockState logState = treeConfig.trunkProvider.get(world.random, pos);
|
||||
BlockState leafState = treeConfig.foliageProvider.get(world.random, pos);
|
||||
|
||||
int logCount = 5 + world.random.nextInt(3);
|
||||
for (int i = 0; i < logCount; i++)
|
||||
drops.addAll(Block.getDroppedStacks(logState, world, pos, null));
|
||||
|
||||
int leafCount = 10 + world.random.nextInt(10);
|
||||
for (int i = 0; i < leafCount; i++)
|
||||
drops.addAll(Block.getDroppedStacks(leafState, world, pos, null));
|
||||
|
||||
drops.add(new ItemStack(sapling));
|
||||
return drops;
|
||||
}
|
||||
}
|
||||
|
||||
drops.add(new ItemStack(sapling));
|
||||
return drops;
|
||||
}
|
||||
|
||||
drops.addAll(Block.getDroppedStacks(state, world, pos, blockEntityProvider != null ? blockEntityProvider.createBlockEntity(pos, state) : null));
|
||||
return drops;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue