Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework targeted modules #258

Merged
merged 10 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package me.desht.modularrouters.api.event;

import me.desht.modularrouters.item.module.TargetedModule;
import me.desht.modularrouters.item.module.ModuleItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.neoforged.bus.api.Event;
Expand All @@ -12,12 +12,12 @@
* This event can be used to allow a module to target blocks it otherwise couldn't in conjunction with {@link ExecuteModuleEvent}.
*/
public final class AddModuleTargetEvent extends Event {
private final TargetedModule item;
private final ModuleItem item;
private final UseOnContext context;
private boolean valid;

@ApiStatus.Internal
public AddModuleTargetEvent(TargetedModule item, UseOnContext context, boolean valid) {
public AddModuleTargetEvent(ModuleItem item, UseOnContext context, boolean valid) {
this.item = item;
this.context = context;
this.valid = valid;
Expand All @@ -26,7 +26,7 @@ public AddModuleTargetEvent(TargetedModule item, UseOnContext context, boolean v
/**
* {@return the module type}
*/
public TargetedModule getModuleType() {
public ModuleItem getModuleType() {
return item;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import me.desht.modularrouters.container.ModuleMenu;
import me.desht.modularrouters.core.ModBlocks;
import me.desht.modularrouters.core.ModDataComponents;
import me.desht.modularrouters.logic.compiled.CompiledFluidModule1;
import me.desht.modularrouters.logic.compiled.CompiledFluidModule;
import me.desht.modularrouters.logic.settings.TransferDirection;
import net.minecraft.Util;
import net.minecraft.client.gui.GuiGraphics;
Expand Down Expand Up @@ -47,7 +47,7 @@ public FluidModuleScreen(ModuleMenu container, Inventory inv, Component displayN
public void init() {
super.init();

CompiledFluidModule1 cfm = new CompiledFluidModule1(null, moduleItemStack);
CompiledFluidModule cfm = new CompiledFluidModule(null, moduleItemStack);

int max = ConfigHolder.common.router.baseTickRate.get() * ConfigHolder.common.router.fluidMaxTransferRate.get();
maxTransferField = new IntegerTextField(font, leftPos + 152, topPos + 23, 34, 12,
Expand Down Expand Up @@ -113,7 +113,7 @@ public void containerTick() {
@Override
protected ItemStack buildModifiedItemStack() {
return Util.make(super.buildModifiedItemStack(), stack ->
stack.set(ModDataComponents.FLUID_SETTINGS, new CompiledFluidModule1.FluidModuleSettings(
stack.set(ModDataComponents.FLUID_SETTINGS, new CompiledFluidModule.FluidModuleSettings(
maxTransferField.getIntValue(),
fluidDirButton.getState(),
forceEmptyButton.isToggled(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package me.desht.modularrouters.client.render.area;

import me.desht.modularrouters.item.module.TargetedModule;
import me.desht.modularrouters.item.module.ITargetedModule;
import me.desht.modularrouters.logic.ModuleTarget;
import net.minecraft.world.item.ItemStack;

Expand All @@ -19,8 +19,7 @@ public interface IPositionProvider {
* @return a list of block positions that has been retrieved from the itemstack
*/
default List<ModuleTarget> getStoredPositions(@Nonnull ItemStack stack) {
ModuleTarget target = TargetedModule.getTarget(stack);
return target == null ? List.of() : List.of(target);
return List.copyOf(ITargetedModule.getTargets(stack, false));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ public class ModDataComponents {
.persistent(CompiledFlingerModule.FlingerSettings.CODEC)
.networkSynchronized(CompiledFlingerModule.FlingerSettings.STREAM_CODEC)
);
public static final Supplier<DataComponentType<CompiledFluidModule1.FluidModuleSettings>> FLUID_SETTINGS
public static final Supplier<DataComponentType<CompiledFluidModule.FluidModuleSettings>> FLUID_SETTINGS
= COMPONENTS.registerComponentType("fluid_settings", builder -> builder
.persistent(CompiledFluidModule1.FluidModuleSettings.CODEC)
.networkSynchronized(CompiledFluidModule1.FluidModuleSettings.STREAM_CODEC)
.persistent(CompiledFluidModule.FluidModuleSettings.CODEC)
.networkSynchronized(CompiledFluidModule.FluidModuleSettings.STREAM_CODEC)
);
public static final Supplier<DataComponentType<CompiledPlayerModule.PlayerSettings>> PLAYER_SETTINGS
= COMPONENTS.registerComponentType("player_settings", builder -> builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public MenuType<? extends ModuleMenu> getMenuType() {

@Override
public List<ModuleTarget> getStoredPositions(@Nonnull ItemStack stack) {
return ImmutableList.copyOf(TargetedModule.getTargets(stack, false));
return ImmutableList.copyOf(ITargetedModule.getTargets(stack, false));
}

@Override
Expand All @@ -55,7 +55,7 @@ public TintColor getItemTint() {
}

@Override
protected int getMaxTargets() {
public int getMaxTargets() {
return 8;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import javax.annotation.Nonnull;
import java.util.List;

public class EnergyDistributorModule extends TargetedModule implements IRangedModule, IPositionProvider {
public class EnergyDistributorModule extends ModuleItem implements IRangedModule, IPositionProvider, ITargetedModule {
private static final TintColor TINT_COLOR = new TintColor(79, 9, 90);

public EnergyDistributorModule() {
Expand Down Expand Up @@ -44,16 +44,16 @@ public int getHardMaxRange() {

@Override
public List<ModuleTarget> getStoredPositions(@Nonnull ItemStack stack) {
return ImmutableList.copyOf(TargetedModule.getTargets(stack, false));
return ImmutableList.copyOf(ITargetedModule.getTargets(stack, false));
}

@Override
protected boolean isValidTarget(UseOnContext ctx) {
public boolean isValidTarget(UseOnContext ctx) {
return ctx.getLevel().getCapability(Capabilities.EnergyStorage.BLOCK, ctx.getClickedPos(), ctx.getClickedFace()) != null;
}

@Override
protected int getMaxTargets() {
public int getMaxTargets() {
return 8;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package me.desht.modularrouters.item.module;

import me.desht.modularrouters.api.matching.IItemMatcher;
import me.desht.modularrouters.client.util.TintColor;
import me.desht.modularrouters.config.ConfigHolder;
import me.desht.modularrouters.container.ModuleMenu;
import me.desht.modularrouters.core.ModDataComponents;
import me.desht.modularrouters.core.ModItems;
import me.desht.modularrouters.core.ModMenuTypes;
import me.desht.modularrouters.item.smartfilter.SmartFilterItem;
import me.desht.modularrouters.logic.compiled.CompiledFluidModule1;
import me.desht.modularrouters.logic.compiled.CompiledFluidModule1.FluidModuleSettings;
import me.desht.modularrouters.logic.compiled.CompiledFluidModule;
import me.desht.modularrouters.logic.compiled.CompiledFluidModule.FluidModuleSettings;
import me.desht.modularrouters.logic.filter.matchers.FluidMatcher;
import me.desht.modularrouters.api.matching.IItemMatcher;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.inventory.MenuType;
Expand All @@ -27,7 +27,7 @@ public class FluidModule1 extends ModuleItem {
private static final TintColor TINT_COLOR = new TintColor(79, 191, 255);

public FluidModule1() {
super(ModItems.defaultProps(), CompiledFluidModule1::new);
super(ModItems.defaultProps(), CompiledFluidModule::new);
}

@Override
Expand All @@ -50,7 +50,11 @@ protected Component getFilterItemDisplayName(ItemStack stack) {
protected void addExtraInformation(ItemStack stack, List<Component> list) {
super.addExtraInformation(stack, list);

addFluidModuleInformation(stack, list);
FluidModuleSettings settings = stack.getOrDefault(ModDataComponents.FLUID_SETTINGS.get(), FluidModuleSettings.DEFAULT);
list.add(xlate("modularrouters.itemText.transfer_direction",
xlate(settings.direction().getTranslationKey()).withStyle(ChatFormatting.AQUA)).withStyle(ChatFormatting.YELLOW));
list.add(xlate("modularrouters.itemText.fluid.maxTransfer",
colorText(settings.maxTransfer(), ChatFormatting.AQUA)).withStyle(ChatFormatting.YELLOW));
}

@Override
Expand Down Expand Up @@ -81,14 +85,4 @@ public boolean isFluidModule() {
public TintColor getItemTint() {
return TINT_COLOR;
}

static void addFluidModuleInformation(ItemStack stack, List<Component> list) {
// CompiledFluidModule1 cfm = new CompiledFluidModule1(null, stack);
FluidModuleSettings settings = stack.getOrDefault(ModDataComponents.FLUID_SETTINGS.get(), FluidModuleSettings.DEFAULT);
list.add(xlate("modularrouters.itemText.transfer_direction",
xlate(settings.direction().getTranslationKey()).withStyle(ChatFormatting.AQUA)).withStyle(ChatFormatting.YELLOW));
list.add(xlate("modularrouters.itemText.fluid.maxTransfer",
colorText(settings.maxTransfer(), ChatFormatting.AQUA)).withStyle(ChatFormatting.YELLOW));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,21 @@
import me.desht.modularrouters.client.render.area.IPositionProvider;
import me.desht.modularrouters.client.util.TintColor;
import me.desht.modularrouters.config.ConfigHolder;
import me.desht.modularrouters.container.ModuleMenu;
import me.desht.modularrouters.core.ModDataComponents;
import me.desht.modularrouters.core.ModItems;
import me.desht.modularrouters.core.ModMenuTypes;
import me.desht.modularrouters.item.smartfilter.SmartFilterItem;
import me.desht.modularrouters.logic.ModuleTargetList;
import me.desht.modularrouters.logic.compiled.CompiledFluidModule2;
import me.desht.modularrouters.logic.filter.matchers.FluidMatcher;
import me.desht.modularrouters.api.matching.IItemMatcher;
import net.minecraft.network.chat.Component;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.FluidUtil;

import java.util.List;

public class FluidModule2 extends TargetedModule implements IRangedModule, IPositionProvider {
public class FluidModule2 extends FluidModule1 implements IRangedModule, IPositionProvider, ITargetedModule {
private static final TintColor TINT_COLOR = new TintColor(64, 224, 255);

public FluidModule2() {
super(ModItems.moduleProps()
.component(ModDataComponents.MODULE_TARGET_LIST, ModuleTargetList.EMPTY), CompiledFluidModule2::new);
}

@Override
protected boolean isValidTarget(UseOnContext ctx) {
public boolean isValidTarget(UseOnContext ctx) {
return !ctx.getLevel().isEmptyBlock(ctx.getClickedPos());
}

@Override
public boolean isDirectional() {
return false;
}

@Override
public MenuType<? extends ModuleMenu> getMenuType() {
return ModMenuTypes.FLUID_MENU.get();
}

@Override
protected Component getFilterItemDisplayName(ItemStack stack) {
return FluidUtil.getFluidContained(stack).map(FluidStack::getHoverName).orElse(stack.getHoverName());
}

@Override
public boolean isItemValidForFilter(ItemStack stack) {
// only fluid-holding items or a smart filter item can go into a fluid module's filter
if (stack.isEmpty() || stack.getItem() instanceof SmartFilterItem) return true;
if (stack.getCount() > 1) return false;

return FluidUtil.getFluidContained(stack).map(fluidStack -> !fluidStack.isEmpty()).orElse(false);
}

@Override
public IItemMatcher getFilterItemMatcher(ItemStack stack) {
return new FluidMatcher(stack);
}

@Override
public boolean isFluidModule() {
return true;
}

@Override
public int getBaseRange() {
return ConfigHolder.common.module.fluid2BaseRange.get();
Expand All @@ -83,12 +33,6 @@ public TintColor getItemTint() {
return TINT_COLOR;
}

@Override
protected void addExtraInformation(ItemStack stack, List<Component> list) {
super.addExtraInformation(stack, list);
FluidModule1.addFluidModuleInformation(stack, list);
}

@Override
public int getRenderColor(int index) {
return 0x8040E0FF;
Expand Down
117 changes: 117 additions & 0 deletions src/main/java/me/desht/modularrouters/item/module/ITargetedModule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package me.desht.modularrouters.item.module;

import com.google.common.collect.Sets;
import me.desht.modularrouters.api.event.AddModuleTargetEvent;
import me.desht.modularrouters.core.ModDataComponents;
import me.desht.modularrouters.logic.ModuleTarget;
import me.desht.modularrouters.logic.ModuleTargetList;
import me.desht.modularrouters.util.BlockUtil;
import me.desht.modularrouters.util.InventoryUtils;
import me.desht.modularrouters.util.MiscUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.neoforged.neoforge.common.NeoForge;
import org.jetbrains.annotations.ApiStatus;

import java.util.Collection;
import java.util.List;
import java.util.Set;

public interface ITargetedModule {
/**
* <strong>Override-only</strong> method that checks whether this module can have the block of the context selected.
* <p>Note: it is not guaranteed that the module will only have blocks that pass this test selected, see {@link AddModuleTargetEvent}.
*/
@ApiStatus.OverrideOnly
default boolean isValidTarget(UseOnContext ctx) {
return InventoryUtils.getInventory(ctx.getLevel(), ctx.getClickedPos(), ctx.getClickedFace()).isPresent();
}

default int getMaxTargets() {
return 1;
}

/**
* Does this module have limited range?
*
* @return true if range is limited, false otherwise
*/
default boolean isRangeLimited() {
return true;
}

/**
* {@return whether this module can operate in the given {@code dimension}}
*/
default boolean canOperateInDimension(ResourceKey<Level> dimension) {
return true;
}

/**
* Retrieve multi-targeting information from a module itemstack.
*
* @param stack the module item stack
* @param checkBlockName verify the name of the target block - only works server-side
* @implNote the set will be limited to the max target amount of the module
* @return a set of targets for the module
*/
static Set<ModuleTarget> getTargets(ItemStack stack, boolean checkBlockName) {
var max = ((ITargetedModule) stack.getItem()).getMaxTargets();
Set<ModuleTarget> result = Sets.newHashSet();

boolean update = false;
var targets = stack.getOrDefault(ModDataComponents.MODULE_TARGET_LIST, ModuleTargetList.EMPTY).targets();
for (int i = 0; i < targets.size() && result.size() < max; i++) {
var target = targets.get(i);
if (checkBlockName) {
var newTarget = updateTargetBlockName(stack, target);
if (newTarget != target) update = true;
target = newTarget;
}
if (target != null) {
result.add(target);
}
}

if (update) {
stack.set(ModDataComponents.MODULE_TARGET_LIST, new ModuleTargetList(List.copyOf(result)));
}

return result;
}

/**
* Sets the targets of a module.
* @param stack the module stack to update
* @param targets the new targets
*/
static void setTargets(ItemStack stack, Collection<ModuleTarget> targets) {
stack.set(ModDataComponents.MODULE_TARGET_LIST, new ModuleTargetList(List.copyOf(targets)));
}

/**
* Checks if the module can select the target of the {@code context}.
*/
static boolean canSelectTarget(UseOnContext context) {
var module = context.getItemInHand().getItem();
return NeoForge.EVENT_BUS.post(new AddModuleTargetEvent((ModuleItem) module, context, ((ITargetedModule) module).isValidTarget(context))).isValid();
}

private static ModuleTarget updateTargetBlockName(ItemStack stack, ModuleTarget target) {
Matyrobbrt marked this conversation as resolved.
Show resolved Hide resolved
ServerLevel level = MiscUtil.getWorldForGlobalPos(target.gPos);
BlockPos pos = target.gPos.pos();
if (level != null && level.getChunkSource().hasChunk(pos.getX() >> 4, pos.getZ() >> 4)) {
String invName = BlockUtil.getBlockName(level, pos);
if (!target.blockTranslationKey.equals(invName)) {
return new ModuleTarget(target.gPos, target.face, invName);
} else {
return target;
}
}
return null;
}
}
Loading