Skip to content

Commit

Permalink
Rewrite remaining Neo platform code in Java
Browse files Browse the repository at this point in the history
- Kitchen sink code cleaned up slightly (using convenience
  methods from FluidTank)
- DistExecutor replaced with a FMLEnvironment.dist check
  • Loading branch information
Juuxel committed Jul 30, 2024
1 parent b6fcd38 commit ad75b1b
Show file tree
Hide file tree
Showing 76 changed files with 1,310 additions and 1,095 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,10 @@ public int calculateComparatorOutput() {
return MathHelper.ceil(level);
}

/** {@return true if you can extract the fluid container as an item} */
protected abstract boolean canExtractFluidContainer();

/** Extract the fluid from the container, if possible. */
protected abstract void tryExtractFluidContainer();

private boolean isActive() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package juuxel.adorn.block.variant;

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public abstract class CompatBlockVariantSet implements BlockVariantSet {
protected abstract String getModId();

protected List<BlockVariant> createVariants(Function<String, BlockVariant> factory, String... variants) {
return Arrays.stream(variants).map(variant -> factory.apply(getModId() + '/' + variant)).toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package juuxel.adorn.block.variant

import java.util.function.Function

interface BlockVariantSet {
val woodVariants: List<BlockVariant> get() = emptyList()
val stoneVariants: List<BlockVariant> get() = emptyList()
Expand All @@ -12,6 +14,12 @@ interface BlockVariantSet {
// No custom sorting by default.
}

companion object {
@JvmStatic
fun createVariants(prefix: String, factory: Function<String, BlockVariant>, vararg variants: String): List<BlockVariant> =
variants.map { factory.apply("$prefix/$it") }
}

fun interface CustomVariantConsumer {
fun add(variant: BlockVariant, kinds: List<BlockKind>)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import net.minecraft.util.DyeColor
import net.minecraft.util.Util

object AdornItemGroups {
@JvmField
val ITEM_GROUPS: Registrar<ItemGroup> = RegistrarFactory.get().create(RegistryKeys.ITEM_GROUP)

// Block kinds for each vanilla item group
Expand Down
1 change: 1 addition & 0 deletions common/src/main/kotlin/juuxel/adorn/menu/AdornMenus.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import net.minecraft.registry.RegistryKeys
import net.minecraft.resource.featuretoggle.FeatureFlags

object AdornMenus {
@JvmField
val MENUS = RegistrarFactory.get().create(RegistryKeys.SCREEN_HANDLER)
val DRAWER: MenuType<DrawerMenu> by MENUS.register("drawer") { createType(DrawerMenu::load) }
val KITCHEN_CUPBOARD: MenuType<KitchenCupboardMenu> by MENUS.register("kitchen_cupboard") { createType(KitchenCupboardMenu::load) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ interface ItemGroupBridge {
@InlineServices
companion object {
private val instance: ItemGroupBridge by lazy { loadService() }

@JvmStatic
fun get(): ItemGroupBridge = instance
}
}
64 changes: 64 additions & 0 deletions forge/src/main/java/juuxel/adorn/platform/forge/Adorn.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package juuxel.adorn.platform.forge;

import juuxel.adorn.AdornCommon;
import juuxel.adorn.block.variant.BlockVariantSets;
import juuxel.adorn.config.ConfigManager;
import juuxel.adorn.criterion.AdornCriteria;
import juuxel.adorn.item.group.AdornItemGroups;
import juuxel.adorn.lib.AdornStats;
import juuxel.adorn.lib.registry.Registrar;
import juuxel.adorn.loot.AdornLootConditionTypes;
import juuxel.adorn.loot.AdornLootFunctionTypes;
import juuxel.adorn.menu.AdornMenus;
import juuxel.adorn.platform.forge.client.AdornClient;
import juuxel.adorn.platform.forge.compat.Compat;
import juuxel.adorn.platform.forge.event.ItemEvents;
import juuxel.adorn.platform.forge.networking.AdornNetworking;
import juuxel.adorn.platform.forge.registrar.ForgeRegistrar;
import juuxel.adorn.recipe.AdornRecipes;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModLoadingContext;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.fml.loading.FMLEnvironment;
import net.neoforged.neoforge.common.NeoForgeMod;

@Mod(AdornCommon.NAMESPACE)
public final class Adorn {
public Adorn() {
var modBus = ModLoadingContext.get().getActiveContainer().getEventBus();
ConfigManager.get().init();
modBus.addListener(this::init);
new EventsImplementedInJava().register(modBus);
AdornItemGroups.init();
registerToBus(AdornItemGroups.ITEM_GROUPS, modBus);
AdornRecipes.init();
registerToBus(AdornMenus.MENUS, modBus);
registerToBus(AdornRecipes.RECIPE_SERIALIZERS, modBus);
registerToBus(AdornRecipes.RECIPE_TYPES, modBus);
registerToBus(AdornLootConditionTypes.LOOT_CONDITION_TYPES, modBus);
registerToBus(AdornLootFunctionTypes.LOOT_FUNCTION_TYPES, modBus);
modBus.addListener(AdornNetworking::register);
AdornCriteria.init();
registerToBus(AdornCriteria.CRITERIA, modBus);
ItemEvents.register(modBus);
modBus.addListener(AdornCapabilities::register);
Compat.init(modBus);
BlockVariantSets.register();
NeoForgeMod.enableMilkFluid();

if (FMLEnvironment.dist == Dist.CLIENT) {
AdornClient.init(modBus);
}
}

private void registerToBus(Registrar<?> registrar, IEventBus modBus) {
((ForgeRegistrar<?>) registrar).hook(modBus);
}

private void init(FMLCommonSetupEvent event) {
AdornStats.init();
ConfigManager.get().finalize();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package juuxel.adorn.platform.forge;

import juuxel.adorn.block.AdornBlockEntities;
import juuxel.adorn.block.variant.BlockKind;
import juuxel.adorn.block.variant.BlockVariantSets;
import juuxel.adorn.platform.forge.block.entity.BlockEntityWithFluidTank;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SidedInventory;
import net.minecraft.util.math.Direction;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.capabilities.IBlockCapabilityProvider;
import net.neoforged.neoforge.capabilities.ICapabilityProvider;
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import net.neoforged.neoforge.fluids.capability.IFluidHandler;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.wrapper.InvWrapper;
import net.neoforged.neoforge.items.wrapper.SidedInvWrapper;
import org.jetbrains.annotations.Nullable;

public final class AdornCapabilities {
private static final IBlockCapabilityProvider<IItemHandler, @Nullable Direction> INVENTORY_WRAPPER_FOR_BLOCK =
(world, pos, state, blockEntity, side) -> blockEntity instanceof Inventory inventory ? getInventoryWrapper(inventory, side) : null;
private static final ICapabilityProvider<BlockEntity, @Nullable Direction, IItemHandler> INVENTORY_WRAPPER_FOR_BLOCK_ENTITY =
(blockEntity, side) -> blockEntity instanceof Inventory inventory ? getInventoryWrapper(inventory, side) : null;
private static final IBlockCapabilityProvider<IFluidHandler, @Nullable Direction> FLUID_TANK_FOR_BLOCK =
(world, pos, state, blockEntity, side) -> blockEntity instanceof BlockEntityWithFluidTank withTank ? withTank.getTank() : null;
private static final ICapabilityProvider<BlockEntity, @Nullable Direction, IFluidHandler> FLUID_TANK_FOR_BLOCK_ENTITY =
(blockEntity, side) -> blockEntity instanceof BlockEntityWithFluidTank withTank ? withTank.getTank() : null;

public static void register(RegisterCapabilitiesEvent event) {
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, AdornBlockEntities.BREWER.get(), INVENTORY_WRAPPER_FOR_BLOCK_ENTITY);

var containerBlockKinds = new BlockKind[] {
BlockKind.DRAWER,
BlockKind.KITCHEN_CUPBOARD,
BlockKind.SHELF,
};

for (var kind : containerBlockKinds) {
for (var block : BlockVariantSets.get(kind)) {
event.registerBlock(Capabilities.ItemHandler.BLOCK, INVENTORY_WRAPPER_FOR_BLOCK, block.get());
}
}

event.registerBlockEntity(Capabilities.FluidHandler.BLOCK, AdornBlockEntities.BREWER.get(), FLUID_TANK_FOR_BLOCK_ENTITY);

for (var kitchenSink : BlockVariantSets.get(BlockKind.KITCHEN_SINK)) {
event.registerBlock(Capabilities.FluidHandler.BLOCK, FLUID_TANK_FOR_BLOCK, kitchenSink.get());
}
}

private static IItemHandler getInventoryWrapper(Inventory inventory, @Nullable Direction side) {
return side != null && inventory instanceof SidedInventory sided ? new SidedInvWrapper(sided, side) : new InvWrapper(inventory);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package juuxel.adorn.platform.forge;

import juuxel.adorn.block.entity.BrewerBlockEntity;
import juuxel.adorn.block.entity.KitchenSinkBlockEntity;
import juuxel.adorn.platform.BlockEntityBridge;
import juuxel.adorn.platform.forge.block.entity.BrewerBlockEntityForge;
import juuxel.adorn.platform.forge.block.entity.KitchenSinkBlockEntityForge;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;

public final class BlockEntityBridgeForge implements BlockEntityBridge {
public static final BlockEntityBridgeForge INSTANCE = new BlockEntityBridgeForge();

@Override
public BrewerBlockEntity createBrewer(BlockPos pos, BlockState state) {
return new BrewerBlockEntityForge(pos, state);
}

@Override
public KitchenSinkBlockEntity createKitchenSink(BlockPos pos, BlockState state) {
return new KitchenSinkBlockEntityForge(pos, state);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package juuxel.adorn.platform.forge;

import juuxel.adorn.block.SofaBlock;
import juuxel.adorn.block.variant.BlockVariant;
import juuxel.adorn.platform.BlockFactory;
import juuxel.adorn.platform.forge.block.SofaBlockForge;

public final class BlockFactoryImpl implements BlockFactory {
public static final BlockFactoryImpl INSTANCE = new BlockFactoryImpl();

@Override
public SofaBlock createSofa(BlockVariant variant) {
return new SofaBlockForge(variant);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package juuxel.adorn.platform.forge;

import juuxel.adorn.config.ConfigManager;
import net.neoforged.fml.loading.FMLPaths;

import java.nio.file.Path;

public final class ConfigManagerImpl extends ConfigManager {
@Override
protected Path getConfigDirectory() {
return FMLPaths.CONFIGDIR.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package juuxel.adorn.platform.forge;

import juuxel.adorn.AdornCommon;
import juuxel.adorn.entity.SeatEntity;
import juuxel.adorn.platform.EntityBridge;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnGroup;

public final class EntityBridgeImpl implements EntityBridge {
public static final EntityBridgeImpl INSTANCE = new EntityBridgeImpl();

@Override
public EntityType<SeatEntity> createSeatType() {
return EntityType.Builder.create(SeatEntity::new, SpawnGroup.MISC)
.setDimensions(0, 0)
.build(AdornCommon.NAMESPACE + ":seat");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package juuxel.adorn.platform.forge;

import juuxel.adorn.fluid.FluidAmountPredicate;
import juuxel.adorn.fluid.FluidUnit;
import juuxel.adorn.fluid.FluidVolume;
import juuxel.adorn.platform.FluidBridge;
import juuxel.adorn.platform.forge.util.FluidTankReference;
import net.minecraft.block.BlockState;
import net.minecraft.fluid.Fluid;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.capability.IFluidHandler;
import org.jetbrains.annotations.Nullable;

public final class FluidBridgeForge implements FluidBridge {
@Override
public FluidUnit getFluidUnit() {
return FluidUnit.LITRE;
}

@Nullable
@Override
public FluidVolume drain(World world, BlockPos pos, @Nullable BlockState state, Direction side, Fluid fluid, FluidAmountPredicate amountPredicate) {
// This method is a port of the Fabric fluid bridge code.
var fluidHandler = world.getCapability(Capabilities.FluidHandler.BLOCK, pos, state, null, side);

if (fluidHandler != null) {
var upperBound = amountPredicate.getUpperBound();
int maxAmount = (int) FluidUnit.convert(upperBound.getAmount(), upperBound.getUnit(), FluidUnit.LITRE);
var max = new FluidStack(fluid, maxAmount);
var extracted = fluidHandler.drain(max, IFluidHandler.FluidAction.SIMULATE);

if (!extracted.isEmpty() && amountPredicate.test(extracted.getAmount(), FluidUnit.LITRE)) {
fluidHandler.drain(extracted, IFluidHandler.FluidAction.EXECUTE);
return FluidTankReference.toFluidVolume(extracted);
}
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package juuxel.adorn.platform.forge;

import com.mojang.datafixers.util.Pair;
import juuxel.adorn.item.group.ItemGroupModifyContext;
import juuxel.adorn.platform.ItemGroupBridge;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.RegistryKey;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent;

import java.util.ArrayList;
import java.util.List;

public final class ItemGroupBridgeForge implements ItemGroupBridge {
private static final ItemGroup.StackVisibility DEFAULT_STACK_VISIBILITY = ItemGroup.StackVisibility.PARENT_AND_SEARCH_TABS;
private final List<Pair<RegistryKey<ItemGroup>, Function1<? super ItemGroupModifyContext, Unit>>> additions = new ArrayList<>();

@Override
public ItemGroup.Builder builder() {
return ItemGroup.builder();
}

@Override
public void addItems(RegistryKey<ItemGroup> group, Function1<? super ItemGroupModifyContext, Unit> configurator) {
additions.add(new Pair<>(group, configurator));
}

@SubscribeEvent
public void addToGroups(BuildCreativeModeTabContentsEvent event) {
for (var entry : additions) {
var group = entry.getFirst();
var configurator = entry.getSecond();
var context = new ItemGroupModifyContext() {
@Override
public void add(ItemConvertible item) {
if (event.getTabKey().equals(group)) {
event.add(item);
}
}

@Override
public void addAfter(ItemConvertible after, List<? extends ItemConvertible> items) {
if (event.getTabKey().equals(group)) {
var afterStack = new ItemStack(after);
for (ItemConvertible item : items) {
var stack = new ItemStack(item);
event.getEntries().putAfter(afterStack, stack, DEFAULT_STACK_VISIBILITY);
afterStack = stack;
}
}
}
};
configurator.invoke(context);
}
}
}
Loading

0 comments on commit ad75b1b

Please sign in to comment.