Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

bewi

Members
  • Joined

  • Last visited

  1. Hi, The spawnEntityIntoClientWorld() function in FMLClientHandler does not work properly for multi-part entities (Entity.getParts() != null). entity.entityId will be set before the offsets are calculated for the parts. This leads to getEntityByID() in NetServerHandler always returning a wrong entity (or null in most cases) for those parts. A simple solution is to move the assignment of the entity ID after the assignments of the parts' ids. public Entity spawnEntityIntoClientWorld(EntityRegistration er, EntitySpawnPacket packet){ /*snip*/ entity = (Entity)(cls.getConstructor(World.class).newInstance(wc)); entity.entityId = packet.entityId; /*snip*/ Entity parts[] = entity.getParts(); if (parts != null) { int i = packet.entityId - entity.entityId; //<- will always be 0 for (int j = 0; j < parts.length; j++) { parts[j].entityId += i; } } /*snip*/ }
  2. I became really annoyed while trying to create a multipart mob and the hitboxes were not visible. It turns out that minecraft does not actually render the hitboxes when pressing F3+B but just a box with a size of width*height*width centered on the mobs position. I modified the code slightly and thought it might be a good idea to incorporate this into forge. Here is the changed function in net.minecraft.client.renderer.entity.RenderManager.java private void func_85094_b(Entity par1Entity, double par2, double par4, double par6, float par8, float par9) { //GL11.glDepthMask(false); GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_CULL_FACE); GL11.glDisable(GL11.GL_BLEND); GL11.glPushMatrix(); Tessellator var10 = Tessellator.instance; var10.startDrawingQuads(); var10.setColorRGBA(255, 255, 255, 32); var10.addVertex(par1Entity.boundingBox.minX, par1Entity.boundingBox.minY, par1Entity.boundingBox.minZ); var10.addVertex(par1Entity.boundingBox.minX, par1Entity.boundingBox.maxY, par1Entity.boundingBox.minZ); var10.addVertex(par1Entity.boundingBox.minX, par1Entity.boundingBox.maxY, par1Entity.boundingBox.maxZ); var10.addVertex(par1Entity.boundingBox.minX, par1Entity.boundingBox.minY, par1Entity.boundingBox.maxZ); var10.addVertex(par1Entity.boundingBox.minX, par1Entity.boundingBox.minY, par1Entity.boundingBox.minZ); var10.addVertex(par1Entity.boundingBox.maxX, par1Entity.boundingBox.minY, par1Entity.boundingBox.minZ); var10.addVertex(par1Entity.boundingBox.maxX, par1Entity.boundingBox.maxY, par1Entity.boundingBox.minZ); var10.addVertex(par1Entity.boundingBox.minX, par1Entity.boundingBox.maxY, par1Entity.boundingBox.minZ); var10.addVertex(par1Entity.boundingBox.maxX, par1Entity.boundingBox.minY, par1Entity.boundingBox.minZ); var10.addVertex(par1Entity.boundingBox.maxX, par1Entity.boundingBox.maxY, par1Entity.boundingBox.minZ); var10.addVertex(par1Entity.boundingBox.maxX, par1Entity.boundingBox.maxY, par1Entity.boundingBox.maxZ); var10.addVertex(par1Entity.boundingBox.maxX, par1Entity.boundingBox.minY, par1Entity.boundingBox.maxZ); var10.addVertex(par1Entity.boundingBox.minX, par1Entity.boundingBox.minY, par1Entity.boundingBox.maxZ); var10.addVertex(par1Entity.boundingBox.maxX, par1Entity.boundingBox.minY, par1Entity.boundingBox.maxZ); var10.addVertex(par1Entity.boundingBox.maxX, par1Entity.boundingBox.maxY, par1Entity.boundingBox.maxZ); var10.addVertex(par1Entity.boundingBox.minX, par1Entity.boundingBox.maxY, par1Entity.boundingBox.maxZ); Entity[] parts = par1Entity.getParts(); if(parts != null) { for(Entity part : parts) { var10.addVertex(part.boundingBox.minX, part.boundingBox.minY, part.boundingBox.minZ); var10.addVertex(part.boundingBox.minX, part.boundingBox.maxY, part.boundingBox.minZ); var10.addVertex(part.boundingBox.minX, part.boundingBox.maxY, part.boundingBox.maxZ); var10.addVertex(part.boundingBox.minX, part.boundingBox.minY, part.boundingBox.maxZ); var10.addVertex(part.boundingBox.minX, part.boundingBox.minY, part.boundingBox.minZ); var10.addVertex(part.boundingBox.maxX, part.boundingBox.minY, part.boundingBox.minZ); var10.addVertex(part.boundingBox.maxX, part.boundingBox.maxY, part.boundingBox.minZ); var10.addVertex(part.boundingBox.minX, part.boundingBox.maxY, part.boundingBox.minZ); var10.addVertex(part.boundingBox.maxX, part.boundingBox.minY, part.boundingBox.minZ); var10.addVertex(part.boundingBox.maxX, part.boundingBox.maxY, part.boundingBox.minZ); var10.addVertex(part.boundingBox.maxX, part.boundingBox.maxY, part.boundingBox.maxZ); var10.addVertex(part.boundingBox.maxX, part.boundingBox.minY, part.boundingBox.maxZ); var10.addVertex(part.boundingBox.minX, part.boundingBox.minY, part.boundingBox.maxZ); var10.addVertex(part.boundingBox.maxX, part.boundingBox.minY, part.boundingBox.maxZ); var10.addVertex(part.boundingBox.maxX, part.boundingBox.maxY, part.boundingBox.maxZ); var10.addVertex(part.boundingBox.minX, part.boundingBox.maxY, part.boundingBox.maxZ); } } GL11.glTranslatef((float)(par2-par1Entity.posX), (float)(par4-par1Entity.posY), (float)(par6-par1Entity.posZ)); var10.draw(); GL11.glPopMatrix(); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_CULL_FACE); GL11.glDisable(GL11.GL_BLEND); //GL11.glDepthMask(true); }
  3. Hi, I've recently started modding and was looking for a tool to properly generate a texture map for mobs. Fortunately notch already wrote such a tool (http://pastebin.com/0AcY6YV2). However this does not work with forge so I changed the necessary variables to make it work. To use it simply pass a "new ModelMob().parts" in the main class and wait for the results. You will need to put all of your boxes into a list called parts (protected ArrayList<ModelRenderer> parts = new ArrayList<ModelRenderer>(); ). Here's an example mob (only the constructor and the list): protected ArrayList<ModelRenderer> parts = new ArrayList<ModelRenderer>(); ModelMob() { textureWidth = 128; //change this to the same size as in ImageGenerator (WIDTH) textureHeight = 64; setTextureOffset("null.part1", 0, 0); // important (needs to be called with any offset for the first time, otherwise you will get a NullPtr exception) setTextureOffset("null.part2", 0, 0); // change it to the output of ImageGenerator afterwards ModelRenderer part1 = new ModelRenderer(this, 0, 0); parts.add(part1); part1.addBox("part1",-8F, -8F, 0F, 16, 16, 32); //some other code ModelRenderer part2 = new ModelRenderer(this, 0, 0); parts.add(part2); part2.addBox("part2",-0.5F, 0F, 0F, 1, 8, ; //some other code } Finally here is the actual code: import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.util.*; import java.util.List; import javax.imageio.ImageIO; import net.minecraft.client.model.ModelBase; import net.minecraft.client.model.ModelBox; import net.minecraft.client.model.ModelRenderer; /* * Generates a texture map for a specified model * modified from: http://pastebin.com/0AcY6YV2 */ public class ImageGenerator { private static final int WIDTH = 256; private static final int HEIGHT = 256; private class Region { public int x1, y1, x2, y2; public Region(int x1, int y1, int x2, int y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public void move(int xo, int yo) { x1 += xo; y1 += yo; x2 += xo; y2 += yo; } public boolean overlaps(Region r2, int xo, int yo) { if (r2.x2 + xo <= x1) return false; if (r2.y2 + yo <= y1) return false; if (r2.x1 + xo >= x2) return false; if (r2.y1 + yo >= y2) return false; return true; } public void render(Graphics g) { g.fillRect(x1, y1, x2 - x1, y2 - y1); } } private class UnfoldedCube { public int x, y; public Region[] cubeRegions = new Region[6]; public String id; public int width, height; public UnfoldedCube(ModelBox cube) { int xs = (int) Math.ceil(cube.posX2 - cube.posX1); int ys = (int) Math.ceil(cube.posY2 - cube.posY1); int zs = (int) Math.ceil(cube.posZ2 - cube.posZ1); width = xs * 2 + zs * 2; height = zs + ys; id = cube.field_78247_g; cubeRegions[0] = new Region(0, zs, zs, zs + ys); cubeRegions[1] = new Region(zs, zs, zs + xs, zs + ys); cubeRegions[2] = new Region(zs + xs, zs, zs + xs + zs, zs + ys); cubeRegions[3] = new Region(zs + xs + zs, zs, zs + xs + zs + xs, zs + ys); cubeRegions[4] = new Region(zs, 0, zs + xs, zs); cubeRegions[5] = new Region(zs + xs, 0, zs + xs * 2, zs); } public boolean fits(int x, int y) { for (int i = 0; i < 6; i++) { if (!isFree(cubeRegions[i], x, y)) return false; } return true; } public void place(int x, int y) { this.x = x; this.y = y; for (int i = 0; i < 6; i++) { cubeRegions[i].move(x, y); occupiedRegions.add(cubeRegions[i]); } } public void render(Graphics g) { float hue = (float) Math.random(); g.setColor(new Color(Color.HSBtoRGB(hue, 1, 0.7f))); cubeRegions[5].render(g); g.setColor(new Color(Color.HSBtoRGB(hue, 1, 1.0f))); cubeRegions[4].render(g); g.setColor(new Color(Color.HSBtoRGB(hue, 1, 0.9f))); cubeRegions[1].render(g); cubeRegions[3].render(g); g.setColor(new Color(Color.HSBtoRGB(hue, 1, 0.8f))); cubeRegions[0].render(g); cubeRegions[2].render(g); } } private List<Region> occupiedRegions = new ArrayList<Region>(); private boolean isFree(Region region, int xo, int yo) { if (region.x1 + xo < 0) return false; if (region.y1 + yo < 0) return false; if (region.x2 + xo > WIDTH) return false; if (region.y2 + yo > HEIGHT) return false; for (int i = 0; i < occupiedRegions.size(); i++) { if (occupiedRegions.get(i).overlaps(region, xo, yo)) return false; } return true; } public void generateImage(List<ModelRenderer> parts) { List<ModelBox> cubes = new ArrayList<ModelBox>(); for (ModelRenderer mp : parts) { getCubes(mp, cubes); } Collections.sort(cubes, new Comparator<ModelBox>() { @Override public int compare(ModelBox c0, ModelBox c1) { int xs = (int) Math.ceil(c0.posX2 - c0.posX1); int ys = (int) Math.ceil(c0.posY2 - c0.posY1); int zs = (int) Math.ceil(c0.posZ2 - c0.posZ1); int ww0 = xs * 2 + zs * 2; int hh0 = zs + ys; xs = (int) Math.ceil(c1.posX2 - c1.posX1); ys = (int) Math.ceil(c1.posY2 - c1.posY1); zs = (int) Math.ceil(c1.posZ2 - c1.posZ1); int ww1 = xs * 2 + zs * 2; int hh1 = zs + ys; if (ww0 * hh0 < ww1 * hh1) { return 1; } else if (ww0 * hh0 > ww1 * hh1) { return -1; } return 0; } }); List<UnfoldedCube> unfolded = new ArrayList<UnfoldedCube>(); for (ModelBox cube : cubes) { UnfoldedCube uc = new UnfoldedCube(cube); boolean placed = false; positionLoop: for (int y = 0; y < HEIGHT - uc.height; y++) { for (int x = 0; x < WIDTH - uc.width; x++) { if (uc.fits(x, y)) { uc.place(x, y); placed = true; break positionLoop; } } } if (!placed) { System.out.println("Failed to place " + uc.id); } else { unfolded.add(uc); } } BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB); Graphics g = img.getGraphics(); System.out.println("----------------"); for (UnfoldedCube uc : unfolded) { System.out.println("setTextureOffset(\"" + uc.id + "\", " + uc.x + ", " + uc.y + ");"); uc.render(g); } try { ImageIO.write(img, "png", new File("output.png")); } catch (IOException e) { e.printStackTrace(); } } public void getCubes(ModelRenderer mp, List<ModelBox> cubeList) { addLoop: for (ModelBox cube : (List<ModelBox>)mp.cubeList) { if (cube.field_78247_g != null) { for (ModelBox otherCube : cubeList) { if (otherCube.field_78247_g != null) { if (otherCube.field_78247_g.equals(cube.field_78247_g)) { System.out.println("Duplicate " + cube.field_78247_g); continue addLoop; } } } } cubeList.add(cube); } } public static void main(String[] args) { new ImageGenerator().generateImage(new ModelMob().parts ); } } I hope it helps.

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.