diff --git a/src/main/java/cr0s/warpdrive/Commons.java b/src/main/java/cr0s/warpdrive/Commons.java index 8fe56f89..a877b3e8 100644 --- a/src/main/java/cr0s/warpdrive/Commons.java +++ b/src/main/java/cr0s/warpdrive/Commons.java @@ -473,4 +473,11 @@ public class Commons { return null; } + + public static int colorARGBtoInt(final int alpha, final int red, final int green, final int blue) { + return (clamp(0, 255, alpha) << 24) + + (clamp(0, 255, red ) << 16) + + (clamp(0, 255, green) << 8) + + clamp(0, 255, blue ); + } } diff --git a/src/main/java/cr0s/warpdrive/WarpDrive.java b/src/main/java/cr0s/warpdrive/WarpDrive.java index 2f77be13..549a1e70 100644 --- a/src/main/java/cr0s/warpdrive/WarpDrive.java +++ b/src/main/java/cr0s/warpdrive/WarpDrive.java @@ -138,6 +138,7 @@ import cr0s.warpdrive.render.RenderBlockOmnipanel; import cr0s.warpdrive.render.RenderBlockStandard; import cr0s.warpdrive.render.RenderOverlayAir; import cr0s.warpdrive.render.RenderOverlayCamera; +import cr0s.warpdrive.render.RenderOverlayLocation; import cr0s.warpdrive.world.BiomeSpace; import cr0s.warpdrive.world.HyperSpaceWorldGenerator; import cr0s.warpdrive.world.HyperSpaceWorldProvider; @@ -308,6 +309,7 @@ public class WarpDrive implements LoadingCallback { if (event.getSide() == Side.CLIENT) { MinecraftForge.EVENT_BUS.register(new RenderOverlayAir()); MinecraftForge.EVENT_BUS.register(new RenderOverlayCamera()); + MinecraftForge.EVENT_BUS.register(new RenderOverlayLocation()); FMLCommonHandler.instance().bus().register(new ClientCameraHandler()); diff --git a/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java b/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java index 564262e5..4c9393bd 100644 --- a/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java +++ b/src/main/java/cr0s/warpdrive/config/WarpDriveConfig.java @@ -36,6 +36,7 @@ import cr0s.warpdrive.config.structures.StructureManager; import cr0s.warpdrive.data.CelestialObject; import cr0s.warpdrive.data.CelestialObjectManager; import cr0s.warpdrive.data.EnumShipMovementType; +import cr0s.warpdrive.data.EnumDisplayAlignment; import cr0s.warpdrive.network.PacketHandler; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; @@ -142,6 +143,17 @@ public class WarpDriveConfig { public static boolean RECIPES_ENABLE_HARD_IC2 = false; public static boolean RECIPES_ENABLE_VANILLA = false; + // Client + public static String CLIENT_LOCATION_FORMAT = "§l"; + public static int CLIENT_LOCATION_COLOR = Commons.colorARGBtoInt(230, 192, 192, 240); + public static boolean CLIENT_LOCATION_HAS_SHADOW = true; + public static EnumDisplayAlignment CLIENT_LOCATION_SCREEN_ALIGNMENT = EnumDisplayAlignment.MIDDLE_RIGHT; + public static int CLIENT_LOCATION_SCREEN_OFFSET_X = -50; + public static int CLIENT_LOCATION_SCREEN_OFFSET_Y = 0; + public static EnumDisplayAlignment CLIENT_LOCATION_TEXT_ALIGNMENT = EnumDisplayAlignment.TOP_CENTER; + public static float CLIENT_LOCATION_WIDTH_RATIO = 0.0F; + public static int CLIENT_LOCATION_WIDTH_MIN = 90; + // Logging public static boolean LOGGING_JUMP = false; public static boolean LOGGING_JUMPBLOCKS = false; @@ -473,6 +485,27 @@ public class WarpDriveConfig { RECIPES_ENABLE_IC2 = config.get("recipes", "enable_ic2", RECIPES_ENABLE_IC2, "Original recipes based on IndustrialCraft2 by Cr0s (you need to disable Dynamic recipes to use those, no longer updated)").getBoolean(false); RECIPES_ENABLE_HARD_IC2 = config.get("recipes", "enable_hard_ic2", RECIPES_ENABLE_HARD_IC2, "Harder recipes based on IC2 by YuRaNnNzZZ (you need to disable Dynamic recipes to use those)").getBoolean(false); + // Client + CLIENT_LOCATION_FORMAT = config.get("client", "location_format", CLIENT_LOCATION_FORMAT, + "Format prefix for location title").getString(); + String stringValue = config.get("client", "location_color", String.format("0x%6X", CLIENT_LOCATION_COLOR), + "Hexadecimal color code for location tile and description (0xAARRGGBB where AA is alpha, RR is Red, GG is Green and BB is Blue component)").getString(); + CLIENT_LOCATION_COLOR = (int) ( Long.decode( stringValue ) & 0xFFFFFFFFL ); + CLIENT_LOCATION_HAS_SHADOW = config.get("client", "location_has_shadow", CLIENT_LOCATION_HAS_SHADOW, + "Shadow casting option for current celestial object name").getBoolean(CLIENT_LOCATION_HAS_SHADOW); + CLIENT_LOCATION_SCREEN_ALIGNMENT = EnumDisplayAlignment.valueOf(config.get("client", "location_screen_alignment", CLIENT_LOCATION_SCREEN_ALIGNMENT.name(), + "Alignment on screen: TOP_LEFT, TOP_CENTER, TOP_RIGHT, MIDDLE_LEFT, MIDDLE_CENTER, MIDDLE_RIGHT, BOTTOM_LEFT, BOTTOM_CENTER or BOTTOM_RIGHT").getString()); + CLIENT_LOCATION_SCREEN_OFFSET_X = config.get("client", "location_offset_x", CLIENT_LOCATION_SCREEN_OFFSET_X, + "Horizontal offset on screen, increase to move to the right").getInt(); + CLIENT_LOCATION_SCREEN_OFFSET_Y = config.get("client", "location_offset_y", CLIENT_LOCATION_SCREEN_OFFSET_Y, + "Vertical offset on screen, increase to move down").getInt(); + CLIENT_LOCATION_TEXT_ALIGNMENT = EnumDisplayAlignment.valueOf(config.get("client", "location_text_alignment", CLIENT_LOCATION_TEXT_ALIGNMENT.name(), + "Text alignment: TOP_LEFT, TOP_CENTER, TOP_RIGHT, MIDDLE_LEFT, MIDDLE_CENTER, MIDDLE_RIGHT, BOTTOM_LEFT, BOTTOM_CENTER or BOTTOM_RIGHT").getString()); + CLIENT_LOCATION_WIDTH_RATIO = (float) config.get("client", "location_width_ratio", CLIENT_LOCATION_WIDTH_RATIO, + "Text width as a ratio of full screen width").getDouble(); + CLIENT_LOCATION_WIDTH_MIN = config.get("client", "location_width_min", CLIENT_LOCATION_WIDTH_MIN, + "Text width as a minimum 'pixel' count").getInt(); + // Logging LOGGING_JUMP = config.get("logging", "enable_jump_logs", LOGGING_JUMP, "Basic jump logs, should always be enabled").getBoolean(true); LOGGING_JUMPBLOCKS = config.get("logging", "enable_jumpblocks_logs", LOGGING_JUMPBLOCKS, "Detailed jump logs to help debug the mod, will spam your logs...").getBoolean(false); diff --git a/src/main/java/cr0s/warpdrive/data/CelestialObject.java b/src/main/java/cr0s/warpdrive/data/CelestialObject.java index 7020ef6e..32a4073d 100644 --- a/src/main/java/cr0s/warpdrive/data/CelestialObject.java +++ b/src/main/java/cr0s/warpdrive/data/CelestialObject.java @@ -156,7 +156,7 @@ public class CelestialObject implements Cloneable, IStringSerializable, ICelesti } if (listElements.size() == 1) { final Element elementName = listElements.get(0); - displayName = elementName.getNodeValue(); + displayName = elementName.getTextContent(); } else { displayName = id; } @@ -170,7 +170,7 @@ public class CelestialObject implements Cloneable, IStringSerializable, ICelesti } if (listElements.size() == 1) { final Element elementName = listElements.get(0); - description = elementName.getNodeValue(); + description = elementName.getTextContent(); } else { description = ""; } @@ -185,7 +185,7 @@ public class CelestialObject implements Cloneable, IStringSerializable, ICelesti nbtTagCompound = null; if (listElements.size() == 1) { final Element elementName = listElements.get(0); - final String stringNBT = elementName.getNodeValue(); + final String stringNBT = elementName.getTextContent(); if (!stringNBT.isEmpty()) { try { nbtTagCompound = (NBTTagCompound) JsonToNBT.func_150315_a(stringNBT); @@ -402,12 +402,12 @@ public class CelestialObject implements Cloneable, IStringSerializable, ICelesti @Override public String getDisplayName() { - return displayName; + return displayName == null ? "" : displayName; } @Override public String getDescription() { - return description; + return description == null ? "" : description; } @Override @@ -559,6 +559,9 @@ public class CelestialObject implements Cloneable, IStringSerializable, ICelesti borderRadiusX = nbtTagCompound.getInteger("borderRadiusX"); borderRadiusZ = nbtTagCompound.getInteger("borderRadiusZ"); + displayName = nbtTagCompound.getString("displayName"); + description = nbtTagCompound.getString("description"); + isVirtual = nbtTagCompound.getBoolean("isVirtual"); if (isVirtual) { dimensionId = 0; @@ -606,6 +609,13 @@ public class CelestialObject implements Cloneable, IStringSerializable, ICelesti nbtTagCompound.setInteger("borderRadiusX", borderRadiusX); nbtTagCompound.setInteger("borderRadiusZ", borderRadiusZ); + if (displayName != null && !displayName.isEmpty()) { + nbtTagCompound.setString("displayName", displayName); + } + if (description != null && !description.isEmpty()) { + nbtTagCompound.setString("description", description); + } + nbtTagCompound.setBoolean("isVirtual", isVirtual); if (!isVirtual) { nbtTagCompound.setInteger("dimensionId", dimensionId); diff --git a/src/main/java/cr0s/warpdrive/data/CelestialObjectManager.java b/src/main/java/cr0s/warpdrive/data/CelestialObjectManager.java index 91e901e3..979b78b1 100644 --- a/src/main/java/cr0s/warpdrive/data/CelestialObjectManager.java +++ b/src/main/java/cr0s/warpdrive/data/CelestialObjectManager.java @@ -169,9 +169,8 @@ public class CelestialObjectManager extends XmlFileManager { // *** client side only *** @SideOnly(Side.CLIENT) - public static void readClientSync(final NBTTagCompound nbtTagCompound) { + public static void readClientSync(final NBTTagList nbtTagList) { clearForReload(true); - final NBTTagList nbtTagList = nbtTagCompound.getTagList("celestialObjects", NBT.TAG_COMPOUND); if (nbtTagList != null && nbtTagList.tagCount() > 0) { for (int index = 0; index < nbtTagList.tagCount(); index++) { final CelestialObject celestialObject = new CelestialObject(nbtTagList.getCompoundTagAt(index)); diff --git a/src/main/java/cr0s/warpdrive/data/EnumDisplayAlignment.java b/src/main/java/cr0s/warpdrive/data/EnumDisplayAlignment.java new file mode 100644 index 00000000..347f5358 --- /dev/null +++ b/src/main/java/cr0s/warpdrive/data/EnumDisplayAlignment.java @@ -0,0 +1,24 @@ +package cr0s.warpdrive.data; + + +public enum EnumDisplayAlignment { + TOP_LEFT ("top_left" , 0.0F, 0.0F), + TOP_CENTER ("top_center" , 0.5F, 0.0F), + TOP_RIGHT ("top_right" , 1.0F, 0.0F), + MIDDLE_LEFT ("middle_left" , 0.0F, 0.5F), + MIDDLE_CENTER ("middle_center", 0.5F, 0.5F), + MIDDLE_RIGHT ("middle_right" , 1.0F, 0.5F), + BOTTOM_LEFT ("bottom_left" , 0.0F, 1.0F), + BOTTOM_CENTER ("bottom_center", 0.5F, 1.0F), + BOTTOM_RIGHT ("bottom_right" , 1.0F, 1.0F); + + public final String unlocalizedName; + public final float xRatio; + public final float yRatio; + + EnumDisplayAlignment(final String unlocalizedName, final float xRatio, final float yRatio) { + this.unlocalizedName = unlocalizedName; + this.xRatio = xRatio; + this.yRatio = yRatio; + } +} diff --git a/src/main/java/cr0s/warpdrive/network/MessageClientSync.java b/src/main/java/cr0s/warpdrive/network/MessageClientSync.java index e09f5b7b..73fb9f1a 100644 --- a/src/main/java/cr0s/warpdrive/network/MessageClientSync.java +++ b/src/main/java/cr0s/warpdrive/network/MessageClientSync.java @@ -60,7 +60,7 @@ public class MessageClientSync implements IMessage, IMessageHandler listMessages = minecraft.fontRenderer.listFormattedStringToWidth(textMessage, widthText); + final int heightText = listMessages.size() * minecraft.fontRenderer.FONT_HEIGHT; + + // compute the position + int x = Math.round(scaledWidth * enumScreenAnchor.xRatio + xOffset - enumTextAlignment.xRatio * widthText ); + int y = Math.round(scaledHeight * enumScreenAnchor.yRatio + yOffset - enumTextAlignment.yRatio * heightText); + + // start rendering + GL11.glPushMatrix(); + GL11.glScalef(1.0F, 1.0F, 0.0F); + + for (final String textLine : listMessages) { + minecraft.fontRenderer.drawString(textLine, x, y, colorText, hasShadow); + y += minecraft.fontRenderer.FONT_HEIGHT; + } + + // close rendering + GL11.glPopMatrix(); + + return heightText; + } } \ No newline at end of file diff --git a/src/main/java/cr0s/warpdrive/render/RenderOverlayLocation.java b/src/main/java/cr0s/warpdrive/render/RenderOverlayLocation.java new file mode 100644 index 00000000..e4d1ba46 --- /dev/null +++ b/src/main/java/cr0s/warpdrive/render/RenderOverlayLocation.java @@ -0,0 +1,87 @@ +package cr0s.warpdrive.render; + +import cr0s.warpdrive.config.WarpDriveConfig; +import cr0s.warpdrive.data.CelestialObject; +import cr0s.warpdrive.data.CelestialObjectManager; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.MathHelper; +import org.lwjgl.opengl.GL11; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; + +@SideOnly(Side.CLIENT) +public class RenderOverlayLocation { + + private static Minecraft minecraft = Minecraft.getMinecraft(); + + private void renderLocation(final int widthScreen, final int heightScreen) { + // get player + EntityPlayer entityPlayer = minecraft.thePlayer; + if (entityPlayer == null) { + return; + } + final int x = MathHelper.floor_double(entityPlayer.posX); + final int z = MathHelper.floor_double(entityPlayer.posZ); + + // get celestial object + String name = entityPlayer.worldObj.provider.getDimensionName(); + String description = ""; + final CelestialObject celestialObject = CelestialObjectManager.get(entityPlayer.worldObj, x, z); + if (celestialObject != null) { + if (!celestialObject.getDisplayName().isEmpty()) { + name = celestialObject.getDisplayName(); + } + description = celestialObject.getDescription(); + } + + // start rendering + GL11.glEnable(GL11.GL_BLEND); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + + int yOffset = 0; + // show current location name in bold + yOffset += RenderCommons.drawText(widthScreen, heightScreen, name, + WarpDriveConfig.CLIENT_LOCATION_FORMAT, + WarpDriveConfig.CLIENT_LOCATION_COLOR, + WarpDriveConfig.CLIENT_LOCATION_HAS_SHADOW, + WarpDriveConfig.CLIENT_LOCATION_SCREEN_ALIGNMENT, + WarpDriveConfig.CLIENT_LOCATION_SCREEN_OFFSET_X, + WarpDriveConfig.CLIENT_LOCATION_SCREEN_OFFSET_Y + yOffset, + WarpDriveConfig.CLIENT_LOCATION_TEXT_ALIGNMENT, + WarpDriveConfig.CLIENT_LOCATION_WIDTH_RATIO, + WarpDriveConfig.CLIENT_LOCATION_WIDTH_MIN); + + // show current location description + yOffset += RenderCommons.drawText(widthScreen, heightScreen, description, + "", + WarpDriveConfig.CLIENT_LOCATION_COLOR, + false, + WarpDriveConfig.CLIENT_LOCATION_SCREEN_ALIGNMENT, + WarpDriveConfig.CLIENT_LOCATION_SCREEN_OFFSET_X, + WarpDriveConfig.CLIENT_LOCATION_SCREEN_OFFSET_Y + yOffset, + WarpDriveConfig.CLIENT_LOCATION_TEXT_ALIGNMENT, + WarpDriveConfig.CLIENT_LOCATION_WIDTH_RATIO, + WarpDriveConfig.CLIENT_LOCATION_WIDTH_MIN); + + // @TODO: show orbiting planet? + + // close rendering + minecraft.getTextureManager().bindTexture(Gui.icons); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glDisable(GL11.GL_BLEND); + } + + @SubscribeEvent + public void onRender(RenderGameOverlayEvent.Pre event) { + if (event.type == ElementType.HOTBAR) { + renderLocation(event.resolution.getScaledWidth(), event.resolution.getScaledHeight()); + } + } +} \ No newline at end of file