diff --git a/src/main/java/com/cleanroommc/modularui/CommonProxy.java b/src/main/java/com/cleanroommc/modularui/CommonProxy.java index 4f3f33b9..83d06666 100644 --- a/src/main/java/com/cleanroommc/modularui/CommonProxy.java +++ b/src/main/java/com/cleanroommc/modularui/CommonProxy.java @@ -31,6 +31,7 @@ public class CommonProxy { void preInit(FMLPreInitializationEvent event) { MinecraftForge.EVENT_BUS.register(CommonProxy.class); MinecraftForge.EVENT_BUS.register(GuiManager.class); + MinecraftForge.EVENT_BUS.register(HoloGuiManager.class); if (ModularUIConfig.enableTestGuis) { MinecraftForge.EVENT_BUS.register(TestBlock.class); @@ -40,6 +41,7 @@ void preInit(FMLPreInitializationEvent event) { NetworkHandler.init(); GuiFactories.init(); + GuiManager.registerFactory(HoloGuiFactory.INSTANCE); } void postInit(FMLPostInitializationEvent event) { @@ -61,6 +63,7 @@ public static void registerBlocks(RegistryEvent.Register event) { .id("modular_screen", 0) .name("ModularScreen") .entity(HoloScreenEntity.class) + .tracker(100, 20, false) .factory(HoloScreenEntity::new) .build()); } diff --git a/src/main/java/com/cleanroommc/modularui/factory/GuiManager.java b/src/main/java/com/cleanroommc/modularui/factory/GuiManager.java index 738054b0..35e54910 100644 --- a/src/main/java/com/cleanroommc/modularui/factory/GuiManager.java +++ b/src/main/java/com/cleanroommc/modularui/factory/GuiManager.java @@ -37,7 +37,7 @@ public class GuiManager { - private static final Object2ObjectMap> FACTORIES = new Object2ObjectOpenHashMap<>(16); + protected static final Object2ObjectMap> FACTORIES = new Object2ObjectOpenHashMap<>(16); private static IMuiScreen lastMui; private static final List openedContainers = new ArrayList<>(4); diff --git a/src/main/java/com/cleanroommc/modularui/factory/HoloGuiFactory.java b/src/main/java/com/cleanroommc/modularui/factory/HoloGuiFactory.java new file mode 100644 index 00000000..65bc507e --- /dev/null +++ b/src/main/java/com/cleanroommc/modularui/factory/HoloGuiFactory.java @@ -0,0 +1,43 @@ +package com.cleanroommc.modularui.factory; + +import com.cleanroommc.modularui.api.IGuiHolder; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.PacketBuffer; + +import net.minecraft.util.EnumHand; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class HoloGuiFactory extends AbstractUIFactory{ + + public static final HoloGuiFactory INSTANCE = new HoloGuiFactory(); + + protected HoloGuiFactory() { + super("mui:holo"); + } + + public static void open(EntityPlayerMP player, EnumHand hand) { + Objects.requireNonNull(player); + Objects.requireNonNull(hand); + HandGuiData guiData = new HandGuiData(player, hand); + HoloGuiManager.open(INSTANCE, guiData, player); + } + @Override + public @NotNull IGuiHolder getGuiHolder(HandGuiData data) { + return Objects.requireNonNull(castGuiHolder(data.getUsedItemStack().getItem()), "Item was not a gui holder!"); + } + + @Override + public void writeGuiData(HandGuiData guiData, PacketBuffer buffer) { + buffer.writeByte(guiData.getHand().ordinal()); + } + + @Override + public @NotNull HandGuiData readGuiData(EntityPlayer player, PacketBuffer buffer) { + return new HandGuiData(player, EnumHand.values()[buffer.readByte()]); + } +} diff --git a/src/main/java/com/cleanroommc/modularui/factory/HoloGuiManager.java b/src/main/java/com/cleanroommc/modularui/factory/HoloGuiManager.java new file mode 100644 index 00000000..059fd24f --- /dev/null +++ b/src/main/java/com/cleanroommc/modularui/factory/HoloGuiManager.java @@ -0,0 +1,145 @@ +package com.cleanroommc.modularui.factory; + +import com.cleanroommc.modularui.api.JeiSettings; +import com.cleanroommc.modularui.api.UIFactory; +import com.cleanroommc.modularui.holoui.HoloScreenEntity; +import com.cleanroommc.modularui.holoui.HoloUI; +import com.cleanroommc.modularui.holoui.ScreenEntityRender; +import com.cleanroommc.modularui.network.NetworkHandler; +import com.cleanroommc.modularui.network.packets.OpenGuiPacket; +import com.cleanroommc.modularui.screen.*; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widget.WidgetTree; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.event.entity.player.PlayerContainerEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import io.netty.buffer.Unpooled; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class HoloGuiManager extends GuiManager { + + + private static GuiScreenWrapper lastMui; + + public static void open(@NotNull UIFactory factory, @NotNull T guiData, EntityPlayerMP player) { + if (player instanceof FakePlayer) return; + // create panel, collect sync handlers and create container + guiData.setJeiSettings(JeiSettings.DUMMY); + PanelSyncManager syncManager = new PanelSyncManager(); + ModularPanel panel = factory.createPanel(guiData, syncManager); + List screens = player.world.getEntities(HoloScreenEntity.class, entity -> entity.isName(panel.getName())); + if (!screens.isEmpty()) { + for (HoloScreenEntity screen : screens) { + screen.setDead(); + } + /*HoloUI.builder() + .inFrontOf(player, 5, true) + .reposition(player, screens); + NetworkHandler.sendToPlayer(new SyncHoloPacket(panel.getName()), player); + ModularUI.LOGGER.warn("reposition the holo, sync to client"); + return;*/ + } + WidgetTree.collectSyncValues(syncManager, panel); + ModularContainer container = new ModularContainer(player, syncManager, panel.getName()); + HoloUI.builder() + .screenScale(0.5f) + .inFrontOf(player, 5, true) + .open(screen -> { + screen.setContainer(container); + screen.setPanel(panel); + //HoloUI.registerSyncedHoloUI(panel, screen); + }, player.getEntityWorld()); + // sync to client +// player.getNextWindowId(); +// player.closeContainer(); +// int windowId = player.currentWindowId; + PacketBuffer buffer = new PacketBuffer(Unpooled.buffer()); + factory.writeGuiData(guiData, buffer); + NetworkHandler.sendToPlayer(new OpenGuiPacket<>(0, factory, buffer), player); + // open container // this mimics forge behaviour +// player.openContainer = container; +// player.openContainer.windowId = windowId; +// player.openContainer.addListener(player); + // finally invoke event + MinecraftForge.EVENT_BUS.post(new PlayerContainerEvent.Open(player, container)); + } + + @SideOnly(Side.CLIENT) + public static void open(int windowId, @NotNull UIFactory factory, @NotNull PacketBuffer data, @NotNull EntityPlayerSP player) { + T guiData = factory.readGuiData(player, data); + JeiSettingsImpl jeiSettings = new JeiSettingsImpl(); + guiData.setJeiSettings(jeiSettings); + PanelSyncManager syncManager = new PanelSyncManager(); + ModularPanel panel = factory.createPanel(guiData, syncManager); + WidgetTree.collectSyncValues(syncManager, panel); + ModularScreen screen = factory.createScreen(guiData, panel); + screen.getContext().setJeiSettings(jeiSettings); + GuiContainerWrapper guiScreenWrapper = new GuiContainerWrapper(new ModularContainer(player, syncManager, panel.getName()), screen); + guiScreenWrapper.inventorySlots.windowId = windowId; + HoloUI.builder() +// .screenScale(0.25f) + .inFrontOf(player, 5, true) + .screenScale(0.5f) + .open(screen1 -> { + screen1.setPanel(panel); + screen1.setWrapper(guiScreenWrapper); + //HoloUI.registerSyncedHoloUI(panel, screen1); + }, player.getEntityWorld()); + } + + public static void reposition(String panel, EntityPlayer player) { + HoloUI.builder() +// .screenScale(0.25f) + .inFrontOf(player, 5, true) + .reposition(player, player.world.getEntities(HoloScreenEntity.class, entity -> entity.isName(panel))); + } + + //todo make this a mixin instead of using event to cancel arm animation stuff + @SideOnly(Side.CLIENT) + @SubscribeEvent + public static void onClick(InputEvent.MouseInputEvent event) { + var player = Minecraft.getMinecraft().player; + if (player != null && player.getHeldItemMainhand().isEmpty() && player.getHeldItemOffhand().isEmpty()) { + ScreenEntityRender.clickScreen(player); + } + } + + + @SideOnly(Side.CLIENT) + @SubscribeEvent + public static void onGuiOpen(GuiOpenEvent event) { + if (lastMui != null && event.getGui() == null) { + if (lastMui.getScreen().getPanelManager().isOpen()) { + lastMui.getScreen().getPanelManager().closeAll(); + } + lastMui.getScreen().getPanelManager().dispose(); + lastMui = null; + } else if (event.getGui() instanceof GuiScreenWrapper screenWrapper) { + if (lastMui == null) { + lastMui = screenWrapper; + } else if (lastMui == event.getGui()) { + lastMui.getScreen().getPanelManager().reopen(); + } else { + if (lastMui.getScreen().getPanelManager().isOpen()) { + lastMui.getScreen().getPanelManager().closeAll(); + } + lastMui.getScreen().getPanelManager().dispose(); + lastMui = screenWrapper; + } + } + } +} diff --git a/src/main/java/com/cleanroommc/modularui/holoui/HoloScreenEntity.java b/src/main/java/com/cleanroommc/modularui/holoui/HoloScreenEntity.java index 33d68fa8..5b17efcc 100644 --- a/src/main/java/com/cleanroommc/modularui/holoui/HoloScreenEntity.java +++ b/src/main/java/com/cleanroommc/modularui/holoui/HoloScreenEntity.java @@ -1,8 +1,6 @@ package com.cleanroommc.modularui.holoui; -import com.cleanroommc.modularui.screen.GuiContainerWrapper; -import com.cleanroommc.modularui.screen.ModularContainer; -import com.cleanroommc.modularui.screen.ModularScreen; +import com.cleanroommc.modularui.screen.*; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; @@ -27,7 +25,8 @@ public class HoloScreenEntity extends Entity { private GuiContainerWrapper wrapper; - private ModularScreen screen; + private ModularContainer container; + private ModularPanel panel; private final Plane3D plane3D; private static final DataParameter ORIENTATION = EntityDataManager.createKey(HoloScreenEntity.class, DataSerializers.BYTE); @@ -40,14 +39,24 @@ public HoloScreenEntity(World world) { this(world, new Plane3D()); } - public void setScreen(ModularScreen screen) { - this.screen = screen; - this.wrapper = new GuiContainerWrapper(new ModularContainer(null), screen); + public void setWrapper(GuiContainerWrapper wrapper) { + this.wrapper = wrapper; this.wrapper.setWorldAndResolution(Minecraft.getMinecraft(), (int) this.plane3D.getWidth(), (int) this.plane3D.getHeight()); + this.getScreen().getContext().holoScreen = this; + this.getScreen().getContext().isHoloScreen = true; + setContainer(wrapper.getScreen().getContainer()); + } + + public void setContainer(ModularContainer container) { + this.container = container; + } + + public void setPanel(ModularPanel panel) { + this.panel = panel; } public ModularScreen getScreen() { - return this.screen; + return this.getWrapper().getScreen(); } public GuiContainerWrapper getWrapper() { @@ -66,6 +75,11 @@ public ScreenOrientation getOrientation() { return ScreenOrientation.values()[this.dataManager.get(ORIENTATION)]; } + public boolean isName(String name) { + if (this.panel == null) return false; + return this.panel.getName().equals(name); + } + public Plane3D getPlane3D() { return this.plane3D; } @@ -84,18 +98,22 @@ public void onEntityUpdate() { this.prevPosZ = this.posZ; this.prevRotationPitch = this.rotationPitch; this.prevRotationYaw = this.rotationYaw; - if (this.world.isRemote) { - this.extinguish(); - } + if (this.posY < -64.0D) { this.outOfWorld(); } if (this.world.isRemote) { + this.extinguish(); int w = (int) this.plane3D.getWidth(), h = (int) this.plane3D.getHeight(); + if (this.wrapper == null) { + this.getEntityWorld().removeEntity(this); + return; + } if (w != this.wrapper.width || h != this.wrapper.height) { this.wrapper.onResize(Minecraft.getMinecraft(), w, h); } + this.wrapper.getScreen().onUpdate(); } this.firstUpdate = false; diff --git a/src/main/java/com/cleanroommc/modularui/holoui/HoloUI.java b/src/main/java/com/cleanroommc/modularui/holoui/HoloUI.java index 085aa86c..946a649d 100644 --- a/src/main/java/com/cleanroommc/modularui/holoui/HoloUI.java +++ b/src/main/java/com/cleanroommc/modularui/holoui/HoloUI.java @@ -1,18 +1,14 @@ package com.cleanroommc.modularui.holoui; -import com.cleanroommc.modularui.screen.JeiSettingsImpl; -import com.cleanroommc.modularui.screen.ModularScreen; - -import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.ApiStatus; -import java.util.Map; -import java.util.function.Supplier; +import java.util.Collection; +import java.util.function.Consumer; /** * Highly experimental @@ -20,12 +16,6 @@ @ApiStatus.Experimental public class HoloUI { - private static final Map> syncedHolos = new Object2ObjectOpenHashMap<>(); - - public static void registerSyncedHoloUI(ResourceLocation loc, Supplier screen) { - syncedHolos.put(loc, screen); - } - public static Builder builder() { return new Builder(); } @@ -43,9 +33,17 @@ public Builder at(double x, double y, double z) { return this; } + public Builder at(BlockPos pos) { + this.x = pos.getX() + 0.5D; + this.y = pos.getY() + 0.5D; + this.z = pos.getZ() + 0.5D; + return this; + } + public Builder inFrontOf(EntityPlayer player, double distance, boolean fixed) { Vec3d look = player.getLookVec(); this.orientation = fixed ? ScreenOrientation.FIXED : ScreenOrientation.TO_PLAYER; + if (fixed) plane3D.setNormal((float) -look.x, 0, (float) -look.z); return at(player.posX + look.x * distance, player.posY + player.getEyeHeight() + look.y * distance, player.posZ + look.z * distance); } @@ -80,15 +78,32 @@ public Builder plane(Plane3D plane) { return this; } - public void open(ModularScreen screen) { - JeiSettingsImpl jeiSettings = new JeiSettingsImpl(); - jeiSettings.disableJei(); - screen.getContext().setJeiSettings(jeiSettings); - HoloScreenEntity holoScreenEntity = new HoloScreenEntity(Minecraft.getMinecraft().world, this.plane3D); - holoScreenEntity.setPosition(this.x, this.y, this.z); - holoScreenEntity.setScreen(screen); - holoScreenEntity.spawnInWorld(); - holoScreenEntity.setOrientation(this.orientation); + public void open(Consumer entityConsumer, World world) { +// JeiSettingsImpl jeiSettings = new JeiSettingsImpl(); +// jeiSettings.disableJei(); +// screen.getContext().setJeiSettings(jeiSettings); + +// wrapper.getScreen().getContext().isHoloScreen = true; + HoloScreenEntity screen = new HoloScreenEntity(world, this.plane3D); + screen.setPosition(this.x, this.y, this.z); + screen.setOrientation(this.orientation); + entityConsumer.accept(screen); + screen.spawnInWorld(); +// holoScreenEntity.setPosition(this.x, this.y, this.z); +// holoScreenEntity.setWrapper(wrapper); +// holoScreenEntity.spawnInWorld(); +// holoScreenEntity.setOrientation(this.orientation); + } + + public void reposition(EntityPlayer player, Collection screens) { + for (HoloScreenEntity screen : screens) { + screen.setPosition(this.x, this.y, this.z); + screen.setOrientation(this.orientation); + if (player.world.isRemote) { + var vec = screen.getPositionVector().subtract(player.getPositionVector()); + screen.getPlane3D().setNormal((float) -vec.x, 0, (float) -vec.z); + } + } } } } diff --git a/src/main/java/com/cleanroommc/modularui/holoui/Plane3D.java b/src/main/java/com/cleanroommc/modularui/holoui/Plane3D.java index 7fcaa70d..f2a2ab41 100644 --- a/src/main/java/com/cleanroommc/modularui/holoui/Plane3D.java +++ b/src/main/java/com/cleanroommc/modularui/holoui/Plane3D.java @@ -4,8 +4,11 @@ import com.cleanroommc.modularui.utils.Matrix4f; +import com.cleanroommc.modularui.utils.Vector3f; + import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.math.Vec3d; import org.jetbrains.annotations.ApiStatus; /** @@ -17,9 +20,15 @@ public class Plane3D { private float w = 480, h = 270; private float scale = 1f; private float aX = 0.5f, aY = 0.5f; - private float nX = 0, nY = 0, nZ = 1; + private Vec3d normal = Direction.NORTH.asVec3d(); + private Vec3d rotation = this.normal; + + + public void transform() { + transform(this.normal, Direction.ORIGIN.asVec3d()); + } - public void transformRectangle() { + public void transform(Vec3d target, Vec3d orig) { // translate to anchor GlStateManager.translate(-this.w * this.aX, -this.h * this.aY, 0); // translate for scale and rotation @@ -28,20 +37,26 @@ public void transformRectangle() { GlStateManager.scale(0.0625 * this.scale, 0.0625 * this.scale, 0.0625 * this.scale); // rotate 180 deg GlStateManager.rotate(180, 0, 0, 1); + // apply facing direction - if (this.nX != 0 || this.nY != 0 || this.nZ != 1) { - Matrix4f rotation = new Matrix4f(); - rotation.m00 = -this.nZ + (this.nY * this.nY * (1 + this.nZ)) / (this.nX * this.nX + this.nY * this.nY); - rotation.m10 = -(this.nX * this.nY * (1 + this.nZ)) / (this.nX * this.nX + this.nY * this.nY); - rotation.m20 = this.nX; - rotation.m01 = -(this.nX * this.nY * (1 + this.nZ)) / (this.nX * this.nX + this.nY * this.nY); - rotation.m11 = -this.nZ + (this.nX * this.nX * (1 + this.nZ)) / (this.nX * this.nX + this.nY * this.nY); - rotation.m21 = this.nY; - rotation.m02 = -this.nX; - rotation.m12 = -this.nY; - rotation.m22 = -this.nZ; - GuiUtils.applyTransformationMatrix(rotation); - } + // handle yaw (left-right) + Vec3d diff = orig.subtract(target); + double yaw = Math.atan(diff.z / diff.x); + if (diff.x < 0) yaw += (Math.PI / 2); + else yaw -= (Math.PI / 2); + + // handle pitch (up-down) + Vec3d vec = new Vec3d(diff.x, 0, diff.z); + double pitch = Math.atan(diff.y / vec.length()); + this.rotation = new Vec3d(pitch, yaw, 0); + + Matrix4f mYaw = new Matrix4f() + .rotate((float) yaw, Direction.UP.asVector3f()); + Matrix4f mPitch = new Matrix4f() + .rotate((float) pitch, Direction.EAST.asVector3f()); + + GuiUtils.applyTransformationMatrix(mYaw); + GuiUtils.applyTransformationMatrix(mPitch); // un-translate for scale and rotation GlStateManager.translate(-(this.w / 2f), -(this.h / 2f), 0); } @@ -64,16 +79,11 @@ public void setHeightWithProp(float h) { } public void setNormal(float x, float y, float z) { - float square = x * x + y * y + z * z; - if (square != 1) { - float factor = (float) Math.sqrt(square); - x /= factor; - y /= factor; - z /= factor; - } - this.nX = x; - this.nY = y; - this.nZ = z; + this.normal = new Vec3d(x, y, z).normalize(); + } + + public Vec3d getRotation() { + return this.rotation; } public void setAnchor(float x, float y) { @@ -96,4 +106,29 @@ public void setScale(float scale) { public float getScale() { return this.scale; } + + public enum Direction { + ORIGIN(0, 0, 0), + UP(0, 1, 0), + DOWN(0, -1, 0), + NORTH(0, 0, -1), + SOUTH(0, 0, 1), + EAST(1, 0, 0), + WEST(-1, 0, 0); + + private final Vector3f vector3f; + private final Vec3d vec3d; + Direction(float x, float y, float z) { + vector3f = new Vector3f(x, y, z); + vec3d = new Vec3d(x, y, z); + } + + public Vector3f asVector3f() { + return vector3f; + } + + public Vec3d asVec3d() { + return vec3d; + } + } } diff --git a/src/main/java/com/cleanroommc/modularui/holoui/ScreenEntityRender.java b/src/main/java/com/cleanroommc/modularui/holoui/ScreenEntityRender.java index a8e389f4..fffd7958 100644 --- a/src/main/java/com/cleanroommc/modularui/holoui/ScreenEntityRender.java +++ b/src/main/java/com/cleanroommc/modularui/holoui/ScreenEntityRender.java @@ -1,23 +1,34 @@ package com.cleanroommc.modularui.holoui; import com.cleanroommc.modularui.screen.GuiContainerWrapper; +import com.cleanroommc.modularui.utils.Animator; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.culling.ICamera; import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.crash.CrashReport; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ReportedException; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Map; +import java.util.UUID; + /** * Highly experimental */ @ApiStatus.Experimental public class ScreenEntityRender extends Render { + private static final Map lookingPlayers = new Object2ObjectOpenHashMap<>(); public ScreenEntityRender(RenderManager renderManager) { super(renderManager); @@ -33,19 +44,101 @@ protected ResourceLocation getEntityTexture(@NotNull HoloScreenEntity entity) { public void doRender(@NotNull HoloScreenEntity entity, double x, double y, double z, float entityYaw, float partialTicks) { GuiContainerWrapper screenWrapper = entity.getWrapper(); if (screenWrapper == null) return; + var screen = screenWrapper.getScreen(); Plane3D plane3D = entity.getPlane3D(); - if (entity.getOrientation() == ScreenOrientation.TO_PLAYER) { - EntityPlayer player = Minecraft.getMinecraft().player; - float xN = (float) (player.posX - entity.posX); - float yN = (float) (player.posY - entity.posY); - float zN = (float) (player.posZ - entity.posZ); - plane3D.setNormal(xN, yN, zN); - } GlStateManager.pushMatrix(); GlStateManager.translate(x, y, z); - plane3D.transformRectangle(); - screenWrapper.drawScreen(0, 0, partialTicks); + EntityPlayer player = Minecraft.getMinecraft().player; + if (entity.getOrientation() == ScreenOrientation.TO_PLAYER) { + plane3D.transform(player.getPositionVector(), entity.getPositionVector()); + } else { + plane3D.transform(); + } + var mouse = calculateMousePos(player.getPositionVector().add(0, player.getEyeHeight(), 0), entity, player.getLookVec()); +// screenWrapper.drawScreen(mouse.getX(), mouse.getY(), partialTicks); + screen.drawScreen(mouse.getX(), mouse.getY(), partialTicks); + screen.onFrameUpdate(); + + UUID id = player.getUniqueID(); + Animator.advance(); + if (withinScreen(mouse, entity.getPlane3D()) && !lookingPlayers.containsKey(id)) { + lookingPlayers.put(id, screenWrapper); + } else if (!withinScreen(mouse, entity.getPlane3D())) { + lookingPlayers.remove(id); + } GlStateManager.popMatrix(); } + + public static void clickScreen(EntityPlayer player) { + if (lookingPlayers.containsKey(player.getUniqueID())) { + try { + lookingPlayers.get(player.getUniqueID()).handleMouseInput(); + } catch (Throwable throwable1) { + CrashReport c = CrashReport.makeCrashReport(throwable1, "Updating screen events"); + c.makeCategory("Affected screen") + .addDetail("Screen name", () -> lookingPlayers.get(player.getUniqueID()).getClass().getCanonicalName()); + throw new ReportedException(c); + } + } + } + + @Override + public boolean shouldRender(HoloScreenEntity screen, ICamera camera, double camX, double camY, double camZ) { + boolean render = super.shouldRender(screen, camera, camX, camY, camZ); + if (!render) { + lookingPlayers.remove(Minecraft.getMinecraft().player.getUniqueID()); + } + return render; + } + + private static Vec3i calculateMousePos(Vec3d player, HoloScreenEntity screen, Vec3d looking) { + var holoPos = screen.getPositionVector(); + var plane = screen.getPlane3D(); + var planeRot = plane.getRotation(); + + // get the difference of the player's eye position and holo position + // rotate diff based on plane rotation + double worldAngle = calculateAngle(holoPos.x, holoPos.z); + double verticalAngle = calculateAngle(holoPos.y, holoPos.z); + var posR = player.rotateYaw((float) (planeRot.y - worldAngle)) + .rotatePitch((float) (planeRot.x + verticalAngle)); + var holoR = holoPos.rotateYaw((float) (planeRot.y - worldAngle)) + .rotatePitch((float) (planeRot.x + verticalAngle)); + + // rotate looking so that 0, 0, 0 is facing exactly at the origin of the screen + var lookRot = looking + .rotateYaw((float) (planeRot.y - worldAngle)) + .rotatePitch((float) (planeRot.x + verticalAngle)); + + // x should be the left-right offset from the player to the holo screen + // y should be the up-down offset from the player to the holo screen + // z should be the distance from the player to the holo screen's plane + var diff = holoR.subtract(posR); + + // the x, y of look rot should be the mouse pos if scaled by looRot z + // the scale factor should be the distance from the player to the plane by the z component of lookRot + double sf = diff.z / lookRot.z; + double mX = ((lookRot.x * sf) - diff.x) * 16 / plane.getScale(); + double mY = ((lookRot.y * sf) - diff.y) * 16 / plane.getScale(); + mY += plane.getHeight() / 2; + mX += plane.getWidth() / 2; + + return new Vec3i(mX, mY, 0); + } + + private static boolean withinScreen(Vec3i mousePos, Plane3D plane) { + return mousePos.getX() > 0 && mousePos.getX() < plane.getWidth() && + mousePos.getY() > 0 && mousePos.getY() < plane.getHeight(); + } + + public static double calculateAngle(double opposite, double adjacent) { + // x is opposite, z is adjacent, theta = atan(x/z) + double a3 = Math.atan(opposite / adjacent); + if (adjacent < 0) { + // if z is negative, the angle returned by atan has to be offset by PI + a3 += opposite < 0 ? -Math.PI : Math.PI; + } + return a3; + } } diff --git a/src/main/java/com/cleanroommc/modularui/network/NetworkHandler.java b/src/main/java/com/cleanroommc/modularui/network/NetworkHandler.java index db83f876..6e950a95 100644 --- a/src/main/java/com/cleanroommc/modularui/network/NetworkHandler.java +++ b/src/main/java/com/cleanroommc/modularui/network/NetworkHandler.java @@ -25,6 +25,7 @@ public static void init() { registerC2S(PacketSyncHandler.class); registerC2S(SyncConfig.class); registerS2C(OpenGuiPacket.class); + registerS2C(SyncHoloPacket.class); //registerC2S(OpenGuiHandshake.class); } diff --git a/src/main/java/com/cleanroommc/modularui/network/packets/OpenGuiPacket.java b/src/main/java/com/cleanroommc/modularui/network/packets/OpenGuiPacket.java index 6d58f071..80677382 100644 --- a/src/main/java/com/cleanroommc/modularui/network/packets/OpenGuiPacket.java +++ b/src/main/java/com/cleanroommc/modularui/network/packets/OpenGuiPacket.java @@ -3,6 +3,8 @@ import com.cleanroommc.modularui.api.UIFactory; import com.cleanroommc.modularui.factory.GuiData; import com.cleanroommc.modularui.factory.GuiManager; +import com.cleanroommc.modularui.factory.HoloGuiFactory; +import com.cleanroommc.modularui.factory.HoloGuiManager; import com.cleanroommc.modularui.network.IPacket; import com.cleanroommc.modularui.network.NetworkHandler; import com.cleanroommc.modularui.network.NetworkUtils; @@ -49,7 +51,11 @@ public void read(PacketBuffer buf) { @SideOnly(Side.CLIENT) @Override public @Nullable IPacket executeClient(NetHandlerPlayClient handler) { - GuiManager.open(this.windowId, this.factory, this.data, Minecraft.getMinecraft().player); + if (this.factory instanceof HoloGuiFactory) { + HoloGuiManager.open(this.windowId, this.factory, this.data, Minecraft.getMinecraft().player); + } else { + GuiManager.open(this.windowId, this.factory, this.data, Minecraft.getMinecraft().player); + } return null; } } diff --git a/src/main/java/com/cleanroommc/modularui/network/packets/SyncHoloPacket.java b/src/main/java/com/cleanroommc/modularui/network/packets/SyncHoloPacket.java new file mode 100644 index 00000000..088547f7 --- /dev/null +++ b/src/main/java/com/cleanroommc/modularui/network/packets/SyncHoloPacket.java @@ -0,0 +1,41 @@ +package com.cleanroommc.modularui.network.packets; + +import com.cleanroommc.modularui.factory.HoloGuiManager; +import com.cleanroommc.modularui.network.IPacket; + +import com.cleanroommc.modularui.network.NetworkUtils; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.PacketBuffer; + +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; + +public class SyncHoloPacket implements IPacket { + + String panel; + + public SyncHoloPacket() {} + + public SyncHoloPacket(String panel) { + this.panel = panel; + } + + @Override + public void write(PacketBuffer buf) throws IOException { + NetworkUtils.writeStringSafe(buf, this.panel); + } + + @Override + public void read(PacketBuffer buf) throws IOException { + this.panel = NetworkUtils.readStringSafe(buf); + } + + @Override + public @Nullable IPacket executeClient(NetHandlerPlayClient handler) { + HoloGuiManager.reposition(this.panel, Minecraft.getMinecraft().player); + return null; + } +} diff --git a/src/main/java/com/cleanroommc/modularui/screen/viewport/GuiContext.java b/src/main/java/com/cleanroommc/modularui/screen/viewport/GuiContext.java index b66cca73..b46c92b6 100644 --- a/src/main/java/com/cleanroommc/modularui/screen/viewport/GuiContext.java +++ b/src/main/java/com/cleanroommc/modularui/screen/viewport/GuiContext.java @@ -5,6 +5,7 @@ import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.api.widget.IGuiElement; import com.cleanroommc.modularui.screen.ClientScreenHandler; +import com.cleanroommc.modularui.holoui.HoloScreenEntity; import com.cleanroommc.modularui.widget.sizer.Area; import net.minecraft.client.Minecraft; @@ -44,6 +45,8 @@ public static GuiContext getDefault() { /* Render states */ private float partialTicks; private long tick = 0; + public boolean isHoloScreen = false; + public HoloScreenEntity holoScreen = null; public boolean isAbove(IGuiElement widget) { return isMouseAbove(widget.getArea()); diff --git a/src/main/java/com/cleanroommc/modularui/test/TestBlock.java b/src/main/java/com/cleanroommc/modularui/test/TestBlock.java index 9b9c742f..8417d9ec 100644 --- a/src/main/java/com/cleanroommc/modularui/test/TestBlock.java +++ b/src/main/java/com/cleanroommc/modularui/test/TestBlock.java @@ -40,6 +40,7 @@ public static void preInit() { testItemBlock.setRegistryName(rl); GameRegistry.registerTileEntity(TestTile.class, rl); TestItem.testItem.setRegistryName(ModularUI.ID, "test_item"); + TestHoloItem.testHoloItem.setRegistryName(ModularUI.ID, "test_holo_item"); } @SubscribeEvent @@ -53,12 +54,14 @@ public static void registerItems(RegistryEvent.Register event) { IForgeRegistry registry = event.getRegistry(); registry.register(testItemBlock); registry.register(TestItem.testItem); + registry.register(TestHoloItem.testHoloItem); } @SubscribeEvent public static void registerModel(ModelRegistryEvent event) { ModelResourceLocation mrl = new ModelResourceLocation(new ResourceLocation("diamond"), "inventory"); ModelLoader.setCustomModelResourceLocation(TestItem.testItem, 0, mrl); + ModelLoader.setCustomModelResourceLocation(TestHoloItem.testHoloItem, 0, mrl); } public TestBlock() { diff --git a/src/main/java/com/cleanroommc/modularui/test/TestHoloItem.java b/src/main/java/com/cleanroommc/modularui/test/TestHoloItem.java new file mode 100644 index 00000000..6d766c92 --- /dev/null +++ b/src/main/java/com/cleanroommc/modularui/test/TestHoloItem.java @@ -0,0 +1,31 @@ +package com.cleanroommc.modularui.test; + +import com.cleanroommc.modularui.factory.HoloGuiFactory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; + +public class TestHoloItem extends TestItem { + + public static final TestHoloItem testHoloItem = new TestHoloItem(); + + public TestHoloItem() { + setTranslationKey("mui.test_holo"); + } + + @NotNull + @Override + public ActionResult onItemRightClick(World world, @NotNull EntityPlayer player, @NotNull EnumHand hand) { + if (!world.isRemote) { + HoloGuiFactory.open((EntityPlayerMP) player, hand); + } + return new ActionResult<>(EnumActionResult.SUCCESS, player.getHeldItem(hand)); + } +} diff --git a/src/main/java/com/cleanroommc/modularui/test/TestItem.java b/src/main/java/com/cleanroommc/modularui/test/TestItem.java index e61f93aa..ba142528 100644 --- a/src/main/java/com/cleanroommc/modularui/test/TestItem.java +++ b/src/main/java/com/cleanroommc/modularui/test/TestItem.java @@ -38,6 +38,10 @@ public class TestItem extends Item implements IGuiHolder { public static final TestItem testItem = new TestItem(); + public TestItem() { + setTranslationKey("mui.test"); + } + @Override public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager) { IItemHandlerModifiable itemHandler = (IItemHandlerModifiable) guiData.getUsedItemStack().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); diff --git a/src/main/java/com/cleanroommc/modularui/widgets/ItemSlot.java b/src/main/java/com/cleanroommc/modularui/widgets/ItemSlot.java index e6e41443..01ecf52c 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/ItemSlot.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/ItemSlot.java @@ -220,8 +220,10 @@ private void drawSlot(Slot slotIn) { } } - ((GuiAccessor) guiScreen).setZLevel(100f); - renderItem.zLevel = 100.0F; + float z = 100f; + float zStart = ((GuiAccessor) guiScreen).getZLevel(); + ((GuiAccessor) guiScreen).setZLevel(zStart + z); + renderItem.zLevel += z; if (!flag1) { if (flag) { @@ -231,7 +233,9 @@ private void drawSlot(Slot slotIn) { if (!itemstack.isEmpty()) { GlStateManager.enableDepth(); // render the item itself - renderItem.renderItemAndEffectIntoGUI(guiScreen.mc.player, itemstack, 1, 1); +// renderItem.renderItemAndEffectIntoGUI(guiScreen.mc.player, itemstack, 1, 1); +// guiScreen.getItemRenderer().renderItemAndEffectIntoGUI(guiScreen.mc.player, itemstack, 1, 1); + renderItem.renderItemIntoGUI(itemstack, 1, 1); if (amount < 0) { amount = itemstack.getCount(); } @@ -272,8 +276,8 @@ private void drawSlot(Slot slotIn) { } } - ((GuiAccessor) guiScreen).setZLevel(0f); - renderItem.zLevel = 0f; + ((GuiAccessor) guiScreen).setZLevel(zStart); + renderItem.zLevel -= z; } @Override