diff --git a/src/main/java/appeng/core/sync/GuiBridge.java b/src/main/java/appeng/core/sync/GuiBridge.java index 2f3134f42..674df330f 100644 --- a/src/main/java/appeng/core/sync/GuiBridge.java +++ b/src/main/java/appeng/core/sync/GuiBridge.java @@ -43,7 +43,6 @@ import appeng.container.AEBaseContainer; import appeng.container.ContainerNull; import appeng.container.ContainerOpenContext; import appeng.container.implementations.*; -import appeng.container.interfaces.IInventorySlotAware; import appeng.fluids.container.*; import appeng.fluids.helper.IFluidInterfaceHost; import appeng.fluids.parts.PartFluidFormationPlane; @@ -59,11 +58,20 @@ import appeng.parts.automation.PartFormationPlane; import appeng.parts.automation.PartLevelEmitter; import appeng.parts.misc.PartOreDicStorageBus; import appeng.parts.misc.PartStorageBus; -import appeng.parts.reporting.*; +import appeng.parts.reporting.PartCraftingTerminal; +import appeng.parts.reporting.PartExpandedProcessingPatternTerminal; +import appeng.parts.reporting.PartFluidInterfaceConfigurationTerminal; +import appeng.parts.reporting.PartInterfaceConfigurationTerminal; +import appeng.parts.reporting.PartInterfaceTerminal; +import appeng.parts.reporting.PartPatternTerminal; import appeng.tile.crafting.TileCraftingTile; import appeng.tile.crafting.TileMolecularAssembler; import appeng.tile.grindstone.TileGrinder; -import appeng.tile.misc.*; +import appeng.tile.misc.TileCellWorkbench; +import appeng.tile.misc.TileCondenser; +import appeng.tile.misc.TileInscriber; +import appeng.tile.misc.TileSecurityStation; +import appeng.tile.misc.TileVibrationChamber; import appeng.tile.networking.TileWireless; import appeng.tile.qnb.TileQuantumBridge; import appeng.tile.spatial.TileSpatialIOPort; @@ -185,6 +193,7 @@ public enum GuiBridge implements IGuiHandler { private Class guiClass; private GuiHostType type; private SecurityPermissions requiredPermission; + private GuiWrapper.IExternalGui externalGui = null; GuiBridge() { this.tileClass = null; @@ -192,6 +201,16 @@ public enum GuiBridge implements IGuiHandler { this.containerClass = null; } + GuiBridge(GuiWrapper.IExternalGui obj) { + this.tileClass = null; + this.containerClass = null; + this.externalGui = obj; + } + + public GuiWrapper.IExternalGui getExternalGui() { + return this.externalGui; + } + GuiBridge(final Class containerClass, final SecurityPermissions requiredPermission) { this.requiredPermission = requiredPermission; this.containerClass = containerClass; diff --git a/src/main/java/appeng/core/sync/GuiWrapper.java b/src/main/java/appeng/core/sync/GuiWrapper.java new file mode 100644 index 000000000..166dcd650 --- /dev/null +++ b/src/main/java/appeng/core/sync/GuiWrapper.java @@ -0,0 +1,90 @@ +package appeng.core.sync; + +import it.unimi.dsi.fastutil.Hash; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.util.EnumHelper; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Allow to register custom GuiBridge from third-party + */ +public class GuiWrapper { + + public static final GuiWrapper INSTANCE = new GuiWrapper(); + + private GuiWrapper() { + // NO-OP + } + + private final Object2ObjectMap openers = new Object2ObjectOpenHashMap<>(); + private final Object2ObjectMap externalGuis = new Object2ObjectOpenCustomHashMap<>(new Hash.Strategy() { + @Override + public int hashCode(IExternalGui o) { + return o.getID().hashCode(); + } + + @Override + public boolean equals(@Nullable IExternalGui a, @Nullable IExternalGui b) { + return a == b || (a != null && b != null && a.getID().equals(b.getID())); + } + }); + + public synchronized void registerExternalGuiHandler(@Nonnull ResourceLocation id, @Nonnull Opener opener) { + openers.put(id, opener); + } + + @Nullable + public Opener getOpener(ResourceLocation id) { + return openers.get(id); + } + + public GuiBridge wrap(IExternalGui obj) { + return externalGuis.computeIfAbsent(obj, this::create); + } + + private GuiBridge create(IExternalGui obj) { + return EnumHelper.addEnum(GuiBridge.class, obj.getID().toString(), new Class[] {IExternalGui.class}, obj); + } + + @FunctionalInterface + public interface Opener { + + void open(T obj, GuiContext context); + + } + + public interface IExternalGui { + + ResourceLocation getID(); + + } + + public static class GuiContext { + + public final World world; + public final EntityPlayer player; + public final BlockPos pos; + public final EnumFacing facing; + public final NBTTagCompound extra; + + public GuiContext(World world, EntityPlayer player, BlockPos pos, EnumFacing face, NBTTagCompound extra) { + this.world = world; + this.player = player; + this.pos = pos; + this.facing = face; + this.extra = extra; + } + + } + +} diff --git a/src/main/java/appeng/util/Platform.java b/src/main/java/appeng/util/Platform.java index 1be39c3f0..37c13ce79 100644 --- a/src/main/java/appeng/util/Platform.java +++ b/src/main/java/appeng/util/Platform.java @@ -53,6 +53,7 @@ import appeng.core.features.AEFeature; import appeng.core.stats.Stats; import appeng.core.sync.GuiBridge; import appeng.core.sync.GuiHostType; +import appeng.core.sync.GuiWrapper; import appeng.fluids.util.AEFluidStack; import appeng.hooks.TickHandler; import appeng.integration.Integrations; @@ -323,6 +324,20 @@ public class Platform { return; } + if (type.getExternalGui() != null) { + GuiWrapper.IExternalGui obj = type.getExternalGui(); + GuiWrapper.Opener opener = GuiWrapper.INSTANCE.getOpener(obj.getID()); + if (opener == null) { + AELog.warn("External Gui with ID: %s is missing a opener.", obj.getID()); + } else { + World world = tile == null ? p.world : tile.getWorld(); + BlockPos pos = tile == null ? null : tile.getPos(); + EnumFacing face = side == null ? null : side.getFacing(); + opener.open(obj, new GuiWrapper.GuiContext(world, p, pos, face, null)); + } + return; + } + int x = 0; int y = 0; int z = Integer.MIN_VALUE; @@ -360,6 +375,20 @@ public class Platform { return; } + if (type.getExternalGui() != null) { + GuiWrapper.IExternalGui obj = type.getExternalGui(); + GuiWrapper.Opener opener = GuiWrapper.INSTANCE.getOpener(obj.getID()); + if (opener == null) { + AELog.warn("External Gui with ID: %s is missing a opener.", obj.getID()); + } else { + NBTTagCompound extra = new NBTTagCompound(); + extra.setInteger("slot", slot); + extra.setBoolean("isBauble", isBauble); + opener.open(obj, new GuiWrapper.GuiContext(p.world, p, null, null, extra)); + } + return; + } + if (type.getType().isItem()) { p.openGui(AppEng.instance(), type.ordinal() << 4, p.getEntityWorld(), slot, isBauble ? 1 : 0, Integer.MIN_VALUE); }