/* * The MIT License (MIT) * * Copyright (c) 2014 - 2017 Dries K. Aka Dries007 * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package net.dries007.holoInventory.client; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import net.dries007.holoInventory.Helper; import net.dries007.holoInventory.HoloInventory; import net.dries007.holoInventory.client.renderers.FakeRenderer; import net.dries007.holoInventory.client.renderers.IRenderer; import net.dries007.holoInventory.client.renderers.RenderHelper; import net.dries007.holoInventory.network.request.EntityRequest; import net.dries007.holoInventory.network.request.TileRequest; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.settings.KeyBinding; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.client.settings.KeyConflictContext; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.InputEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.lwjgl.input.Keyboard; import java.lang.ref.WeakReference; import java.text.DecimalFormat; import java.util.concurrent.TimeUnit; @SideOnly(Side.CLIENT) public class ClientEventHandler { public static final DecimalFormat DF = new DecimalFormat("#.#"); public static final int TEXT_COLOR = 0xFFFFFFFF; //255 + (255 << 8) + (255 << 16) + (255 << 24); public static final int TEXT_COLOR_LIGHT = 0xFFFFFFFF; //255 + (255 << 8) + (255 << 16) + (255 << 24); private static final Cache<BlockPos, IRenderer> TILE_CACHE = CacheBuilder.newBuilder().maximumSize(150).expireAfterWrite(500, TimeUnit.MILLISECONDS).build(); private static final Cache<Integer, IRenderer> ENTITY_CACHE = CacheBuilder.newBuilder().maximumSize(150).expireAfterWrite(500, TimeUnit.MILLISECONDS).build(); private static ClientEventHandler instance; private static boolean enabled = true; private static boolean toggleState = true; private static KeyBinding keyHold; private static KeyBinding keyToggle; private WeakReference<WorldClient> worldRef = new WeakReference<>(null); private ClientEventHandler() { } public static void init() { if (instance != null) MinecraftForge.EVENT_BUS.unregister(instance); instance = new ClientEventHandler(); MinecraftForge.EVENT_BUS.register(new ClientEventHandler()); keyHold = new KeyBinding("Hold to show", KeyConflictContext.IN_GAME, Keyboard.KEY_H, HoloInventory.MODID); keyToggle = new KeyBinding("Toggle to show", KeyConflictContext.IN_GAME, 0, HoloInventory.MODID); ClientRegistry.registerKeyBinding(keyHold); ClientRegistry.registerKeyBinding(keyToggle); } public static void cache(BlockPos pos, IRenderer iRenderer) { TILE_CACHE.put(pos, iRenderer); } public static void cache(int id, IRenderer iRenderer) { ENTITY_CACHE.put(id, iRenderer); } @SubscribeEvent public void onKeyInput(InputEvent.KeyInputEvent event) { if (keyToggle.isPressed()) toggleState = !toggleState; if (keyHold.isKeyDown()) enabled = true; } @SubscribeEvent public void updateEvent(TickEvent.ClientTickEvent event) { if (event.phase == TickEvent.Phase.END) return; Minecraft mc = Minecraft.getMinecraft(); if (mc.isGamePaused()) return; WorldClient mcWorld = Minecraft.getMinecraft().world; if (mcWorld == null) return; WorldClient world = worldRef.get(); if (world == null || mcWorld != world) { TILE_CACHE.invalidateAll(); ENTITY_CACHE.invalidateAll(); worldRef = new WeakReference<>(mcWorld); return; } enabled = (Helper.showOnSneak && mc.gameSettings.keyBindSneak.isKeyDown()) || (Helper.showOnSprint && mc.gameSettings.keyBindSprint.isKeyDown()) || (keyHold.getKeyCode() != 0 && keyHold.isKeyDown()) || (keyToggle.getKeyCode() != 0 && toggleState) || (!Helper.showOnSneak && !Helper.showOnSprint && keyHold.getKeyCode() == 0 && keyToggle.getKeyCode() == 0); if (!enabled) return; TILE_CACHE.cleanUp(); ENTITY_CACHE.cleanUp(); RayTraceResult ray = mc.objectMouseOver; if (ray == null) return; if (ray.typeOfHit == RayTraceResult.Type.BLOCK) { final TileEntity tileEntity = world.getTileEntity(ray.getBlockPos()); if (tileEntity == null || !Helper.accept(tileEntity) || Helper.banned.contains(tileEntity.getClass().getCanonicalName())) return; HoloInventory.getSnw().sendToServer(new TileRequest(world.provider.getDimension(), ray.getBlockPos())); } else if (ray.typeOfHit == RayTraceResult.Type.ENTITY && Helper.accept(ray.entityHit)) { HoloInventory.getSnw().sendToServer(new EntityRequest(world.provider.getDimension(), ray.entityHit.getEntityId())); } } @SubscribeEvent public void renderEvent(RenderWorldLastEvent event) { if (worldRef.get() == null || !enabled) return; Minecraft mc = Minecraft.getMinecraft(); RayTraceResult ray = mc.objectMouseOver; if (ray == null) return; if (ray.typeOfHit == RayTraceResult.Type.BLOCK) { final IRenderer renderer = TILE_CACHE.getIfPresent(ray.getBlockPos()); if (renderer == null || !renderer.shouldRender()) return; try { RenderHelper.start(); renderer.render(worldRef.get(), ray, ray.hitVec); } catch (Exception e) { HoloInventory.getLogger().warn("Some error while rendering the hologram :("); HoloInventory.getLogger().warn("INFO: Block @ {}", ray.getBlockPos()); HoloInventory.getLogger().warn("Please make an issue on github if this happens."); HoloInventory.getLogger().catching(e); TILE_CACHE.put(ray.getBlockPos(), new FakeRenderer()); // This should cut back on console spam } finally { RenderHelper.end(); } } else if (ray.typeOfHit == RayTraceResult.Type.ENTITY) { final IRenderer renderer = ENTITY_CACHE.getIfPresent(ray.entityHit.getEntityId()); if (renderer == null || !renderer.shouldRender()) return; try { RenderHelper.start(); renderer.render(worldRef.get(), ray, ray.hitVec); } catch (Exception e) { HoloInventory.getLogger().warn("Some error while rendering the hologram :("); HoloInventory.getLogger().warn("INFO: Entity: {}", ray.entityHit); HoloInventory.getLogger().warn("Please make an issue on github if this happens."); HoloInventory.getLogger().catching(e); ENTITY_CACHE.put(ray.entityHit.getEntityId(), new FakeRenderer()); // This should cut back on console spam } finally { RenderHelper.end(); } } } }