diff --git a/game/client/.gitignore b/game/client/.gitignore
index cc46de012..c5dcc39b7 100644
--- a/game/client/.gitignore
+++ b/game/client/.gitignore
@@ -1,3 +1,3 @@
 build
-/dumpTextures/
-logs
\ No newline at end of file
+logs
+dumpTextures
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/Minecraft.java b/game/client/src/main/java/net/minecraft/client/Minecraft.java
index f13f5ef15..2eac4866e 100644
--- a/game/client/src/main/java/net/minecraft/client/Minecraft.java
+++ b/game/client/src/main/java/net/minecraft/client/Minecraft.java
@@ -190,6 +190,7 @@ import net.minecraft.core.world.save.SaveConverters;
 import net.minecraft.core.world.save.SaveFormats;
 import net.minecraft.core.world.save.mcregion.SaveFormat19134;
 import org.slf4j.Logger;
+import org.useless.dragonfly.data.entity.mojang.EntityGeometryMojangData;
 
 
 import static net.minecraft.core.Global.CURRENT_SAVE_VERSION;
@@ -532,6 +533,7 @@ public class Minecraft
         }
 
         this.texturePackList.init();
+        EntityGeometryMojangData.Cache.reload(this.texturePackList);
 
         TooltipElement.reloadStyles(this.texturePackList);
         SoundRepository.initialize(this);
@@ -550,7 +552,6 @@ public class Minecraft
         BlockModelDispatcher.getInstance();
         ItemModelDispatcher.getInstance();
 
-        EntityRenderDispatcher.instance.itemRenderer = new ItemRenderer(this);
         loadScreen();	// Update loading screen so it doesn't say no response
 
         LOGGER.info("Initializing input");
diff --git a/game/client/src/main/java/net/minecraft/client/entity/ClientSkinVariantList.java b/game/client/src/main/java/net/minecraft/client/entity/ClientSkinVariantList.java
index 510a0610c..086c36f1f 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/ClientSkinVariantList.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/ClientSkinVariantList.java
@@ -30,109 +30,112 @@ public class ClientSkinVariantList extends SkinVariantList {
 
 	private final Map<String, @Nullable EntityVariants> variantProcessorMap = new HashMap<>();
 
-	public ClientSkinVariantList(Minecraft minecraft) {
-		this.mc = minecraft;
-	}
+	public ClientSkinVariantList(final Minecraft minecraft) {
+        super();
+        this.mc = minecraft;
+    }
 
 
-	public void refresh(List<Throwable> errors) {
-		variantProcessorMap.clear();
+	public void refresh(final List<Throwable> errors) {
+        this.variantProcessorMap.clear();
 	}
 
 
 	@Override
-	public @NotNull String getSkinReference(@Nullable String variantJsonPath, @NotNull String defaultKey, int skinIndex) {
-		EntityVariants variants = getEntityVariants(variantJsonPath);
+	public @NotNull String getSkinReference(@Nullable final String variantJsonPath, @NotNull final String defaultKey, final int skinIndex) {
+		final EntityVariants variants = getEntityVariants(variantJsonPath);
 		if (variants == null) return defaultKey;
 		return variants.getKeyFromIndex(skinIndex);
 	}
 
-	protected @Nullable EntityVariants getEntityVariants(@Nullable String variantJsonPath) {
+	protected @Nullable EntityVariants getEntityVariants(@Nullable final String variantJsonPath) {
 		try {
 			if (!Minecraft.getMinecraft().gameSettings.mobVariants.value) return null;
 			if (variantJsonPath == null) return null;
-			if (!variantProcessorMap.containsKey(variantJsonPath)) {
-				loadJson(variantJsonPath);
+			if (this.variantProcessorMap.containsKey(variantJsonPath)) {
+				return this.variantProcessorMap.get(variantJsonPath);
 			}
-			return variantProcessorMap.get(variantJsonPath);
-		} catch (Exception e) {
+			final EntityVariants variants = loadJson(variantJsonPath);
+			this.variantProcessorMap.put(variantJsonPath, variants);
+			return variants;
+		} catch (final Exception e) {
 			LOGGER.error("Failed to load json at '{}'!", variantJsonPath, e);
-			variantProcessorMap.put(variantJsonPath, null); // Null the path after an exception happened trying to load it, prevents exception spam
+            this.variantProcessorMap.put(variantJsonPath, null); // Null the path after an exception happened trying to load it, prevents exception spam
 		}
 		return null;
 	}
 
 	@Override
-	public int nextSkinVariant(@Nullable String variantJsonPath, int skinIndex) {
-		EntityVariants variants = getEntityVariants(variantJsonPath);
+	public int nextSkinVariant(@Nullable final String variantJsonPath, final int skinIndex) {
+		final EntityVariants variants = getEntityVariants(variantJsonPath);
 		if (variants == null) return skinIndex;
 		return variants.getNextVariant(skinIndex);
 	}
 
-	public void loadJson(String variantJsonPath) {
-		load: try (InputStream stream = mc.texturePackList.getResourceAsStream(variantJsonPath)){
-			if (stream == null) return;
-			String jsonString;
+	protected @Nullable EntityVariants loadJson(final String variantJsonPath) {
+		load: try (final InputStream stream = this.mc.texturePackList.getResourceAsStream(variantJsonPath)){
+			if (stream == null) return null;
+			final String jsonString;
 			try {
 				jsonString = StringUtils.readInputString(stream);
-			} catch (Exception e) {
+			} catch (final Exception e) {
                 LOGGER.error("Failed to parse '{}' as a Json String!", variantJsonPath, e);
 				break load;
 			}
             try {
-                JsonObject variantObject = JsonParser.parseString(jsonString).getAsJsonObject();
+                final JsonObject variantObject = JsonParser.parseString(jsonString).getAsJsonObject();
 				if (variantObject.has("skins")) {
-					JsonElement skins = variantObject.get("skins");
+					final JsonElement skins = variantObject.get("skins");
 					if (skins.isJsonPrimitive()) {
-						variantProcessorMap.put(variantJsonPath, new EntityVariants(skins.getAsInt()));
-						return;
+						return new EntityVariants(skins.getAsInt());
 					} else if (skins.isJsonArray()) {
-						List<EntityVariants.VariantEntry> variants = new ArrayList<>();
-						JsonArray arr = skins.getAsJsonArray();
-						for (JsonElement e: arr) {
-							JsonObject entryObj = e.getAsJsonObject();
-							String textureReference = entryObj.get("texture").getAsString();
+						final List<EntityVariants.VariantEntry> variants = new ArrayList<>();
+						final JsonArray arr = skins.getAsJsonArray();
+						for (final JsonElement e: arr) {
+							final JsonObject entryObj = e.getAsJsonObject();
+							final String textureReference = entryObj.get("texture").getAsString();
 							double weight = 1;
 							if (entryObj.has("weight")) {
 								weight = entryObj.get("weight").getAsDouble();
 							}
 							variants.add(new EntityVariants.VariantEntry(textureReference, weight));
 						}
-						variantProcessorMap.put(variantJsonPath, new EntityVariants(variants));
-						return;
+						return new EntityVariants(variants);
 					} else {
                         LOGGER.error("Error at {}: value 'skins' must either be a integer or an array!", variantJsonPath);
 						break load;
 					}
 				}
-            } catch (JsonParseException e) {
+            } catch (final JsonParseException e) {
                 LOGGER.error("Failed to parse Json at {}", variantJsonPath, e);
             }
-        } catch (IOException e) {
+        } catch (final IOException e) {
             LOGGER.error("IO Exception while trying to read '{}'!", variantJsonPath, e);
 			break load;
         }
-		variantProcessorMap.put(variantJsonPath, null);
+		return null;
     }
 
 	protected static class EntityVariants {
+		private final String @Nullable [] indexedSkins;
+		private final VariantEntry @Nullable [] variantEntries;
 
-		private final VariantEntry[] variantEntries;
-		private final int skins;
-
-		public EntityVariants(int skins) {
+		public EntityVariants(final int skins) {
 			if (skins <= 0) throw new IllegalArgumentException("Skins number attribute must be at-least 1!");
-			this.skins = skins;
+			this.indexedSkins = new String[skins];
+			for (int i = 0; i < this.indexedSkins.length; i++) {
+				this.indexedSkins[i] = Integer.toString(i);
+			}
 			this.variantEntries = null;
 		}
 
-		public EntityVariants(List<VariantEntry> entries) {
-			variantEntries = new VariantEntry[MAX_VARIANT_ID + 1];
-			this.skins = -1;
+		public EntityVariants(final List<VariantEntry> entries) {
+            this.variantEntries = new VariantEntry[MAX_VARIANT_ID + 1];
+			this.indexedSkins = null;
 			double accWeight = 0;
 			entries.sort(Comparator.comparingDouble(o -> -o.weight));
 
-			for (VariantEntry e : entries) {
+			for (final VariantEntry e : entries) {
 				accWeight += e.weight;
 			}
 
@@ -140,57 +143,59 @@ public class ClientSkinVariantList extends SkinVariantList {
 			main:
 			{
 				int pointer = 0;
-				for (VariantEntry e : entries) {
+				for (final VariantEntry e : entries) {
 					int amount = MathHelper.floor((e.weight / accWeight) * MAX_VARIANT_ID);
 					if (amount < 1) amount = 1;
 
 					for (int i = 0; i < amount; i++) {
-						variantEntries[pointer] = e;
+                        this.variantEntries[pointer] = e;
 						pointer++;
-						if (pointer > variantEntries.length - 1) break main;
+						if (pointer > this.variantEntries.length - 1) break main;
 					}
 				}
 
-				VariantEntry last = entries.get(0);
-				while (pointer < variantEntries.length) {
-					variantEntries[pointer] = last;
+				final VariantEntry last = entries.get(0);
+				while (pointer < this.variantEntries.length) {
+                    this.variantEntries[pointer] = last;
 					pointer++;
 				}
 			}
 
 
-			Map<String, Integer> counts = new HashMap<>();
-			for (VariantEntry e : variantEntries) {
+			final Map<String, Integer> counts = new HashMap<>();
+			for (final VariantEntry e : this.variantEntries) {
 				counts.putIfAbsent(e.textureKey, 0);
 				counts.put(e.textureKey, counts.get(e.textureKey) + 1);
 			}
 		}
 
-		public String getKeyFromIndex(int index) {
-			if (variantEntries != null) {
-				return variantEntries[index].textureKey;
+		public @NotNull String getKeyFromIndex(final int index) {
+			if (this.variantEntries != null) {
+				return this.variantEntries[index].textureKey;
 			}
-			return String.valueOf(index % skins);
+			assert this.indexedSkins != null;
+			return this.indexedSkins[index % this.indexedSkins.length];
 		}
 
-		public int getNextVariant(int index) {
-			if (variantEntries != null) {
-				VariantEntry currentEntry = variantEntries[index];
-				for (int i = 1; i < variantEntries.length; i++) {
-					if (currentEntry != variantEntries[(index + i)%variantEntries.length]) {
-						return (index + i)%variantEntries.length;
+		public int getNextVariant(final int index) {
+			if (this.variantEntries != null) {
+				final VariantEntry currentEntry = this.variantEntries[index];
+				for (int i = 1; i < this.variantEntries.length; i++) {
+					if (currentEntry != this.variantEntries[(index + i)% this.variantEntries.length]) {
+						return (index + i)% this.variantEntries.length;
 					}
 				}
 				return index;
 			} else {
-				return (index + 1) % skins;
+                assert this.indexedSkins != null;
+                return (index + 1) % this.indexedSkins.length;
 			}
 		}
 
 		protected static class VariantEntry {
 			public final String textureKey;
 			public final double weight;
-			public VariantEntry(String key, double weight) {
+			public VariantEntry(final String key, final double weight) {
 				this.textureKey = key;
 				this.weight = weight;
 			}
diff --git a/game/client/src/main/java/net/minecraft/client/entity/particle/Particle.java b/game/client/src/main/java/net/minecraft/client/entity/particle/Particle.java
index e1a665baf..d7ba95d57 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/particle/Particle.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/particle/Particle.java
@@ -35,7 +35,7 @@ public class Particle extends Entity {
      * @param ya The particle's initial Y velocity.
      * @param za The particle's initial Z velocity.
      */
-    public Particle(World world, double x, double y, double z, double xa, double ya, double za) {
+    public Particle(@NotNull final World world, double x, double y, double z, double xa, double ya, double za) {
         super(world);
         setSize(0.2F, 0.2F);
         this.heightOffset = this.bbHeight / 2.0F;
diff --git a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleFirefly.java b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleFirefly.java
index d4ed48f6f..935210f93 100644
--- a/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleFirefly.java
+++ b/game/client/src/main/java/net/minecraft/client/entity/particle/ParticleFirefly.java
@@ -6,6 +6,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.animal.MobFireflyCluster;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
 
 public class ParticleFirefly extends Particle {
     private float sinTimer = 0;
@@ -23,11 +24,11 @@ public class ParticleFirefly extends Particle {
     private final float oG;
     private final float oB;
 
-    public ParticleFirefly(World world, double x, double y, double z, double xa, double ya, double za, int type) {
+    public ParticleFirefly(@NotNull final World world, double x, double y, double z, double xa, double ya, double za, int type) {
         this(world, x, y, z, xa, ya, za, 1.0F, type);
     }
 
-    public ParticleFirefly(World world, double x, double y, double z, double xa, double ya, double za, float scale, int type) {
+    public ParticleFirefly(@NotNull final World world, double x, double y, double z, double xa, double ya, double za, float scale, int type) {
         super(world, x, y, z, 0.0D, 0.0D, 0.0D);
         this.xd = 0.01D;
         this.yd = 0.01D;
diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
index 9901455d8..0e275291a 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java
@@ -451,14 +451,6 @@ public abstract class ScreenContainerAbstract extends Screen
 			}
 		}
 		
-		// Equip armor
-		if(slot != null && itemInSlot instanceof IArmorItem) {
-			if(mouseButton == 1 && shiftPressed) {
-				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.EQUIP_ARMOR, new int[] {slot.index}, mc.thePlayer);
-				return;
-			}
-		}
-		
 		// ContainerInventory Interactions (Grabbed Item)
 		if(slot != null && slot.allowItemInteraction() && grabbedItem != null && grabbedItem.getItem().hasInventoryInteraction()) {
 			if(mouseButton == 1) {
diff --git a/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java b/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java
index 2662f8106..eb46eeb9a 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/guidebook/mobs/GuidebookPageMob.java
@@ -10,6 +10,7 @@ import net.minecraft.client.render.*;
 import net.minecraft.client.render.font.FontRenderer;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
+import net.minecraft.client.world.WorldClient;
 import net.minecraft.core.achievement.stat.StatList;
 import net.minecraft.core.data.registry.recipe.RecipeSymbol;
 import net.minecraft.core.entity.Entity;
@@ -50,7 +51,7 @@ public class GuidebookPageMob
         this.mobInfo = mobInfo;
         Mob example = null;
         try {
-            example = (Mob) mobClass.getConstructor(World.class).newInstance((Object)null);
+            example = (Mob) mobClass.getConstructor(World.class).newInstance(WorldClient.EMPTY_WORLD);
         } catch (Exception e) {
             LOGGER.error("Failed to create example instance of mob '{}'!", mobClass.getSimpleName(), e);
         }
diff --git a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
index 3e9af8a67..61e9785a2 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/modelviewer/ScreenModelViewer.java
@@ -80,6 +80,8 @@ public class ScreenModelViewer extends ScreenPhotoMode implements ListenerTextFi
     protected boolean rotateToCamera = true;
     public ScreenModelViewer(){
         this.mc = Minecraft.getMinecraft();
+        mc.currentWorld.loadedEntityList.clear();
+        mc.currentWorld.loadedTileEntityList.clear();
         mc.thePlayer.absMoveTo(0.5, 64.5, 0.5, 180, 0);
         mc.thePlayer.noPhysics = true;
         mc.textureManager.refreshTexturesAndDisplayErrors();
@@ -136,7 +138,7 @@ public class ScreenModelViewer extends ScreenPhotoMode implements ListenerTextFi
         buttonCategory.setOnValueChanged(() -> buttonCategory.displayString = i18n.translateKey(currentCategory.getCategoryNameKey()));
 
         buttonReloadTextures = new ListenerButtonElement(12, 21, height - 20, 98, 20, i18n.translateKey("gui.model_viewer.button.reload_textures"));
-        buttonReloadTextures.setActionListener(() -> mc.textureManager.refreshTexturesAndDisplayErrors());
+        buttonReloadTextures.setActionListener(() -> mc.texturePackList.refresh());
         buttonOpenScreenshotFolder = (ListenerButtonElement) new ListenerButtonElement(30, buttonReloadTextures.getWidth() + buttonReloadTextures.getX() + 1, buttonReloadTextures.getY(), 20, 20, "")
             .setTextures("minecraft:gui/misc/button_folder", "minecraft:gui/misc/button_folder_highlighted", "minecraft:gui/misc/button_folder");
         buttonOpenScreenshotFolder.setActionListener(() -> FileOpener.open(new File(mc.getMinecraftDir(), "")));
diff --git a/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java b/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
index c473d621b..08bc1cede 100644
--- a/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
+++ b/game/client/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
@@ -345,7 +345,7 @@ public abstract class OptionsPages
             .withComponent(new OptionsCategory("gui.options.page.debug.category.utility")
                 .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.model_viewer", () -> {
                                    mc.playerController = new PlayerControllerSP(mc);
-                                   mc.changeWorld(new WorldClient(), "Loading Model Viewer");
+                                   mc.changeWorld(WorldClient.EMPTY_WORLD, "Loading Model Viewer");
                                    mc.displayScreen(new ScreenModelViewer());}) {
                                    @Override
                                    public void render(final int x, final int y, final int width, final int relativeMouseX, final int relativeMouseY) {
diff --git a/game/client/src/main/java/net/minecraft/client/input/controller/Joystick.java b/game/client/src/main/java/net/minecraft/client/input/controller/Joystick.java
index d34d9bbfe..c4d8ecdd3 100644
--- a/game/client/src/main/java/net/minecraft/client/input/controller/Joystick.java
+++ b/game/client/src/main/java/net/minecraft/client/input/controller/Joystick.java
@@ -41,13 +41,22 @@ public class Joystick{
 		float x = this.joystickListener.getValue(xAxis);
 		float y = this.joystickListener.getValue(yAxis);
 
-		float length = (float) Math.sqrt(x * x + y * y);
+		float magnitude = (float) Math.sqrt(x * x + y * y);
 		
-		boolean inDeadzone = length < deadzone.value;
+		boolean inDeadzone = magnitude < deadzone.value;
 
 		if (inDeadzone) {
 			x = 0.0f;
 			y = 0.0f;
+		} else {
+			float ux = x / magnitude;
+			float uy = y / magnitude;
+			float dx = ux * deadzone.value;
+			float dy = uy * deadzone.value;
+			float px = (x - dx) / (1.0f - Math.abs(dx));
+			float py = (y - dy) / (1.0f - Math.abs(dy));
+			x = px;
+			y = py;
 		}
 
 		this.x = x;
diff --git a/game/client/src/main/java/net/minecraft/client/render/EntityRenderDispatcher.java b/game/client/src/main/java/net/minecraft/client/render/EntityRenderDispatcher.java
index 1b95542cc..fdd9b2918 100644
--- a/game/client/src/main/java/net/minecraft/client/render/EntityRenderDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/EntityRenderDispatcher.java
@@ -3,9 +3,10 @@ package net.minecraft.client.render;
 import java.util.HashMap;
 import java.util.Map;
 
+import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.entity.*;
 import net.minecraft.client.render.font.FontRenderer;
-import net.minecraft.client.render.model.*;
+import net.minecraft.client.render.texturepack.TexturePackList;
 import net.minecraft.core.entity.EntityItem;
 import net.minecraft.core.entity.EntityLightning;
 import net.minecraft.core.entity.EntityPainting;
@@ -22,6 +23,9 @@ import net.minecraft.core.entity.projectile.ProjectileFireball;
 import net.minecraft.core.entity.projectile.ProjectileSnowball;
 import net.minecraft.core.entity.vehicle.EntityBoat;
 import net.minecraft.core.item.Items;
+import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.render.camera.ICamera;
@@ -38,173 +42,158 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.entity.projectile.ProjectileArrow;
 import net.minecraft.core.entity.projectile.ProjectilePebble;
 import net.minecraft.core.entity.vehicle.EntityMinecart;
-import net.minecraft.core.world.World;
 
-public class EntityRenderDispatcher
+public final class EntityRenderDispatcher
 {
-    private EntityRenderDispatcher()
-    {
-        renderers = new HashMap<>();
-        renderers.put(MobSpider.class, new MobRendererSpider());
-        renderers.put(MobScorpion.class, new MobRendererScorpion());
-        renderers.put(MobPig.class, new MobRendererPig(new ModelPig(), new ModelPig(0.5F), 0.7F));
-        renderers.put(MobSheep.class, new MobRendererSheep(new ModelSheep(), new ModelSheepWool(), new ModelSheepOverlay(), 0.7F));
-        renderers.put(MobCow.class, new MobRendererCow(new ModelCow(), 0.7F));
-        renderers.put(MobWolf.class, new MobRendererWolf(new ModelWolf(0.0f), 0.5F));
-        renderers.put(MobChicken.class, new MobRendererChicken(new ModelChicken(), 0.3F));
-        renderers.put(MobCreeper.class, new MobRendererCreeper());
-        renderers.put(MobSkeleton.class, new MobRendererBipedArmored<>(new ModelSkeleton(), new ModelZombie(1.0f), new ModelZombie(0.5f), 0.5F));
-        renderers.put(MobZombie.class, new MobRendererBipedArmored<>(new ModelZombie(), new ModelZombie(1.0f), new ModelZombie(0.5f), 0.5F));
-        renderers.put(MobZombiePig.class, new MobRendererBipedArmored<>(new ModelZombiePigman(), new ModelZombie(1.0f), new ModelZombie(0.5f), 0.5F));
-        renderers.put(MobSnowman.class, new MobRendererBiped<>(new ModelZombie(), 0.5F));
-        renderers.put(MobZombieArmored.class, new MobRendererZombieArmored(new ModelZombie(), 0.5F));
-        renderers.put(MobSlime.class, new MobRendererSlime(new ModelSlime(16), new ModelSlime(0), 0.25F));
-        renderers.put(Player.class, new MobRendererPlayer());
-        renderers.put(MobHuman.class, new MobRendererHuman());
-        renderers.put(MobGiant.class, new MobRendererGiant(new ModelZombie(), 0.5F, 6F));
-        renderers.put(MobGhast.class, new MobRendererGhast());
-        renderers.put(MobSquid.class, new MobRendererSquid(new ModelSquid(), 0.7F));
-        renderers.put(Mob.class, new MobRenderer<>(new ModelBiped(), 0.5F));
-        renderers.put(Entity.class, new EntityRendererDefault());
-        renderers.put(EntityPainting.class, new EntityRendererPainting());
-        renderers.put(ProjectileArrow.class, new EntityRendererArrow());
-        renderers.put(ProjectileSnowball.class, new EntityRendererSprite<ProjectileSnowball>(Items.AMMO_SNOWBALL));
-        renderers.put(ProjectileEgg.class, new EntityRendererSprite<ProjectileEgg>(Items.EGG_CHICKEN));
-        renderers.put(ProjectileFireball.class, new EntityRendererSprite<ProjectileFireball>(Items.AMMO_FIREBALL).setScale(4).setFullBright());
-        renderers.put(EntityItem.class, new EntityRendererItem());
-        renderers.put(EntityPrimedTNT.class, new EntityRendererTNT());
-        renderers.put(EntityFallingBlock.class, new EntityRendererFallingBlock());
-        renderers.put(EntityMinecart.class, new EntityRendererMinecart());
-        renderers.put(EntityBoat.class, new EntityRendererBoat());
-        renderers.put(EntityFishingBobber.class, new EntityRendererFishingBobber());
-        renderers.put(MobFireflyCluster.class, new MobRendererFireflyCluster());
-        renderers.put(EntityLightning.class, new EntityRendererLightningBolt());
-        renderers.put(ProjectileCannonball.class, new EntityRendererCannonball());
-        renderers.put(ProjectilePebble.class, new EntityRendererSprite<ProjectilePebble>(Items.AMMO_PEBBLE));
-        renderers.put(MobButterfly.class, new MobRendererButterfly());
-
-        for (EntityRenderer<?> renderer : renderers.values())
-        {
-            renderer.init(this);
-        }
+    public static final @NotNull EntityRenderDispatcher instance = new EntityRenderDispatcher();
+    public static double renderPosX = 0;
+    public static double renderPosY = 0;
+    public static double renderPosZ = 0;
+
+    private final @NotNull Map<@NotNull Class<? extends Entity>, @Nullable EntityRenderer<? extends Entity>> renderers;
+    public final @NotNull TextureManager textureManager;
+    public final @NotNull TexturePackList packList;
+    public final @NotNull FontRenderer font;
+    public final @NotNull GameSettings settings;
+    public @Nullable World world;
+    public @Nullable ICamera camera;
+    public float viewLerpYaw = 0;
+    public float viewLerpPitch = 0;
+    public double viewLerpPosX = 0;
+    public double viewLerpPosY = 0;
+    public double viewLerpPosZ = 0;
+
+    private EntityRenderDispatcher() {
+        final Minecraft mc = Minecraft.getMinecraft();
+        this.textureManager = mc.textureManager;
+        this.packList = mc.texturePackList;
+        this.font = mc.font;
+        this.settings = mc.gameSettings;
+
+        this.renderers = new HashMap<>();
+        reload();
+    }
+
+    public void reload() {
+        this.renderers.clear();
+        assignRenderer(MobSpider.class, new MobRendererSpider(1));
+        assignRenderer(MobScorpion.class, new MobRendererScorpion(0.5f));
+        assignRenderer(MobPig.class, new MobRendererPig(0.7F));
+        assignRenderer(MobSheep.class, new MobRendererSheep(0.7F));
+        assignRenderer(MobCow.class, new MobRendererQuadruped<>(0.7F));
+        assignRenderer(MobWolf.class, new MobRendererWolf(0.5F));
+        assignRenderer(MobChicken.class, new MobRendererChicken(0.3F));
+        assignRenderer(MobCreeper.class, new MobRendererCreeper(0.5f));
+        assignRenderer(MobSkeleton.class, new MobRendererSkeleton(0.5F));
+        assignRenderer(MobZombie.class, new MobRendererZombie(0.5F));
+        assignRenderer(MobZombiePig.class, new MobRendererZombie(0.5F));
+        assignRenderer(MobSnowman.class, new MobRendererSnowman(0.5F));
+        assignRenderer(MobZombieArmored.class, new MobRendererZombieArmored(0.5F));
+        assignRenderer(MobSlime.class, new MobRendererSlime(0.25F));
+        assignRenderer(Player.class, new MobRendererPlayer());
+        assignRenderer(MobHuman.class, new MobRendererHuman());
+        assignRenderer(MobGiant.class, new MobRendererGiant(0.5F, MobGiant.GIANT_SCALE));
+        assignRenderer(MobGhast.class, new MobRendererGhast(0.5f));
+        assignRenderer(MobSquid.class, new MobRendererSquid(0.7F));
+        assignRenderer(Entity.class, new EntityRendererDefault());
+        assignRenderer(Mob.class, new EntityRendererDefault());
+        assignRenderer(EntityPainting.class, new EntityRendererPainting());
+        assignRenderer(ProjectileArrow.class, new EntityRendererArrow());
+        assignRenderer(ProjectileSnowball.class, new EntityRendererSprite<>(Items.AMMO_SNOWBALL));
+        assignRenderer(ProjectileEgg.class, new EntityRendererSprite<>(Items.EGG_CHICKEN));
+        assignRenderer(ProjectileFireball.class, new EntityRendererSprite<ProjectileFireball>(Items.AMMO_FIREBALL).setScale(4).setFullBright());
+        assignRenderer(EntityItem.class, new EntityRendererItem());
+        assignRenderer(EntityPrimedTNT.class, new EntityRendererTNT());
+        assignRenderer(EntityFallingBlock.class, new EntityRendererFallingBlock());
+        assignRenderer(EntityMinecart.class, new EntityRendererMinecart());
+        assignRenderer(EntityBoat.class, new EntityRendererBoat());
+        assignRenderer(EntityFishingBobber.class, new EntityRendererFishingBobber());
+        assignRenderer(MobFireflyCluster.class, new MobRendererFireflyCluster());
+        assignRenderer(EntityLightning.class, new EntityRendererLightningBolt());
+        assignRenderer(ProjectileCannonball.class, new EntityRendererCannonball());
+        assignRenderer(ProjectilePebble.class, new EntityRendererSprite<>(Items.AMMO_PEBBLE));
+        assignRenderer(MobButterfly.class, new MobRendererButterfly());
+    }
+
+    private <T extends Entity> void assignRenderer(final @NotNull Class<? extends T> clazz, final @NotNull EntityRenderer<T> renderer) {
+        this.renderers.put(clazz, renderer);
+        renderer.init(clazz, this);
     }
 
     @SuppressWarnings("unchecked") // trust me this is safe, Notch did it first
-    public <T extends Entity> EntityRenderer<T> getRenderer(Class<? extends Entity> e)
-    {
-        EntityRenderer<? extends Entity> r = renderers.get(e);
-        if(r == null && e != Entity.class)
-        {
+    public <T extends Entity> EntityRenderer<T> getRenderer(final @NotNull Class<T> e) {
+        EntityRenderer<? extends Entity> r = this.renderers.get(e);
+        if(r == null && e != Entity.class) {
             r = getRenderer((Class<? extends Entity>) e.getSuperclass());
-            renderers.put(e, r);
+            this.renderers.put(e, r);
         }
         return (EntityRenderer<T>) r;
     }
 
-    public <T extends Entity> EntityRenderer<T> getRenderer(Entity entity)
-    {
-        return getRenderer(entity.getClass());
+    @SuppressWarnings("unchecked")
+    public <T extends Entity> EntityRenderer<T> getRenderer(final @NotNull T entity) {
+        return (EntityRenderer<T>) getRenderer(entity.getClass());
     }
 
-    public void cacheActiveRenderInfo(World world, TextureManager textureManager, FontRenderer fontRenderer, ICamera camera, GameSettings gameSettings, float partialTick)
+    public void cacheActiveRenderInfo(final @NotNull World world, final @NotNull ICamera camera, final float partialTick)
     {
+        if(this.world != world) {
+            for (final @Nullable EntityRenderer<?> renderer : this.renderers.values()) {
+                if (renderer == null) continue;
+                renderer.onWorldChanged(world);
+            }
+        }
         this.world = world;
-        this.textureManager = textureManager;
-        this.gameSettings = gameSettings;
-        this.fontRenderer = fontRenderer;
         this.camera = camera;
-        viewLerpYaw = (float) camera.getYRot(partialTick);
-        viewLerpPitch = (float) camera.getXRot(partialTick);
-        viewLerpPosX = (float) camera.getX(partialTick);
-        viewLerpPosY = (float) camera.getY(partialTick);
-        viewLerpPosZ = (float) camera.getZ(partialTick);
+        this.viewLerpYaw = (float) camera.getYRot(partialTick);
+        this.viewLerpPitch = (float) camera.getXRot(partialTick);
+        this.viewLerpPosX = camera.getX(partialTick);
+        this.viewLerpPosY = camera.getY(partialTick);
+        this.viewLerpPosZ = camera.getZ(partialTick);
     }
 
-    public <T extends Entity> void renderEntity(Tessellator tessellator, T entity, float partialTick)
-    {
-        double lerpPosX = entity.xo + (entity.x - entity.xo) * (double)partialTick;
-        double lerpPosY = entity.yo + (entity.y - entity.yo) * (double)partialTick;
-        double lerpPosZ = entity.zo + (entity.z - entity.zo) * (double)partialTick;
-        float lerpYaw = entity.yRotO + (entity.yRot - entity.yRotO) * partialTick;
+    public <T extends Entity> void renderEntity(final Tessellator tessellator, final T entity, final float partialTick) {
+        final double lerpPosX = entity.xo + (entity.x - entity.xo) * (double)partialTick;
+        final double lerpPosY = entity.yo + (entity.y - entity.yo) * (double)partialTick;
+        final double lerpPosZ = entity.zo + (entity.z - entity.zo) * (double)partialTick;
+        final float lerpYaw = entity.yRotO + (entity.yRot - entity.yRotO) * partialTick;
         float brightness;
-        
+
         if(LightmapHelper.isLightmapEnabled()) {
         	brightness = 1.0f;
-        	
+
         	LightmapHelper.setLightmapCoord(entity.getLightmapCoord(partialTick));
-        }else if(Global.accessor.isFullbrightEnabled()) {
+        } else if(Global.accessor.isFullbrightEnabled()) {
         	brightness = 1.0f;
-        }else {
+        } else {
         	brightness = entity.getBrightness(partialTick);
         }
-        
+
         if (Global.accessor.isFullbrightEnabled()) brightness = 1.0f;
         GL11.glColor3f(brightness, brightness, brightness);
-        
+
         renderEntityWithPosYaw(tessellator, entity, lerpPosX - renderPosX, lerpPosY - renderPosY, lerpPosZ - renderPosZ, lerpYaw, partialTick);
     }
 
-    public <T extends Entity> void renderEntityWithPosYaw(Tessellator tessellator, T entity, double x, double y, double z, float yaw, float partialTick)
-    {
-        EntityRenderer<T> renderer = getRenderer(entity);
-        if(renderer != null)
-        {
+    public <T extends Entity> void renderEntityWithPosYaw(final @NotNull Tessellator tessellator, final @NotNull T entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        final EntityRenderer<T> renderer = getRenderer(entity);
+        if(renderer != null) {
             renderer.render(tessellator, entity, x, y, z, yaw, partialTick);
             renderer.postRender(tessellator, entity, x, y, z, yaw, partialTick);
         }
     }
 
-    public <T extends Entity> void renderEntityPreviewWithPosYaw(Tessellator tessellator, T entity, double x, double y, double z, float yaw, float partialTick)
-    {
-        EntityRenderer<T> renderer = getRenderer(entity);
-        if(renderer != null)
-        {
+    public <T extends Entity> void renderEntityPreviewWithPosYaw(final @NotNull Tessellator tessellator, final @NotNull T entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        final EntityRenderer<T> renderer = getRenderer(entity);
+        if(renderer != null) {
             renderer.renderPreview(tessellator, entity, x, y, z, yaw, partialTick);
         }
     }
 
-    public void unloadEntityRenderers(){
-        // Needs to be run to clear any instances of entity inside the model classes.
-        // Not running can cause a temporary gc deadlock where old world objects are not cleared as the entity renderer is retained by the dispatcher.
-        for (EntityRenderer<?> renderer : renderers.values())
-        {
-            renderer.onUnload();
-        }
-    }
-
-    public void setWorld(World world)
-    {
-        this.world = world;
-    }
-
-    public double distanceToLerpSquared(double x, double y, double z)
-    {
-        double dx = x - viewLerpPosX;
-        double dy = y - viewLerpPosY;
-        double dz = z - viewLerpPosZ;
+    public double distanceToLerpSquared(final double x, final double y, final double z) {
+        final double dx = x - this.viewLerpPosX;
+        final double dy = y - this.viewLerpPosY;
+        final double dz = z - this.viewLerpPosZ;
         return dx * dx + dy * dy + dz * dz;
     }
-
-    public FontRenderer getFont()
-    {
-        return this.fontRenderer;
-    }
-
-    private final Map<Class<?>, EntityRenderer<?>> renderers;
-    public static EntityRenderDispatcher instance = new EntityRenderDispatcher();
-    private FontRenderer fontRenderer;
-    public static double renderPosX;
-    public static double renderPosY;
-    public static double renderPosZ;
-    public TextureManager textureManager;
-    public ItemRenderer itemRenderer;
-    public World world;
-    public ICamera camera;
-    public float viewLerpYaw;
-    public float viewLerpPitch;
-    public GameSettings gameSettings;
-    public double viewLerpPosX;
-    public double viewLerpPosY;
-    public double viewLerpPosZ;
-
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java b/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java
index 3c9e7d855..3900439c7 100644
--- a/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/ItemRenderer.java
@@ -1,6 +1,7 @@
 package net.minecraft.client.render;
 
 import net.minecraft.client.entity.player.PlayerLocal;
+import net.minecraft.client.render.entity.MobRendererPlayer;
 import net.minecraft.core.block.Blocks;
 import org.lwjgl.opengl.GL11;
 
@@ -8,7 +9,6 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.entity.EntityRenderer;
-import net.minecraft.client.render.entity.MobRendererPlayer;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
@@ -19,10 +19,10 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
 import org.lwjgl.opengl.GL12;
-import org.useless.dragonfly.DisplayPos;
 
 import static org.lwjgl.opengl.GL11.GL_ALPHA_TEST;
 import static org.lwjgl.opengl.GL11.GL_BLEND;
+import static org.lwjgl.opengl.GL11.GL_CCW;
 import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
 import static org.lwjgl.opengl.GL11.glColor4f;
 import static org.lwjgl.opengl.GL11.glDisable;
@@ -106,7 +106,14 @@ public class ItemRenderer
 
                     GL11.glPushMatrix();
                     GL11.glScalef(-1, 1, 1);
-                    playerRenderer.drawFirstPersonHand(mc.thePlayer, true);
+                    GL11.glPushMatrix();
+                    GL11.glScalef(1/16f, 1/16f, -1/16f);
+                    GL11.glTranslatef(0, 16, 0);
+                    GL11.glRotatef(180, 1, 0, 0);
+                    GL11.glTranslatef(0, -16, 0);
+                    GL11.glTranslatef(0, 8, 0);
+                    playerRenderer.drawFirstPersonHand(Tessellator.instance, mc.thePlayer, true);
+                    GL11.glPopMatrix();
                     GL11.glPopMatrix();
                 } else {
                     float f6 = 0.8F;
@@ -126,7 +133,14 @@ public class ItemRenderer
                     GL11.glRotatef(200F, 1.0F, 0.0F, 0.0F);
                     GL11.glRotatef(-135F, 0.0F, 1.0F, 0.0F);
                     GL11.glTranslatef(5.6F, 0.0F, 0.0F);
-                    playerRenderer.drawFirstPersonHand(mc.thePlayer, false);
+                    GL11.glPushMatrix();
+                    GL11.glScalef(1/16f, 1/16f, -1/16f);
+                    GL11.glTranslatef(0, 16, 0);
+                    GL11.glRotatef(180, 1, 0, 0);
+                    GL11.glTranslatef(0, -16, 0);
+                    GL11.glTranslatef(0, 8, 0);
+                    playerRenderer.drawFirstPersonHand(Tessellator.instance, mc.thePlayer, false);
+                    GL11.glPopMatrix();
                 }
             } else {
                 GL11.glPushMatrix();
diff --git a/game/client/src/main/java/net/minecraft/client/render/Polygon.java b/game/client/src/main/java/net/minecraft/client/render/Polygon.java
deleted file mode 100644
index 480f80e3a..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/Polygon.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package net.minecraft.client.render;
-
-import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.util.phys.Vec3;
-
-public class Polygon
-{
-    public Vertex[] vertices;
-    public int vertexCount;
-    public boolean flipNormal;
-
-
-    public Polygon(Vertex[] vertices)
-    {
-        flipNormal = false;
-        this.vertices = vertices;
-        vertexCount = vertices.length;
-    }
-
-    public Polygon(Vertex[] vertices, int minU, int minV, int maxU, int maxV, int texWidth, int texHeight)
-    {
-        this(vertices);
-        float offsetU = 0.0015625F;
-        float offsetV = 0.003125F;
-        vertices[0] = vertices[0].remap((float)maxU / texWidth - offsetU, (float)minV / texHeight + offsetV);
-        vertices[1] = vertices[1].remap((float)minU / texWidth + offsetU, (float)minV / texHeight + offsetV);
-        vertices[2] = vertices[2].remap((float)minU / texWidth + offsetU, (float)maxV / texHeight - offsetV);
-        vertices[3] = vertices[3].remap((float)maxU / texWidth - offsetU, (float)maxV / texHeight - offsetV);
-    }
-
-    public void mirror()
-    {
-        Vertex[] vertices = new Vertex[this.vertices.length];
-        for(int i = 0; i < this.vertices.length; i++)
-        {
-            vertices[i] = this.vertices[this.vertices.length - i - 1];
-        }
-
-        this.vertices = vertices;
-    }
-
-    public void mirrorU()
-    {
-        float minU = vertices[1].u;
-        float maxU = vertices[0].u;
-        vertices[0].u = minU;
-        vertices[1].u = maxU;
-        vertices[2].u = maxU;
-        vertices[3].u = minU;
-    }
-
-    public void mirrorV()
-    {
-        float minV = vertices[1].v;
-        float maxV = vertices[2].v;
-        vertices[0].u = maxV;
-        vertices[1].u = maxV;
-        vertices[2].u = minV;
-        vertices[3].u = minV;
-    }
-
-    public void render(Tessellator tessellator, float scale)
-    {
-        Vec3 vec3 = vertices[1].pos.vectorTo(vertices[0].pos);
-        Vec3 vec31 = vertices[1].pos.vectorTo(vertices[2].pos);
-        Vec3 vec32 = vec31.crossProduct(vec3).normalize();
-        tessellator.startDrawingQuads();
-        if(flipNormal)
-        {
-            tessellator.setNormal(-(float) vec32.x, -(float) vec32.y, -(float) vec32.z);
-        } else
-        {
-            tessellator.setNormal((float) vec32.x, (float) vec32.y, (float) vec32.z);
-        }
-        for(int i = 0; i < 4; i++)
-        {
-            Vertex positiontexturevertex = vertices[i];
-            tessellator.addVertexWithUV((float)positiontexturevertex.pos.x * scale, (float)positiontexturevertex.pos.y * scale, (float)positiontexturevertex.pos.z * scale, positiontexturevertex.u, positiontexturevertex.v);
-        }
-
-        tessellator.draw();
-    }
-    public Polygon flipNormal() {
-        this.flipNormal = true;
-        return this;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
index 82b871a68..fdd0e2818 100644
--- a/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
+++ b/game/client/src/main/java/net/minecraft/client/render/RenderGlobal.java
@@ -98,7 +98,6 @@ public class RenderGlobal
     private int countEntitiesTotal;
     private int countEntitiesRendered;
     private int countEntitiesHidden;
-    int[] dummyBuf50k;
     IntBuffer occlusionResult;
     private int renderersLoaded;
     private int renderersBeingClipped;
@@ -110,8 +109,6 @@ public class RenderGlobal
     private final DisplayList[] allDisplayLists = {
         new DisplayList(), new DisplayList(), new DisplayList(), new DisplayList()
     };
-    int dummyInt0;
-    int glDummyList;
     double prevSortX;
     double prevSortY;
     double prevSortZ;
@@ -133,11 +130,8 @@ public class RenderGlobal
         occlusionEnabled = false;
         cloudOffsetX = 0;
         renderEntitiesStartupCounter = 2;
-        dummyBuf50k = new int[50000];
         occlusionResult = GLAllocation.createDirectIntBuffer(64);
         glRenderLists = new ArrayList<>();
-        dummyInt0 = 0;
-        glDummyList = GLAllocation.generateDisplayLists(1);
         prevSortX = -9999D;
         prevSortY = -9999D;
         prevSortZ = -9999D;
@@ -245,20 +239,18 @@ public class RenderGlobal
         tessellator.draw();
     }
 
-    public void changeWorld(WorldClient world)
+    public void changeWorld(final WorldClient world)
     {
-        if(worldObj != null)
+        if(this.worldObj != null)
         {
-            worldObj.removeListener(this);
+            this.worldObj.removeListener(this);
         }
-        prevSortX = -9999D;
-        prevSortY = -9999D;
-        prevSortZ = -9999D;
-        EntityRenderDispatcher.instance.unloadEntityRenderers();
-        EntityRenderDispatcher.instance.setWorld(world);
-        worldObj = world;
-        auroraBrightness = 0.0f;
-        targetAuroraBrightness = Float.NaN;
+        this.prevSortX = -9999D;
+        this.prevSortY = -9999D;
+        this.prevSortZ = -9999D;
+        this.worldObj = world;
+        this.auroraBrightness = 0.0f;
+        this.targetAuroraBrightness = Float.NaN;
         if(world != null)
         {
             world.addListener(this);
@@ -464,8 +456,8 @@ public class RenderGlobal
             renderEntitiesStartupCounter--;
             return;
         }
-        TileEntityRenderDispatcher.instance.cacheActiveRenderInfo(worldObj, textureManager, mc.font, camera, partialTick);
-        EntityRenderDispatcher.instance.cacheActiveRenderInfo(worldObj, textureManager, mc.font, camera, mc.gameSettings, partialTick);
+        TileEntityRenderDispatcher.instance.cacheActiveRenderInfo(worldObj, camera, partialTick);
+        EntityRenderDispatcher.instance.cacheActiveRenderInfo(worldObj, camera, partialTick);
         countEntitiesTotal = 0;
         countEntitiesRendered = 0;
         countEntitiesHidden = 0;
@@ -483,7 +475,7 @@ public class RenderGlobal
         {
             Entity entity = worldObj.weatherEffects.get(i);
             countEntitiesRendered++;
-            if(entity.shouldRender(camera.getPosition(partialTick)) || mc.thePlayer.vehicle == entity)
+            if(entity.shouldRender(camera.getPosition(partialTick), 1) || mc.thePlayer.vehicle == entity)
             {
                 EntityRenderDispatcher.instance.renderEntity(tessellator, entity, partialTick);
             }
@@ -500,7 +492,7 @@ public class RenderGlobal
                     continue;
                 }
             }
-            if (mc.thePlayer.vehicle != entity && (!entity.shouldRender(camera.getPosition(partialTick)) || !entity.ignoreFrustumCheck && !camera.getFrustum().isVisible(entity.bb, partialTick)))
+            if (mc.thePlayer.vehicle != entity && (!entity.shouldRender(camera.getPosition(partialTick), 1) || !entity.ignoreFrustumCheck && !camera.getFrustum().isVisible(EntityRenderDispatcher.instance.getRenderer(entity).entityViewBox(entity), partialTick)))
             {
                 continue;
             }
@@ -1457,7 +1449,6 @@ public class RenderGlobal
 			drawOutlinedBoundingBox(aabb.cloneMove(-offsetX, -offsetY, -offsetZ).grow(expand, expand, expand));
 		}
 
-		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 		float entityRadius = 10.0f;
 		if(mc.thePlayer.getGamemode() == Gamemode.creative) {
 			entityRadius = 100.0f;
@@ -1483,6 +1474,15 @@ public class RenderGlobal
         boundingBox = boundingBox.cloneMove(-entity.x, -entity.y, -entity.z);
         boundingBox = boundingBox.cloneMove(-cameraX, -cameraY, -cameraZ);
         boundingBox = boundingBox.cloneMove(lerpOffsetX, lerpOffsetY, lerpOffsetZ);
+
+        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        drawOutlinedBoundingBox(boundingBox);
+
+        glColor4f(1.0f, 0f, 0f, 1.0f);
+        boundingBox = EntityRenderDispatcher.instance.getRenderer(entity).entityViewBox(entity);
+        boundingBox = boundingBox.cloneMove(-entity.x, -entity.y, -entity.z);
+        boundingBox = boundingBox.cloneMove(-cameraX, -cameraY, -cameraZ);
+        boundingBox = boundingBox.cloneMove(lerpOffsetX, lerpOffsetY, lerpOffsetZ);
         drawOutlinedBoundingBox(boundingBox);
     }
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/TileEntityRenderDispatcher.java b/game/client/src/main/java/net/minecraft/client/render/TileEntityRenderDispatcher.java
index 2d3c03fed..7719805c6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/TileEntityRenderDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/TileEntityRenderDispatcher.java
@@ -2,51 +2,84 @@ package net.minecraft.client.render;
 
 import java.util.*;
 
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.render.camera.ICamera;
 import net.minecraft.client.render.font.FontRenderer;
 import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.client.render.texturepack.TexturePackList;
 import net.minecraft.client.render.tileentity.*;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.entity.*;
 import net.minecraft.core.block.piston.TileEntityMovingPistonBlock;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 
-public class TileEntityRenderDispatcher
+public final class TileEntityRenderDispatcher
 {
+    public static final @NotNull TileEntityRenderDispatcher instance = new TileEntityRenderDispatcher();
+    public static double renderPosX = 0;
+    public static double renderPosY = 0;
+    public static double renderPosZ = 0;
+
+    private final @NotNull Map<@NotNull Class<? extends TileEntity>, @Nullable TileEntityRenderer<?>> renderers;
+
+    public final @NotNull TextureManager textureManager;
+    public final @NotNull TexturePackList packList;
+    private final @NotNull FontRenderer font;
+    public final @NotNull GameSettings settings;
+    public @Nullable World world;
+    public @Nullable ICamera camera;
+    public float viewLerpYaw = 0;
+    public float viewLerpPitch = 0;
+    public double viewLerpPosX = 0;
+    public double viewLerpPosY = 0;
+    public double viewLerpPosZ = 0;
+
 
     private TileEntityRenderDispatcher()
     {
-        renderers = new HashMap<>();
-        renderers.put(TileEntitySign.class, new TileEntityRendererSign());
-        renderers.put(TileEntityFlag.class, new TileEntityRendererFlag());
-        renderers.put(TileEntityMobSpawner.class, new TileEntityRendererMobSpawner());
-        renderers.put(TileEntityMovingPistonBlock.class, new TileEntityRendererMovingPiston());
-        renderers.put(TileEntityFlowerJar.class, new TileEntityRendererFlowerJar());
-        renderers.put(TileEntityJarButterfly.class, new TileEntityRendererJarButterfly());
-        renderers.put(TileEntityMeshGold.class, new TileEntityRendererMeshGold());
-        renderers.put(TileEntityStatue.class, new TileEntityRendererStatue());
-
-        for (TileEntityRenderer<?> tileEntityRenderer : renderers.values())
-        {
-            tileEntityRenderer.setRenderDispatcher(this);
-        }
+        final Minecraft mc = Minecraft.getMinecraft();
+        this.textureManager = mc.textureManager;
+        this.packList = mc.texturePackList;
+        this.font = mc.font;
+        this.settings = mc.gameSettings;
+        this.renderers = new HashMap<>();
+        reload();
+    }
 
+    public void reload() {
+        this.renderers.clear();
+        assignRenderer(TileEntitySign.class, new TileEntityRendererSign());
+        assignRenderer(TileEntityFlag.class, new TileEntityRendererFlag());
+        assignRenderer(TileEntityMobSpawner.class, new TileEntityRendererMobSpawner());
+        assignRenderer(TileEntityMovingPistonBlock.class, new TileEntityRendererMovingPiston());
+        assignRenderer(TileEntityFlowerJar.class, new TileEntityRendererFlowerJar());
+        assignRenderer(TileEntityJarButterfly.class, new TileEntityRendererJarButterfly());
+        assignRenderer(TileEntityMeshGold.class, new TileEntityRendererMeshGold());
+        assignRenderer(TileEntityStatue.class, new TileEntityRendererStatue());
+    }
+
+    public <T extends TileEntity> void assignRenderer(final Class<? extends T> clazz, final TileEntityRenderer<T> renderer) {
+        this.renderers.put(clazz, renderer);
+        renderer.init(clazz, this);
     }
 
     @SuppressWarnings("unchecked") // trust me this is safe, Notch did it first
-    public <T extends TileEntity> TileEntityRenderer<T> getRenderer(Class<? extends TileEntity> e)
+    public <T extends TileEntity> TileEntityRenderer<T> getRenderer(final Class<? extends TileEntity> e)
     {
-        TileEntityRenderer<? extends TileEntity> r = renderers.get(e);
+        TileEntityRenderer<? extends TileEntity> r = this.renderers.get(e);
         if(r == null && e != TileEntity.class)
         {
             r = getRenderer((Class<? extends TileEntity>) e.getSuperclass());
-            renderers.put(e, r);
+            this.renderers.put(e, r);
         }
         return (TileEntityRenderer<T>) r;
     }
 
-    public <T extends TileEntity> TileEntityRenderer<T> getRenderer(T tileEntity)
+    public <T extends TileEntity> @Nullable TileEntityRenderer<T> getRenderer(final @Nullable T tileEntity)
     {
         if(tileEntity == null)
         {
@@ -58,38 +91,41 @@ public class TileEntityRenderDispatcher
         }
     }
 
-    public <T extends TileEntity> boolean hasRenderer(T tileEntity)
+    public <T extends TileEntity> boolean hasRenderer(final @NotNull T tileEntity)
     {
         return getRenderer(tileEntity) != null;
     }
 
-    public void cacheActiveRenderInfo(World world, TextureManager textureManager, FontRenderer fontRenderer, ICamera camera, float partialTick)
+    public void cacheActiveRenderInfo(final @NotNull World world, final @NotNull ICamera camera, final float partialTick)
     {
-        if(worldObj != world)
-        {
-            updateRendererWorldCache(world);
+        if(this.world != world) {
+            for (final @Nullable TileEntityRenderer<?> renderer : this.renderers.values()) {
+                if (renderer == null) continue;
+                renderer.onWorldChanged(world);
+            }
         }
-        this.textureManager = textureManager;
+        this.world = world;
         this.camera = camera;
-        this.fontRenderer = fontRenderer;
-        viewLerpYaw = (float) camera.getYRot(partialTick);
-        viewLerpPitch = (float) camera.getXRot(partialTick);
-        viewLerpPosX = (float) camera.getX(partialTick);
-        viewLerpPosY = (float) camera.getY(partialTick);
-        viewLerpPosZ = (float) camera.getZ(partialTick);
+        this.viewLerpYaw = (float) camera.getYRot(partialTick);
+        this.viewLerpPitch = (float) camera.getXRot(partialTick);
+        this.viewLerpPosX = camera.getX(partialTick);
+        this.viewLerpPosY = camera.getY(partialTick);
+        this.viewLerpPosZ = camera.getZ(partialTick);
     }
 
-    public <T extends TileEntity> void renderTileEntity(Tessellator tessellator, T tileEntity, float partialTick)
+    public <T extends TileEntity> void renderTileEntity(final @NotNull Tessellator tessellator, final @NotNull T tileEntity, final float partialTick)
     {
-        if(tileEntity.getDistanceFrom(viewLerpPosX, viewLerpPosY, viewLerpPosZ) < 4096D)
+        if(tileEntity.getDistanceFrom(this.viewLerpPosX, this.viewLerpPosY, this.viewLerpPosZ) < 4096D)
         {
-            float brightness = 1.0f;
+            assert this.world != null;
+            final float brightness;
             if(LightmapHelper.isLightmapEnabled()) {
-            	LightmapHelper.setLightmapCoord(worldObj.getLightmapCoord(tileEntity.x, tileEntity.y, tileEntity.z, 0));
+            	LightmapHelper.setLightmapCoord(this.world.getLightmapCoord(tileEntity.x, tileEntity.y, tileEntity.z, 0));
+                brightness = 1.0f;
             }else if(Global.accessor.isFullbrightEnabled()) {
-            	
+                brightness = 1.0f;
             }else {
-            	brightness = worldObj.getLightBrightness(tileEntity.x, tileEntity.y, tileEntity.z);
+                brightness = this.world.getLightBrightness(tileEntity.x, tileEntity.y, tileEntity.z);
             }
             GL11.glColor3f(brightness, brightness, brightness);
             renderTileEntity(tessellator,
@@ -100,45 +136,18 @@ public class TileEntityRenderDispatcher
         }
     }
 
-    public <T extends TileEntity> void renderTileEntity(Tessellator tessellator, T tileEntity, double x, double y, double z, float partialTick)
+    public <T extends TileEntity> void renderTileEntity(final @NotNull Tessellator tessellator, final @NotNull T tileEntity, final double x, final double y, final double z, final float partialTick)
     {
-        TileEntityRenderer<T> renderer = getRenderer(tileEntity);
+        final TileEntityRenderer<T> renderer = getRenderer(tileEntity);
         if(renderer != null)
         {
             renderer.doRender(tessellator, tileEntity, x, y, z, partialTick);
         }
     }
 
-    public void updateRendererWorldCache(World world)
+    public @NotNull FontRenderer getFont()
     {
-        worldObj = world;
-        for (TileEntityRenderer<?> renderer : renderers.values())
-        {
-            if (renderer != null)
-            {
-                renderer.onWorldChanged(world);
-            }
-        }
+        return this.font;
     }
 
-    public FontRenderer getFont()
-    {
-        return fontRenderer;
-    }
-
-    private final Map<Class<?>, TileEntityRenderer<?>> renderers;
-    public static TileEntityRenderDispatcher instance = new TileEntityRenderDispatcher();
-    private FontRenderer fontRenderer;
-    public static double renderPosX;
-    public static double renderPosY;
-    public static double renderPosZ;
-    public TextureManager textureManager;
-    public World worldObj;
-    public ICamera camera;
-    public float viewLerpYaw;
-    public float viewLerpPitch;
-    public double viewLerpPosX;
-    public double viewLerpPosY;
-    public double viewLerpPosZ;
-
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/Vertex.java b/game/client/src/main/java/net/minecraft/client/render/Vertex.java
deleted file mode 100644
index 4193a1d79..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/Vertex.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package net.minecraft.client.render;
-
-import net.minecraft.core.util.phys.Vec3;
-
-public class Vertex
-{
-    public Vec3 pos;
-    public float u;
-    public float v;
-
-    public Vertex(float x, float y, float z, float u, float v)
-    {
-        this(Vec3.getPermanentVec3(x, y, z), u, v);
-    }
-
-    public Vertex(Vertex vertex, float u, float v) {
-        pos = vertex.pos;
-        this.u = u;
-        this.v = v;
-    }
-
-    public Vertex(Vec3 vec3, float u, float v) {
-        pos = vec3;
-        this.u = u;
-        this.v = v;
-    }
-
-    public Vertex remap(float u, float v)
-    {
-        return new Vertex(this, u, v);
-    }
-
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
index 9fe9c3bb5..7b141fe5f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
@@ -18,7 +18,7 @@ public abstract class BlockModel<T extends BlockLogic>
     public static final float FULL_CUBE_THRESHOLD = 1.0f / 16.0f;
 
     public final Block<T> block;
-    public BlockModel(Block<T> block){
+    public BlockModel(final Block<T> block){
         this.block = block;
     }
     public abstract boolean render(@NotNull Tessellator tessellator, @NotNull WorldSource worldSource, int x, int y, int z);
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
index 5494b99a4..45f82d949 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
@@ -1,6 +1,7 @@
 package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.util.dispatch.Dispatcher;
 import net.minecraft.core.block.Block;
@@ -15,11 +16,11 @@ import static net.minecraft.client.render.block.model.BlockModelStandard.BLOCK_T
 import static net.minecraft.client.render.block.model.BlockModelStandard.OVERBRIGHT_TEXTURES;
 import static net.minecraft.client.render.block.model.BlockModelStandard.RETRO_BLOCK_TEXTURES;
 
-public class BlockModelDispatcher
+public final class BlockModelDispatcher
     extends Dispatcher<Block<?>, BlockModel<?>>
 {
-    private static final Side[] S_TB = new Side[]{Side.TOP, Side.BOTTOM};
-    private static final Side[] S_SIDES = new Side[]{Side.NORTH, Side.EAST, Side.SOUTH, Side.WEST};
+    private static final Side[] S_TB = {Side.TOP, Side.BOTTOM};
+    private static final Side[] S_SIDES = {Side.NORTH, Side.EAST, Side.SOUTH, Side.WEST};
 
     private static BlockModelDispatcher instance = new BlockModelDispatcher();
     public static BlockModelDispatcher getInstance()
@@ -27,17 +28,17 @@ public class BlockModelDispatcher
         return instance;
     }
     public static BlockModelEmpty<?> modelEmpty = new BlockModelEmpty<>(null);
-    public void addDispatch(BlockModel<?> model)
+    public void addDispatch(final BlockModel<?> model)
     {
         addDispatch(model.block, model);
     }
     @Override
-    public void addDispatch(Block<?> key, BlockModel<?> value)
+    public void addDispatch(final Block<?> key, final BlockModel<?> value)
     {
         if (hasDispatch(key)){
             throw new IllegalArgumentException("Block '" + key.toString() + "' already assigned a model!");
         }
-        dispatches.put(key, value);
+        this.dispatches.put(key, value);
     }
     @Override
     protected BlockModel<?> getDefault()
@@ -45,19 +46,20 @@ public class BlockModelDispatcher
         return modelEmpty;
     }
 
-    private @NotNull BlockModelMojangData loadDataModel(@NotNull String id) {
-        Minecraft mc = Minecraft.getMinecraft();
+    private static @NotNull BlockModelMojangData loadDataModel(@NotNull final String id) {
+        final Minecraft mc = Minecraft.getMinecraft();
         return Objects.requireNonNull(BlockModelMojangData.Cache.loadModelData(mc.texturePackList, id), "Cannot find model for id '" + id + "'!");
     }
 
     private BlockModelDispatcher() {
+        super();
         instance = this;
         reload();
     }
 
     public void reload() {
         BlockModelMojangData.Cache.resetCache();
-        dispatches.clear();
+        this.dispatches.clear();
         addDispatch(new BlockModelStandard<>(Blocks.STONE).setAllTextures(BLOCK_TEXTURES, "minecraft:block/stone"));
         addDispatch(new BlockModelStandard<>(Blocks.BASALT).setAllTextures(BLOCK_TEXTURES, "minecraft:block/basalt"));
         addDispatch(new BlockModelStandard<>(Blocks.LIMESTONE).setAllTextures(BLOCK_TEXTURES, "minecraft:block/limestone"));
@@ -508,7 +510,7 @@ public class BlockModelDispatcher
             .withCustomItemBounds(0,0,0,1,1,1));
 
         addDispatch(new BlockModelPistonHead(Blocks.PISTON_HEAD, TextureRegistry.getTexture("minecraft:block/piston/head"), TextureRegistry.getTexture("minecraft:block/piston/shaft")).setAllTextures(BLOCK_TEXTURES, "minecraft:block/piston/face"));
-        addDispatch(new BlockModelEmpty<>(Blocks.PISTON_MOVING));
+        addDispatch(new BlockModelEmpty<>(Blocks.PISTON_MOVING).setAllTextures(BLOCK_TEXTURES, (IconCoordinate) null));
         addDispatch(new BlockModelPistonHead(Blocks.PISTON_HEAD_STEEL, TextureRegistry.getTexture("minecraft:block/piston_steel/head"), TextureRegistry.getTexture("minecraft:block/piston_steel/shaft"), 6/16d, 8d/16d).setAllTextures(BLOCK_TEXTURES, "minecraft:block/piston_steel/face"));
 
         addDispatch(new BlockModelStandard<>(Blocks.NOTEBLOCK).setAllTextures(BLOCK_TEXTURES, "minecraft:block/noteblock"));
@@ -761,10 +763,10 @@ public class BlockModelDispatcher
         addDispatch(new BlockModelLantern<>(Blocks.LANTERN_FIREFLY_RED).setAllTextures(BLOCK_TEXTURES, "minecraft:block/lantern_firefly/red"));
         addDispatch(new BlockModelJar<>(Blocks.JAR_GLASS));
 
-        addDispatch(new BlockModelJarButterfly<>(Blocks.JAR_BUTTERFLY_BLUE).withTextures("minecraft:block/jar_butterfly"));
-        addDispatch(new BlockModelJarButterfly<>(Blocks.JAR_BUTTERFLY_ORANGE).withTextures("minecraft:block/jar_butterfly"));
-        addDispatch(new BlockModelJarButterfly<>(Blocks.JAR_BUTTERFLY_PINK).withTextures("minecraft:block/jar_butterfly"));
-        addDispatch(new BlockModelJarButterfly<>(Blocks.JAR_BUTTERFLY_SILVER).withTextures("minecraft:block/jar_butterfly"));
+        addDispatch(new BlockModelJarButterfly<>(Blocks.JAR_BUTTERFLY_BLUE).setAllTextures(BLOCK_TEXTURES, "minecraft:block/jar_butterfly"));
+        addDispatch(new BlockModelJarButterfly<>(Blocks.JAR_BUTTERFLY_ORANGE).setAllTextures(BLOCK_TEXTURES, "minecraft:block/jar_butterfly"));
+        addDispatch(new BlockModelJarButterfly<>(Blocks.JAR_BUTTERFLY_PINK).setAllTextures(BLOCK_TEXTURES, "minecraft:block/jar_butterfly"));
+        addDispatch(new BlockModelJarButterfly<>(Blocks.JAR_BUTTERFLY_SILVER).setAllTextures(BLOCK_TEXTURES, "minecraft:block/jar_butterfly"));
 
         addDispatch(new BlockModelPebbles<>(Blocks.OVERLAY_PEBBLES));
 
@@ -788,8 +790,8 @@ public class BlockModelDispatcher
         addDispatch(new BlockModelEmpty<>(Blocks.STATUE_GRANITE_UPPER).setAllTextures(BLOCK_TEXTURES, "minecraft:block/granite"));
         addDispatch(new BlockModelEmpty<>(Blocks.STATUE_MARBLE_LOWER).setAllTextures(BLOCK_TEXTURES, "minecraft:block/marble"));
         addDispatch(new BlockModelEmpty<>(Blocks.STATUE_MARBLE_UPPER).setAllTextures(BLOCK_TEXTURES, "minecraft:block/marble"));
-        addDispatch(new BlockModelEmpty<>(Blocks.STATUE_PIGMAN_LOWER).setAllTextures(BLOCK_TEXTURES, "minecraft:block/pigman"));
-        addDispatch(new BlockModelEmpty<>(Blocks.STATUE_PIGMAN_UPPER).setAllTextures(BLOCK_TEXTURES, "minecraft:block/pigman"));
+        addDispatch(new BlockModelEmpty<>(Blocks.STATUE_PIGMAN_LOWER).setAllTextures(BLOCK_TEXTURES, "minecraft:block/marble"));
+        addDispatch(new BlockModelEmpty<>(Blocks.STATUE_PIGMAN_UPPER).setAllTextures(BLOCK_TEXTURES, "minecraft:block/marble"));
 
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java
index 1c3644656..b1d381d22 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelEmpty.java
@@ -4,31 +4,26 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogic;
-import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.WorldSource;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class BlockModelEmpty<T extends BlockLogic> extends BlockModelStandard<T> {
-    public BlockModelEmpty(Block<T> block) {
+    protected @Nullable IconCoordinate particle = null;
+    public BlockModelEmpty(final Block<T> block) {
         super(block);
     }
 
     @Override
-    public boolean render(@NotNull Tessellator tessellator, @NotNull WorldSource worldSource, int x, int y, int z) {
+    public boolean render(@NotNull final Tessellator tessellator, @NotNull final WorldSource worldSource, final int x, final int y, final int z) {
         return false;
     }
 
     @Override
-    public void renderStandalone(@NotNull Tessellator tessellator, int metadata, float brightness, float alpha, @Nullable Integer lightmapCoordinate) {
+    public void renderStandalone(@NotNull final Tessellator tessellator, final int metadata, final float brightness, final float alpha, @Nullable final Integer lightmapCoordinate) {
 
     }
 
-    @Override
-    public @Nullable IconCoordinate getParticleTexture(@NotNull Side side, int meta) {
-        return null;
-    }
-
     @Override
     public boolean shouldItemRender3d() {
         return false;
diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGeneric.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGeneric.java
index f6c098ddb..3fbcede22 100644
--- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGeneric.java
+++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelGeneric.java
@@ -16,19 +16,19 @@ import org.useless.dragonfly.models.block.StaticBlockModel;
 public class BlockModelGeneric<T extends BlockLogic> extends BlockModel<T>{
     private final StaticBlockModel staticModel;
 
-    public BlockModelGeneric(@NotNull Block<T> block, @NotNull StaticBlockModel staticModel) {
+    public BlockModelGeneric(@NotNull final Block<T> block, @NotNull final StaticBlockModel staticModel) {
         super(block);
         this.staticModel = staticModel;
     }
 
-    public BlockModelGeneric(@NotNull Block<T> block, @NotNull BlockModelData staticModel) {
+    public BlockModelGeneric(@NotNull final Block<T> block, @NotNull final BlockModelData staticModel) {
         super(block);
         this.staticModel = staticModel.asModel();
     }
 
     @Override
-    public boolean renderNoCulling(@NotNull Tessellator tessellator, @NotNull WorldSource worldSource, int x, int y, int z) {
-        return staticModel.renderAttached(this,
+    public boolean renderNoCulling(@NotNull final Tessellator tessellator, @NotNull final WorldSource worldSource, final int x, final int y, final int z) {
+        return this.staticModel.renderAttached(this,
             tessellator,
             worldSource, x,
             y,
@@ -37,8 +37,8 @@ public class BlockModelGeneric<T extends BlockLogic> extends BlockModel<T>{
     }
 
     @Override
-    public boolean render(@NotNull Tessellator tessellator, @NotNull WorldSource worldSource, int x, int y, int z) {
-        return staticModel.renderAttached(this,
+    public boolean render(@NotNull final Tessellator tessellator, @NotNull final WorldSource worldSource, final int x, final int y, final int z) {
+        return this.staticModel.renderAttached(this,
             tessellator,
             worldSource, x,
             y,
@@ -47,13 +47,13 @@ public class BlockModelGeneric<T extends BlockLogic> extends BlockModel<T>{
     }
 
     @Override
-    public boolean renderOverbright(@NotNull Tessellator tessellator, @NotNull WorldSource worldSource, int x, int y, int z) {
+    public boolean renderOverbright(@NotNull final Tessellator tessellator, @NotNull final WorldSource worldSource, final int x, final int y, final int z) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public boolean renderWithOverrideTexture(@NotNull Tessellator tessellator, @NotNull WorldSource worldSource, int x, int y, int z, IconCoordinate textureIndex) {
-        return staticModel.renderAttached(this,
+    public boolean renderWithOverrideTexture(@NotNull final Tessellator tessellator, @NotNull final WorldSource worldSource, final int x, final int y, final int z, final IconCoordinate textureIndex) {
+        return this.staticModel.renderAttached(this,
             tessellator,
             worldSource, x,
             y,
@@ -62,11 +62,11 @@ public class BlockModelGeneric<T extends BlockLogic> extends BlockModel<T>{
     }
 
     @Override
-    public void renderStandalone(@NotNull Tessellator tessellator, int metadata, float brightness, float alpha, @Nullable Integer lightmapCoordinate) {
-        staticModel.renderStandalone(this,
+    public void renderStandalone(@NotNull final Tessellator tessellator, final int metadata, final float brightness, final float alpha, @Nullable final Integer lightmapCoordinate) {
+        this.staticModel.renderStandalone(this,
             tessellator, 0, 0, 0,
             metadata,
-            BlockColorDispatcher.getInstance().getDispatch(block),
+            BlockColorDispatcher.getInstance().getDispatch(this.block),
             brightness, alpha);
     }
 
@@ -76,27 +76,27 @@ public class BlockModelGeneric<T extends BlockLogic> extends BlockModel<T>{
     }
 
     @Override
-    public @NotNull DisplayPos getItemDisplayPos(@NotNull String id) {
-        return staticModel.getItemDisplayPos(id);
+    public @NotNull DisplayPos getItemDisplayPos(@NotNull final String id) {
+        return this.staticModel.getItemDisplayPos(id);
     }
 
     @Override
     public int renderLayer() {
-        return staticModel.renderLayer();
+        return this.staticModel.renderLayer();
     }
 
     @Override
-    public @Nullable IconCoordinate getParticleTexture(@NotNull Side side, int meta) {
-        return staticModel.getParticle(side);
+    public @Nullable IconCoordinate getParticleTexture(@NotNull final Side side, final int meta) {
+        return this.staticModel.getParticle(side);
     }
 
     @Override
-    public @Nullable IconCoordinate getOverlayTexture(int meta) {
-        return staticModel.getOverlay();
+    public @Nullable IconCoordinate getOverlayTexture(final int meta) {
+        return this.staticModel.getOverlay();
     }
 
     @Override
-    public int particleColorIndex(@NotNull WorldSource worldSource, int x, int y, int z, @NotNull Side side, int meta) {
-        return staticModel.particleColorIndex(side);
+    public int particleColorIndex(@NotNull final WorldSource worldSource, final int x, final int y, final int z, @NotNull final Side side, final int meta) {
+        return this.staticModel.particleColorIndex(side);
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java
index ff4b727cf..0191185b2 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java
@@ -2,6 +2,9 @@ package net.minecraft.client.render.entity;
 
 import net.minecraft.client.render.font.FontRenderer;
 import net.minecraft.core.block.Blocks;
+import net.minecraft.core.entity.EntityDispatcher;
+import net.minecraft.core.util.collection.NamespaceID;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 
 import net.minecraft.client.render.EntityRenderDispatcher;
@@ -17,49 +20,80 @@ import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
+import org.useless.dragonfly.data.entity.mojang.EntityGeometryMojangData;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
+import java.util.HashMap;
+import java.util.Map;
 
 public abstract class EntityRenderer<T extends Entity>
 {
-    protected EntityRenderDispatcher renderDispatcher;
+    private final @NotNull Map<@NotNull String, @NotNull StaticEntityModel> modelMap = new HashMap<>();
+    protected EntityRenderDispatcher renderDispatcher = null;
+    protected Class<? extends T> appliedClass = null;
     protected float shadowSize;
     protected float shadowOpacity;
 
     public EntityRenderer()
     {
-        shadowSize = 0.0F;
-        shadowOpacity = 1.0F;
+        this.shadowSize = 0.0F;
+        this.shadowOpacity = 1.0F;
     }
 
-    public abstract void render(Tessellator tessellator, T entity, double x, double y, double z,
+    public abstract void render(@NotNull Tessellator tessellator, @NotNull T entity, double x, double y, double z,
                                 float yaw, float partialTick);
 
-    public void renderPreview(Tessellator tessellator, T entity, double x, double y, double z, float yaw, float partialTick) {
+    public void renderPreview(@NotNull final Tessellator tessellator, @NotNull final T entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
         render(tessellator, entity, x, y, z, yaw, partialTick);
     }
 
-    protected void bindTexture(String texturePath)
+    protected void bindTexture(final @NotNull String texturePath)
     {
-        TextureManager textureManager = renderDispatcher.textureManager;
+        final TextureManager textureManager = this.renderDispatcher.textureManager;
         textureManager.bindTexture(textureManager.loadTexture(texturePath));
     }
-    public boolean bindDownloadableTexture(String urlTexture, String backupTexture, ImageParser imageParser) {
-        return renderDispatcher.textureManager.bindDownloadableTexture(urlTexture, backupTexture, imageParser);
+    public boolean bindDownloadableTexture(final String urlTexture, final String backupTexture, final ImageParser imageParser) {
+        return this.renderDispatcher.textureManager.bindDownloadableTexture(urlTexture, backupTexture, imageParser);
+    }
+
+    protected @NotNull StaticEntityModel getModel(@NotNull final String localId) {
+        StaticEntityModel model = this.modelMap.get(localId);
+        if (model != null) {
+            return model;
+        }
+        final NamespaceID id = EntityDispatcher.idForClass(this.appliedClass);
+        if (id != null) {
+            model = EntityGeometryMojangData.Cache.getModelForEntity(id, localId);
+        } else {
+            model = EntityGeometryMojangData.Cache.getFallbackModel();
+        }
+        this.modelMap.put(localId, model);
+        return model;
+    }
+
+    public final @NotNull EntityRenderer<T> setModel(@NotNull final String localId, @NotNull final String modelId, final double inflation) {
+        this.modelMap.put(localId, EntityGeometryMojangData.Cache.getModel(modelId, inflation));
+        return this;
+    }
+
+    public void onWorldChanged(final @NotNull World world)
+    {
     }
     
-    private void renderFire(Tessellator tessellator, T entity, double x, double y, double z, float partialTick)
+    private void renderFire(final @NotNull Tessellator tessellator, final @NotNull T entity, final double x, final double y, final double z, final float partialTick)
     {
         GL11.glDisable(GL11.GL_LIGHTING);
-        IconCoordinate texture = TextureRegistry.getTexture("minecraft:block/fire");
+        final IconCoordinate texture = TextureRegistry.getTexture("minecraft:block/fire");
         texture.parentAtlas.bind();
         GL11.glPushMatrix();
         GL11.glTranslatef((float)x, (float)y, (float)z);
-        float f9 = entity.bbWidth * 1.4F;
+        final float f9 = entity.bbWidth * 1.4F;
         GL11.glScalef(f9, f9, f9);
         float f10 = 0.5F;
-        float f11 = 0.0F;
+        final float f11 = 0.0F;
         float f12 = entity.bbHeight;
         float f13 = (float)(entity.y - entity.bb.minY);
-        GL11.glRotatef(-renderDispatcher.viewLerpYaw, 0.0F, 1.0F, 0.0F);
+        GL11.glRotatef(-this.renderDispatcher.viewLerpYaw, 0.0F, 1.0F, 0.0F);
         GL11.glTranslatef(0.0F, 0.0F, -0.3F + (float)(int)f12 * 0.02F);
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         if(LightmapHelper.isLightmapEnabled()) {
@@ -74,11 +108,11 @@ public abstract class EntityRenderer<T extends Entity>
         {
             double f2 = texture.getIconUMin();
             double f4 = texture.getIconUMax();
-            double f6 = texture.getIconVMin();
-            double f8 = texture.getIconVMax();
+            final double f6 = texture.getIconVMin();
+            final double f8 = texture.getIconVMax();
             if((l / 2) % 2 == 0)
             {
-                double f15 = f4;
+                final double f15 = f4;
                 f4 = f2;
                 f2 = f15;
             }
@@ -97,27 +131,27 @@ public abstract class EntityRenderer<T extends Entity>
         GL11.glEnable(GL11.GL_LIGHTING);
     }
 
-    private void renderShadow(Tessellator tessellator, T entity, double posX, double posY, double posZ,
-                              float opacity, float partialTick)
+    private void renderShadow(final @NotNull Tessellator tessellator, @NotNull final T entity, final double posX, final double posY, final double posZ,
+                              final float opacity, final float partialTick)
     {
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-        TextureManager textureManager = renderDispatcher.textureManager;
+        final TextureManager textureManager = this.renderDispatcher.textureManager;
         textureManager.bindTexture(textureManager.loadTexture("/assets/minecraft/textures/misc/shadow.png"));
-        World world = getWorld();
+        final World world = entity.world;
         GL11.glDepthMask(false);
-        double lerpX = entity.xo + (entity.x - entity.xo) * (double)partialTick;
-        double lerpY = entity.yo + (entity.y - entity.yo) * (double)partialTick + (double)entity.getShadowHeightOffs();
-        double lerpZ = entity.zo + (entity.z - entity.zo) * (double)partialTick;
-        int minX = MathHelper.floor(lerpX - (double)shadowSize);
-        int maxX = MathHelper.floor(lerpX + (double)shadowSize);
-        int minY = MathHelper.floor(lerpY - (double)shadowSize);
-        int maxY = MathHelper.floor(lerpY);
-        int minZ = MathHelper.floor(lerpZ - (double)shadowSize);
-        int maxZ = MathHelper.floor(lerpZ + (double)shadowSize);
-        double dxLerp = posX - lerpX;
-        double dyLerp = posY - lerpY;
-        double dzLerp = posZ - lerpZ;
+        final double lerpX = entity.xo + (entity.x - entity.xo) * (double)partialTick;
+        final double lerpY = entity.yo + (entity.y - entity.yo) * (double)partialTick + (double)entity.getShadowHeightOffs();
+        final double lerpZ = entity.zo + (entity.z - entity.zo) * (double)partialTick;
+        final int minX = MathHelper.floor(lerpX - (double) this.shadowSize);
+        final int maxX = MathHelper.floor(lerpX + (double) this.shadowSize);
+        final int minY = MathHelper.floor(lerpY - (double) this.shadowSize);
+        final int maxY = MathHelper.floor(lerpY);
+        final int minZ = MathHelper.floor(lerpZ - (double) this.shadowSize);
+        final int maxZ = MathHelper.floor(lerpZ + (double) this.shadowSize);
+        final double dxLerp = posX - lerpX;
+        final double dyLerp = posY - lerpY;
+        final double dzLerp = posZ - lerpZ;
         tessellator.startDrawingQuads();
 
         for(int blockX = minX; blockX <= maxX; blockX++)
@@ -126,10 +160,10 @@ public abstract class EntityRenderer<T extends Entity>
             {
                 for(int blockZ = minZ; blockZ <= maxZ; blockZ++)
                 {
-                    int blockId = world.getBlockId(blockX, blockY - 1, blockZ);
+                    final int blockId = world.getBlockId(blockX, blockY - 1, blockZ);
                     if(blockId > 0 && world.getBlockLightValue(blockX, blockY, blockZ) > 3)
                     {
-                        renderShadowOnBlock(tessellator, entity, Blocks.blocksList[blockId], posX, posY + (double)entity.getShadowHeightOffs(), posZ, blockX, blockY, blockZ, opacity, shadowSize, dxLerp, dyLerp + (double)entity.getShadowHeightOffs(), dzLerp);
+                        renderShadowOnBlock(tessellator, entity, Blocks.blocksList[blockId], posX, posY + (double)entity.getShadowHeightOffs(), posZ, blockX, blockY, blockZ, opacity, this.shadowSize, dxLerp, dyLerp + (double)entity.getShadowHeightOffs(), dzLerp);
                     }
                 }
 
@@ -142,20 +176,15 @@ public abstract class EntityRenderer<T extends Entity>
         GL11.glDepthMask(true);
     }
 
-    private World getWorld()
-    {
-        return renderDispatcher.world;
-    }
-
-    private void renderShadowOnBlock(Tessellator tessellator, T entity, Block<?> block, double d, double d1, double d2,
-                                     int x, int y, int z, float opacity, float size, double xo,
-                                     double yo, double zo)
+    private void renderShadowOnBlock(final @NotNull Tessellator tessellator, final @NotNull T entity, final @NotNull Block<?> block, final double d, final double d1, final double d2,
+                                     final int x, final int y, final int z, final float opacity, final float size, final double xo,
+                                     final double yo, final double zo)
     {
         if(!block.isCubeShaped())
         {
             return;
         }
-        double brightness = getWorld().getLightBrightness(x, y, z);
+        double brightness = entity.world.getLightBrightness(x, y, z);
         if (Global.accessor.isFullbrightEnabled()) brightness = 1.0f;
         double alpha = ((double)opacity - (d1 - ((double)(y + 1) + yo)) / 2D) * 0.5D * brightness;
         if(alpha < 0.0D)
@@ -167,112 +196,109 @@ public abstract class EntityRenderer<T extends Entity>
             alpha = 1.0D;
         }
         tessellator.setColorRGBA_F(1.0F, 1.0F, 1.0F, (float)alpha);
-        AABB aabb = block.getCollisionBoundingBoxFromPool(getWorld(), x, y, z);
+        final AABB aabb = block.getCollisionBoundingBoxFromPool(entity.world, x, y, z);
         if(aabb == null) {
         	return;
         }
-        double xMin = aabb.minX + xo;
-        double xMax = aabb.maxX + xo;
-        double yMin = aabb.maxY + yo + 0.015625D - 1;
-        double zMin = aabb.minZ + zo;
-        double zMax = aabb.maxZ + zo;
-        float f2 = (float)((d - xMin) / 2D / (double)size + 0.5D);
-        float f3 = (float)((d - xMax) / 2D / (double)size + 0.5D);
-        float f4 = (float)((d2 - zMin) / 2D / (double)size + 0.5D);
-        float f5 = (float)((d2 - zMax) / 2D / (double)size + 0.5D);
+        final double xMin = aabb.minX + xo;
+        final double xMax = aabb.maxX + xo;
+        final double yMin = aabb.maxY + yo + 0.015625D - 1;
+        final double zMin = aabb.minZ + zo;
+        final double zMax = aabb.maxZ + zo;
+        final float f2 = (float)((d - xMin) / 2D / (double)size + 0.5D);
+        final float f3 = (float)((d - xMax) / 2D / (double)size + 0.5D);
+        final float f4 = (float)((d2 - zMin) / 2D / (double)size + 0.5D);
+        final float f5 = (float)((d2 - zMax) / 2D / (double)size + 0.5D);
         tessellator.addVertexWithUV(xMin, yMin, zMin, f2, f4);
         tessellator.addVertexWithUV(xMin, yMin, zMax, f2, f5);
         tessellator.addVertexWithUV(xMax, yMin, zMax, f3, f5);
         tessellator.addVertexWithUV(xMax, yMin, zMin, f3, f4);
     }
 
-    public static void renderOffsetAABB(Tessellator tessellator, AABB axisalignedbb, double d, double d1, double d2)
+    public static void renderOffsetAABB(final @NotNull Tessellator tessellator, final @NotNull AABB aabb, final double x, final double y, final double z)
     {
         GL11.glDisable(GL11.GL_TEXTURE_2D);
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         tessellator.startDrawingQuads();
-        tessellator.setTranslation(d, d1, d2);
+        tessellator.setTranslation(x, y, z);
         tessellator.setNormal(0.0F, 0.0F, -1F);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.minZ);
         tessellator.setNormal(0.0F, 0.0F, 1.0F);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.maxZ);
         tessellator.setNormal(0.0F, -1F, 0.0F);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.maxZ);
         tessellator.setNormal(0.0F, 1.0F, 0.0F);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.minZ);
         tessellator.setNormal(-1F, 0.0F, 0.0F);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.minZ);
         tessellator.setNormal(1.0F, 0.0F, 0.0F);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.maxZ);
         tessellator.setTranslation(0.0D, 0.0D, 0.0D);
         tessellator.draw();
         GL11.glEnable(GL11.GL_TEXTURE_2D);
     }
 
-    public static void renderFlatAABB(AABB axisalignedbb)
+    public static void renderFlatAABB(final @NotNull AABB aabb)
     {
-        Tessellator tessellator = Tessellator.instance;
+        final Tessellator tessellator = Tessellator.instance;
         tessellator.startDrawingQuads();
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.minZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ);
-        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.minX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.minX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.minZ);
+        tessellator.addVertex(aabb.maxX, aabb.maxY, aabb.maxZ);
+        tessellator.addVertex(aabb.maxX, aabb.minY, aabb.maxZ);
         tessellator.draw();
     }
 
-    public void init(EntityRenderDispatcher dispatcher)
+    public void init(@NotNull final Class<? extends T> appliedClass, final @NotNull EntityRenderDispatcher dispatcher)
     {
         this.renderDispatcher = dispatcher;
+        this.appliedClass = appliedClass;
     }
 
-    public void onUnload() {
-
-    }
-
-    public void postRender(Tessellator tessellator, T entity, double x, double y, double z, float yaw, float partialTick)
+    public void postRender(final @NotNull Tessellator tessellator, final @NotNull T entity, final double x, final double y, final double z, final float yaw, final float partialTick)
     {
-        if(renderDispatcher.gameSettings != null && (renderDispatcher.gameSettings.fancyGraphics.value == 1 && shadowSize > 0.0F))
+        if(this.renderDispatcher.settings.fancyGraphics.value == 1 && this.shadowSize > 0.0F)
         {
-            double distance = renderDispatcher.distanceToLerpSquared(entity.x, entity.y, entity.z);
-            float opacity = (float)((1.0D - distance / 256D) * (double) shadowOpacity);
+            final double distance = this.renderDispatcher.distanceToLerpSquared(entity.x, entity.y, entity.z);
+            final float opacity = (float)((1.0D - distance / 256D) * (double) this.shadowOpacity);
             if(opacity > 0.0F)
             {
                 renderShadow(tessellator, entity, x, y, z, opacity, partialTick);
@@ -284,8 +310,12 @@ public abstract class EntityRenderer<T extends Entity>
         }
     }
 
-    public FontRenderer getFont()
+    public @NotNull FontRenderer getFont()
     {
-        return renderDispatcher.getFont();
+        return this.renderDispatcher.font;
+    }
+
+    public @NotNull AABB entityViewBox(@NotNull final T entity) {
+        return entity.bb;
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererArrow.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererArrow.java
index 0996f594e..7998bd015 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererArrow.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererArrow.java
@@ -3,13 +3,14 @@ package net.minecraft.client.render.entity;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.projectile.ProjectileArrow;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
 
 public class EntityRendererArrow extends EntityRenderer<ProjectileArrow>
 {
     @Override
-    public void render(Tessellator tessellator, ProjectileArrow arrow, double x, double y, double z,
+    public void render(@NotNull Tessellator tessellator, @NotNull ProjectileArrow arrow, double x, double y, double z,
                        float yaw, float partialTick) {
         bindTexture("/assets/minecraft/textures/entity/arrows.png");
         GL11.glPushMatrix();
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererBoat.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererBoat.java
index d53a766c6..5ecdc0d13 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererBoat.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererBoat.java
@@ -2,37 +2,39 @@ package net.minecraft.client.render.entity;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.TileEntityRenderDispatcher;
-import net.minecraft.client.render.model.ModelBase;
-import net.minecraft.client.render.model.ModelBoat;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.tileentity.TileEntityRendererFlag;
+import net.minecraft.core.block.entity.TileEntityFlag;
 import net.minecraft.core.entity.vehicle.EntityBoat;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.wind.WindProvider;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
 
 public class EntityRendererBoat extends EntityRenderer<EntityBoat>
 {
-	
-	private final Minecraft mc = Minecraft.getMinecraft();
 
-    public EntityRendererBoat()
-    {
-        shadowSize = 0.5F;
-        modelBoat = new ModelBoat();
-        flagRenderer.setRenderDispatcher(TileEntityRenderDispatcher.instance);
+    private final TileEntityRendererFlag flagRenderer;
+    private final Minecraft mc = Minecraft.getMinecraft();
+
+    public EntityRendererBoat() {
+        super();
+        this.shadowSize = 0.5F;
+        this.flagRenderer = (TileEntityRendererFlag) (Object) TileEntityRenderDispatcher.instance.getRenderer(TileEntityFlag.class); // Definitely safe casting :)
     }
 
     @Override
-    public void render(Tessellator tessellator, EntityBoat entity, double x, double y, double z,
-                       float yaw, float partialTick)
+    public void render(@NotNull final Tessellator tessellator, @NotNull final EntityBoat entity, final double x, final double y, final double z,
+                       final float yaw, final float partialTick)
     {
+        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
         GL11.glPushMatrix();
         GL11.glTranslatef((float)x, (float)y, (float)z);
         GL11.glRotatef(180F - yaw, 0.0F, 1.0F, 0.0F);
-        float hurt = (float)entity.boatTimeSinceHit - partialTick;
+        final float hurt = (float)entity.boatTimeSinceHit - partialTick;
         float dmg = (float)entity.boatCurrentDamage - partialTick;
         if(dmg < 0.0F)
         {
@@ -44,29 +46,28 @@ public class EntityRendererBoat extends EntityRenderer<EntityBoat>
         }
         if (entity.tileEntityFlag != null)
         {
-            World theWorld = mc.currentWorld;
-            WindProvider theWind = theWorld.getWorldType().getWindManager();
+            final World theWorld = this.mc.currentWorld;
+            final WindProvider theWind = theWorld.getWorldType().getWindManager();
 
-            float windAngle = theWind.getWindDirection(theWorld, (float) x, (float) y, (float) z) * 360f + (180 - yaw);
-            float boatAngle = 180;
+            final float windAngle = theWind.getWindDirection(theWorld, (float) x, (float) y, (float) z) * 360f + (180 - yaw);
+            final float boatAngle = 180;
 
             // If boat speed is 0, windAngle is 100% and boatAngle is 0%
             // If boat speed is > 3, windAngle is 0% and boatAngle is 100%
-            float boatSpeed = MathHelper.sqrt_float((float) (entity.xd * entity.xd + entity.zd * entity.zd));
-            float angle = MathHelper.lerp(windAngle, boatAngle, (float)MathHelper.clamp(boatSpeed, 0, 0.25) * 4);
+            final float boatSpeed = MathHelper.sqrt_float((float) (entity.xd * entity.xd + entity.zd * entity.zd));
+            final float angle = MathHelper.lerp(windAngle, boatAngle, (float)MathHelper.clamp(boatSpeed, 0, 0.25) * 4);
 
-            flagRenderer.doRender(entity.tileEntityFlag, -1.19, 0.187, -0.5, partialTick, false, angle, 1.0f);
+            this.flagRenderer.doRender(tessellator, entity.tileEntityFlag, -1.19, 0.187, -0.5, partialTick, false, angle, 1.0f);
         }
         TextureRegistry.blockAtlas.bind();
-        float f4 = 0.75F;
+        final float f4 = 0.75F;
         GL11.glScalef(f4, f4, f4);
         GL11.glScalef(1.0F / f4, 1.0F / f4, 1.0F / f4);
         bindTexture("/assets/minecraft/textures/entity/boat.png");
-        GL11.glScalef(-1F, -1F, 1.0F);
-        modelBoat.render(null, 0.0F, 0.0F, -0.1F, 0.0F, 0.0F, 0.0625F, partialTick);
+        GL11.glScalef(1/16f, 1/16f, -1/16f);
+        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+        getModel("main").render(tessellator);
         GL11.glPopMatrix();
+        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
     }
-
-    protected ModelBase modelBoat;
-    private TileEntityRendererFlag flagRenderer = new TileEntityRendererFlag();
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererCannonball.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererCannonball.java
index b10c0a198..4210664ab 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererCannonball.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererCannonball.java
@@ -1,31 +1,25 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelBase;
-import net.minecraft.client.render.model.ModelCannonball;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.projectile.ProjectileCannonball;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 
 public class EntityRendererCannonball extends EntityRenderer<ProjectileCannonball>
 {
 
-    protected ModelBase modelCannonball;
-
-    public EntityRendererCannonball()
-    {
-        modelCannonball = new ModelCannonball();
+    public EntityRendererCannonball() {
+        super();
     }
 
     @Override
-    public void render(Tessellator tessellator, ProjectileCannonball entity, double x, double y, double z,
-                       float yaw, float partialTick)
-    {
+    public void render(@NotNull final Tessellator tessellator, @NotNull final ProjectileCannonball entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
         GL11.glPushMatrix();
         GL11.glTranslatef((float)x, (float)y, (float)z);
-        GL11.glRotatef(180F - yaw, 0.0F, 1.0F, 0.0F);
+        GL11.glRotatef(yaw, 0.0F, 1.0F, 0.0F);
         bindTexture("/assets/minecraft/textures/entity/cannonball.png");
-        GL11.glScalef(-1F, -1F, 1.0F);
-        modelCannonball.render(null, 0.0F, 0.0F, -0.1F, 0.0F, 0.0F, 0.03125F, partialTick);
+        GL11.glScalef(1/MobRenderer.ENTITY_RENDER_SCALE, 1/MobRenderer.ENTITY_RENDER_SCALE, -1/MobRenderer.ENTITY_RENDER_SCALE);
+        getModel("main").render(tessellator);
         GL11.glPopMatrix();
     }
 }
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererDefault.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererDefault.java
index 76b04542b..68f357952 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererDefault.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererDefault.java
@@ -2,13 +2,14 @@ package net.minecraft.client.render.entity;
 
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.Entity;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 
 public class EntityRendererDefault extends EntityRenderer<Entity>
 {
     @Override
-    public void render(Tessellator tessellator, Entity entity, double x, double y, double z,
-                       float yaw, float partialTick)
+    public void render(@NotNull final Tessellator tessellator, @NotNull final Entity entity, final double x, final double y, final double z,
+                       final float yaw, final float partialTick)
     {
         GL11.glPushMatrix();
         renderOffsetAABB(tessellator, entity.bb, x - entity.xo, y - entity.yo, z - entity.zo);
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFallingBlock.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFallingBlock.java
index dac540d6e..47ef9d12c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFallingBlock.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFallingBlock.java
@@ -12,6 +12,7 @@ import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.entity.EntityFallingBlock;
 import net.minecraft.core.world.BlocksContainer;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 
 public class EntityRendererFallingBlock extends EntityRenderer<EntityFallingBlock>
@@ -27,7 +28,7 @@ public class EntityRendererFallingBlock extends EntityRenderer<EntityFallingBloc
     }
 
     @Override
-    public void render(Tessellator tessellator, EntityFallingBlock fallingBlock, double x, double y, double z, float yaw, float partialTick) {
+    public void render(@NotNull Tessellator tessellator, @NotNull EntityFallingBlock fallingBlock, double x, double y, double z, float yaw, float partialTick) {
         if (container == null || container.world != fallingBlock.world) {
             container = new BlocksContainer(fallingBlock.world);
         }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFireball.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFireball.java
deleted file mode 100644
index 1a5017b8e..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFireball.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package net.minecraft.client.render.entity;
-
-import net.minecraft.client.render.item.model.ItemModelDispatcher;
-import net.minecraft.client.render.texture.stitcher.IconCoordinate;
-import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.entity.projectile.ProjectileFireball;
-
-import net.minecraft.core.item.Items;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL12;
-
-/**
- * @deprecated replaced by use of the more generic {@link EntityRendererSprite}
- */
-@Deprecated
-public class EntityRendererFireball extends EntityRenderer<ProjectileFireball> {
-
-    public EntityRendererFireball()
-    {
-    }
-
-    public void renderFireball(ProjectileFireball entity, double d, double d1, double d2,
-                               float f, float f1)
-    {
-
-        GL11.glPushMatrix();
-        GL11.glTranslatef((float)d, (float)d1, (float)d2);
-        GL11.glDisable(GL11.GL_LIGHTING);
-        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
-        final float scalar = 2.0F;
-        GL11.glScalef(scalar, scalar, scalar);
-        IconCoordinate i = ItemModelDispatcher.getInstance().getDispatch(Items.AMMO_FIREBALL).getIcon(null, Items.AMMO_FIREBALL.getDefaultStack());
-        i.parentAtlas.bind();
-        Tessellator tessellator = Tessellator.instance;
-        float f3 = (float) i.getIconUMin();
-        float f4 = (float) i.getIconUMax();
-        float f5 = (float) i.getIconVMin();
-        float f6 = (float) i.getIconVMax();
-        float f7 = 1.0F;
-        float f8 = 0.5F;
-        float f9 = 0.25F;
-        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        GL11.glRotatef(180F - renderDispatcher.viewLerpYaw, 0.0F, 1.0F, 0.0F);
-        GL11.glRotatef(-renderDispatcher.viewLerpPitch, 1.0F, 0.0F, 0.0F);
-        tessellator.startDrawingQuads();
-        tessellator.setNormal(0.0F, 0.0F, 0.0F);
-        tessellator.addVertexWithUV(0.0F - f8, 0.0F - f9, 0.0D, f3, f6);
-        tessellator.addVertexWithUV(f7 - f8, 0.0F - f9, 0.0D, f4, f6);
-        tessellator.addVertexWithUV(f7 - f8, 1.0F - f9, 0.0D, f4, f5);
-        tessellator.addVertexWithUV(0.0F - f8, 1.0F - f9, 0.0D, f3, f5);
-        tessellator.draw();
-        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
-        GL11.glPopMatrix();
-        GL11.glEnable(GL11.GL_LIGHTING);
-    }
-
-    @Override
-    public void render(Tessellator tessellator, ProjectileFireball entity, double x, double y, double z,
-                       float yaw, float partialTick)
-    {
-        renderFireball(entity, x, y, z, yaw, partialTick);
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFishingBobber.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFishingBobber.java
index 7b4692e63..70f69f443 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFishingBobber.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererFishingBobber.java
@@ -5,6 +5,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.EntityFishingBobber;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.Vec3;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 public class EntityRendererFishingBobber extends EntityRendererSprite<EntityFishingBobber>
 {
@@ -14,7 +15,7 @@ public class EntityRendererFishingBobber extends EntityRendererSprite<EntityFish
     }
 
     @Override
-    public void render(Tessellator tessellator, EntityFishingBobber entity, double x, double y, double z, float yaw, float partialTick) {
+    public void render(@NotNull Tessellator tessellator, @NotNull EntityFishingBobber entity, double x, double y, double z, float yaw, float partialTick) {
         super.render(tessellator, entity, x, y, z, yaw, partialTick);
         if(entity.owner != null)
         {
@@ -28,7 +29,7 @@ public class EntityRendererFishingBobber extends EntityRendererSprite<EntityFish
             double xp = entity.owner.xo + (entity.owner.x - entity.owner.xo) * (double)partialTick + vec3.x;
             double yp = entity.owner.yo + (entity.owner.y - entity.owner.yo) * (double)partialTick + vec3.y;
             double zp = entity.owner.zo + (entity.owner.z - entity.owner.zo) * (double)partialTick + vec3.z;
-            if(renderDispatcher.gameSettings.thirdPersonView.value > 0)
+            if(renderDispatcher.settings.thirdPersonView.value > 0)
             {
                 float rr = ((entity.owner.yBodyRotO + (entity.owner.yBodyRot - entity.owner.yBodyRotO) * partialTick) * MathHelper.PI) / 180F;
                 double ss = MathHelper.sin(rr);
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererGeneric.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererGeneric.java
new file mode 100644
index 000000000..c64d1ed24
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererGeneric.java
@@ -0,0 +1,25 @@
+package net.minecraft.client.render.entity;
+
+import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.core.entity.Entity;
+import org.jetbrains.annotations.NotNull;
+import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
+public class EntityRendererGeneric<T extends Entity> extends EntityRenderer<T>{
+    public final @NotNull StaticEntityModel entityModel;
+    public EntityRendererGeneric(final @NotNull StaticEntityModel entityModel, final float shadowSize) {
+        super();
+        this.shadowSize = shadowSize;
+        this.entityModel = entityModel;
+    }
+    @Override
+    public void render(final @NotNull Tessellator tessellator, final @NotNull T entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        GL11.glPushMatrix();
+        bindTexture("/assets/minecraft/textures/entity/creeper/0.png");
+        GL11.glTranslated(x, y, z);
+        this.entityModel.resetBones();
+        this.entityModel.render(tessellator);
+        GL11.glPopMatrix();
+    }
+}
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererItem.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererItem.java
index 98eb6efcc..a4d01df79 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererItem.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererItem.java
@@ -2,6 +2,7 @@ package net.minecraft.client.render.entity;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.core.entity.EntityItem;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 
 import net.minecraft.client.render.LightmapHelper;
@@ -10,8 +11,6 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
-import org.lwjgl.opengl.GL12;
-import org.useless.dragonfly.DisplayPos;
 
 import static org.lwjgl.opengl.GL11.glPushMatrix;
 
@@ -24,7 +23,7 @@ public class EntityRendererItem extends EntityRenderer<EntityItem>
 		shadowOpacity = 0.75F;
 	}
 
-	public void render(Tessellator tessellator, final EntityItem entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
+	public void render(@NotNull Tessellator tessellator, final @NotNull EntityItem entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
 		float brightness = 1.0f;
 		if(!LightmapHelper.isLightmapEnabled()) {
 			brightness = entity.getBrightness(partialTick);
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererLightningBolt.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererLightningBolt.java
index 24f68064b..e77c83682 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererLightningBolt.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererLightningBolt.java
@@ -4,6 +4,7 @@ import java.util.Random;
 
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.EntityLightning;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 
 public class EntityRendererLightningBolt extends EntityRenderer<EntityLightning>
@@ -14,7 +15,7 @@ public class EntityRendererLightningBolt extends EntityRenderer<EntityLightning>
     }
 
     @Override
-    public void render(Tessellator tessellator, EntityLightning lightning, double x, double y, double z,
+    public void render(@NotNull Tessellator tessellator, @NotNull EntityLightning lightning, double x, double y, double z,
                        float yaw, float partialTick)
     {
         GL11.glDisable(GL11.GL_TEXTURE_2D);
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererMinecart.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererMinecart.java
index a937cccf0..5c0f563c8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererMinecart.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererMinecart.java
@@ -2,8 +2,6 @@ package net.minecraft.client.render.entity;
 
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
-import net.minecraft.client.render.model.ModelBase;
-import net.minecraft.client.render.model.ModelMinecart;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Block;
@@ -12,22 +10,25 @@ import net.minecraft.core.Global;
 import net.minecraft.core.entity.vehicle.EntityMinecart;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.Vec3;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
 
 public class EntityRendererMinecart extends EntityRenderer<EntityMinecart> {
     public EntityRendererMinecart() {
-        shadowSize = 0.5F;
-        modelMinecart = new ModelMinecart();
+        super();
+        this.shadowSize = 0.5F;
     }
 
     @Override
-    public void render(Tessellator tessellator, EntityMinecart minecart, final double x, final double y, final double z, final float yaw, final float partialTick) {
+    public void render(@NotNull final Tessellator tessellator, @NotNull final EntityMinecart minecart, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
         GL11.glPushMatrix();
-        
-        double lerpX = MathHelper.lerp(minecart.xo, minecart.x, partialTick);
-        double lerpY = MathHelper.lerp(minecart.yo, minecart.y, partialTick);
-        double lerpZ = MathHelper.lerp(minecart.zo, minecart.z, partialTick);
-        Vec3 vec3 = minecart.getPos(lerpX, lerpY, lerpZ); // Opposite of velocity vector?
+
+        final double lerpX = MathHelper.lerp(minecart.xo, minecart.x, partialTick);
+        final double lerpY = MathHelper.lerp(minecart.yo, minecart.y, partialTick);
+        final double lerpZ = MathHelper.lerp(minecart.zo, minecart.z, partialTick);
+        final Vec3 vec3 = minecart.getPos(lerpX, lerpY, lerpZ); // Opposite of velocity vector?
         double lerpXRot = MathHelper.lerp(minecart.xRotO, minecart.xRot, partialTick);
 
         double renderX = x;
@@ -60,7 +61,7 @@ public class EntityRendererMinecart extends EntityRenderer<EntityMinecart> {
                 lerpXRot = Math.atan(velVec.y) * 73D;
             }
 
-            Vec3 realVecVec = Vec3.getTempVec3(minecart.xd, minecart.yd, minecart.zd);
+            final Vec3 realVecVec = Vec3.getTempVec3(minecart.xd, minecart.yd, minecart.zd);
 
             doAFlip = velVec.dotProduct(realVecVec) < 0;
 
@@ -69,7 +70,7 @@ public class EntityRendererMinecart extends EntityRenderer<EntityMinecart> {
         GL11.glTranslated(renderX, renderY, renderZ);
         GL11.glRotated(180F - renderYaw, 0.0F, 1.0F, 0.0F);
         GL11.glRotated(-lerpXRot, 0.0F, 0.0F, 1.0F);
-        double hurtAngle = minecart.timeSinceHit - partialTick;
+        final double hurtAngle = minecart.timeSinceHit - partialTick;
         double currentDamage = minecart.currentDamage - partialTick;
         if(currentDamage < 0.0F) {
             currentDamage = 0.0F;
@@ -97,7 +98,7 @@ public class EntityRendererMinecart extends EntityRenderer<EntityMinecart> {
             }
             switch (minecart.getType()){
                 case EntityMinecart.CHEST_CART:
-                    Block<?> block;
+                    final Block<?> block;
                     if ((minecart.getMeta() & 0b0000_0001) != 0) {
                         block = Blocks.CHEST_PLANKS_OAK_PAINTED;
                     } else {
@@ -119,12 +120,12 @@ public class EntityRendererMinecart extends EntityRenderer<EntityMinecart> {
             GL11.glScalef(1.0F / scale, 1.0F / scale, 1.0F / scale);
         }
         bindTexture("/assets/minecraft/textures/entity/cart.png");
-        GL11.glScalef(-1F, -1F, 1.0F);
-        modelMinecart.render(null, 0.0F, 0.0F, -0.1F, 0.0F, 0.0F, 0.0625F, partialTick);
+        GL11.glScalef(1/16f, 1/16f, -1/16f);
+        getModel("main").render(tessellator);
         GL11.glPopMatrix();
+        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
     }
-
-    private void drawDebugVec(Tessellator tessellator, Vec3 pos, Vec3 vec, double scale, float r, float g, float b, float a){
+    private static void drawDebugVec(final Tessellator tessellator, final Vec3 pos, final Vec3 vec, final double scale, final float r, final float g, final float b, final float a){
         if (pos == null || vec == null) return;
         GL11.glLineWidth(10);
         GL11.glDisable(GL11.GL_LIGHTING);
@@ -140,5 +141,4 @@ public class EntityRendererMinecart extends EntityRenderer<EntityMinecart> {
         GL11.glEnable(GL11.GL_TEXTURE_2D);
         GL11.glEnable(GL11.GL_LIGHTING);
     }
-    protected ModelBase modelMinecart;
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererPainting.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererPainting.java
index cc2f8da3b..00cddbbf7 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererPainting.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererPainting.java
@@ -10,6 +10,7 @@ import net.minecraft.core.enums.ArtType;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
 
@@ -125,7 +126,7 @@ public class EntityRendererPainting extends EntityRenderer<EntityPainting>
         {
             worldZ = MathHelper.floor(entity.z + (double)(centerX / 16F));
         }
-        float brightness = renderDispatcher.world.getLightBrightness(worldX, worldY, worldZ);
+        float brightness = entity.world.getLightBrightness(worldX, worldY, worldZ);
         if (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) {
             LightmapHelper.setLightmapCoord(entity.world.getLightmapCoord(worldX, worldY, worldZ, entity.world.getBlockLightValue(worldX, worldY, worldZ)));
         	brightness = 1.0f;
@@ -134,7 +135,7 @@ public class EntityRendererPainting extends EntityRenderer<EntityPainting>
     }
 
     @Override
-    public void render(Tessellator tessellator, EntityPainting entity, double x, double y, double z, float yaw, float partialTick) {
+    public void render(@NotNull Tessellator tessellator, @NotNull EntityPainting entity, double x, double y, double z, float yaw, float partialTick) {
         rand.setSeed(187L);
         GL11.glPushMatrix();
         GL11.glTranslatef((float)x, (float)y, (float)z);
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererSprite.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererSprite.java
index a97975654..f513d37cb 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererSprite.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererSprite.java
@@ -6,6 +6,7 @@ import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.item.Item;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
 
@@ -33,7 +34,7 @@ public class EntityRendererSprite<T extends Entity> extends EntityRenderer<T>
     }
 
     @Override
-    public void render(Tessellator tessellator, T entity, double x, double y, double z,
+    public void render(@NotNull Tessellator tessellator, @NotNull T entity, double x, double y, double z,
                        float yaw, float partialTick)
     {
         GL11.glPushMatrix();
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererTNT.java b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererTNT.java
index 22606bde2..0055535fd 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererTNT.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/EntityRendererTNT.java
@@ -7,6 +7,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.EntityPrimedTNT;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.Blocks;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 
 public class EntityRendererTNT extends EntityRenderer<EntityPrimedTNT>
@@ -17,7 +18,7 @@ public class EntityRendererTNT extends EntityRenderer<EntityPrimedTNT>
     }
 
     @Override
-    public void render(Tessellator tessellator, EntityPrimedTNT tnt, double x, double y, double z, float yaw, float partialTick)
+    public void render(@NotNull Tessellator tessellator, @NotNull EntityPrimedTNT tnt, double x, double y, double z, float yaw, float partialTick)
     {
         GL11.glPushMatrix();
         GL11.glTranslatef((float)x, (float)y, (float)z);
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRenderer.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRenderer.java
index 3a49016bd..939f9752c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRenderer.java
@@ -4,266 +4,230 @@ import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.font.FontRenderer;
-import net.minecraft.client.render.model.ModelBase;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.Global;
 import net.minecraft.core.entity.Mob;
+import net.minecraft.core.util.helper.Color;
 import net.minecraft.core.util.helper.MathHelper;
+import net.minecraft.core.util.phys.AABB;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
 import org.slf4j.Logger;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRenderer<T extends Mob> extends EntityRenderer<T>
-{
-    private static final Logger LOGGER = LogUtils.getLogger();
-    public static final int MAX_ARMOR_LAYERS = 4;
-    protected ModelBase mainModel;
-    protected ModelBase armorModel;
-    protected ModelBase overlayModel;
-    protected String overlayTexture;
-    private final Minecraft mc;
+import java.util.ArrayList;
+import java.util.List;
 
-    public MobRenderer(ModelBase model, float shadowSize)
-    {
-        this.mainModel = model;
+public abstract class MobRenderer<T extends Mob> extends EntityRenderer<T>{
+    public static final float ENTITY_RENDER_SCALE = 16f;
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private final @NotNull List<@Nullable StaticEntityModel> setupModels = new ArrayList<>();
+    public MobRenderer(final float shadowSize) {
+        super();
         this.shadowSize = shadowSize;
-        this.mc = Minecraft.getMinecraft();
-    }
-
-
-    public void setArmorModel(ModelBase armor)
-    {
-        armorModel = armor;
-    }
-    public void setOverlayModel(ModelBase modelbase, String texture)
-    {
-        overlayModel = modelbase;
-        overlayTexture = texture;
     }
+    @Override
+    public void render(final @NotNull Tessellator tessellator, final @NotNull T entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        loadEntityTexture(entity);
+//        bindTexture("/assets/minecraft/textures/entity/creeper/debug.png");
+        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+        GL11.glDisable(GL11.GL_CULL_FACE);
 
-    public void render(Tessellator tessellator, T entity, double x, double y, double z,
-                       float yaw, float partialTick)
-    {
         GL11.glPushMatrix();
-        GL11.glDisable(GL11.GL_CULL_FACE);
-        mainModel.swingProgress = getSwingProgress(entity, partialTick);
-        if (armorModel != null) armorModel.swingProgress = mainModel.swingProgress;
-        if (overlayModel != null) overlayModel.swingProgress = mainModel.swingProgress;
-        mainModel.isRiding = entity.isPassenger();
-        if (armorModel != null) armorModel.isRiding = mainModel.isRiding;
-        if (overlayModel != null) overlayModel.isRiding = mainModel.isRiding;
-        try
-        {
-            float bodyYaw = entity.yBodyRotO + (entity.yBodyRot - entity.yBodyRotO) * partialTick;
-            float headYaw = entity.yRotO + (entity.yRot - entity.yRotO) * partialTick;
-            float headPitch = entity.xRotO + (entity.xRot - entity.xRotO) * partialTick;
-            translateModel(entity, x, y, z);
-            float limbSway = limbSway(entity, partialTick);
-            setupRotations(entity, limbSway, bodyYaw, partialTick);
-            float scale = 0.0625F;
-            GL12.glEnable(GL12.GL_RESCALE_NORMAL);
-            GL11.glScalef(-1F, -1F, 1.0F);
-            setupScale(entity, partialTick);
-            GL11.glTranslatef(0.0F, -24F * scale - 0.0078125F, 0.0F);
-            float walkSpeed = entity.walkAnimSpeedO + (entity.walkAnimSpeed - entity.walkAnimSpeedO) * partialTick;
-            float walkProgress = entity.walkAnimPos - entity.walkAnimSpeed * (1.0F - partialTick);
-            if(walkSpeed > 1.0F)
-            {
-                walkSpeed = 1.0F;
-            }
-            loadEntityTexture(entity);
-            GL11.glEnable(GL11.GL_ALPHA_TEST);
-            mainModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-            if (overlayModel != null)
-            {
-                bindTexture(overlayTexture);
-                overlayModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-            }
-            for(int renderPass = 0; renderPass < MAX_ARMOR_LAYERS; renderPass++)
-            {
-                if(prepareArmor(entity, renderPass, partialTick))
-                {
-                    armorModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                    GL11.glDisable(GL11.GL_BLEND);
-                    GL11.glEnable(GL11.GL_ALPHA_TEST);
+        preRenderTransform(entity, x, y, z, yaw, partialTick);
+
+        float brightness = entity.getBrightness(partialTick);
+        if (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) brightness = 1.0f;
+
+        this.setupModels.clear();
+        final int maxRenderLayer = maxRenderLayer(entity);
+        for(int layer = 0; layer <= maxRenderLayer; layer++) {
+            try {
+                final StaticEntityModel model = getAndSetupModelForLayer(entity, brightness, partialTick, layer);
+                this.setupModels.add(model);
+                if (model != null) {
+                    model.render(tessellator);
                 }
+            } catch (final Exception e) {
+                LOGGER.error("Error setting up model on layer '{}' in renderer '{}'", layer, getClass().getSimpleName(), e);
             }
-
-            renderAdditional(entity, partialTick);
-            float brightness = entity.getBrightness(partialTick);
-            if (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) brightness = 1.0f;
-            int argb = getOverlayColor(entity, brightness, partialTick);
-            if((argb >> 24 & 0xff) > 0 || entity.hurtTime > 0 || entity.deathTime > 0)
-            {
-                GL11.glDisable(GL11.GL_TEXTURE_2D);
-                GL11.glDisable(GL11.GL_ALPHA_TEST);
-                GL11.glEnable(GL11.GL_BLEND);
-                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-                GL11.glDepthFunc(514);
-                if(entity.hurtTime > 0 || entity.deathTime > 0)
-                {
-                    GL11.glColor4f(brightness, 0.0F, 0.0F, 0.4F);
-                    mainModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                    if (overlayModel != null) overlayModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                    for(int k = 0; k < MAX_ARMOR_LAYERS; k++)
-                    {
-                        if(prepareArmor(entity, k, partialTick))
-                        {
-                            GL11.glColor4f(brightness, 0.0F, 0.0F, 0.4F);
-                            armorModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                        }
+        }
+        renderAdditional(tessellator, entity, partialTick);
+        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+
+        final int argb = getOverlayColor(entity, brightness, partialTick);
+        final boolean hasOverlayAlpha = Color.alphaFromInt(argb) > 0;
+        if(hasOverlayAlpha || entity.hurtTime > 0 || entity.deathTime > 0) {
+            GL11.glDisable(GL11.GL_TEXTURE_2D);
+            GL11.glDisable(GL11.GL_ALPHA_TEST);
+            GL11.glEnable(GL11.GL_BLEND);
+            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+            GL11.glDepthFunc(GL11.GL_EQUAL);
+            if(entity.hurtTime > 0 || entity.deathTime > 0) {
+                for(int layer = 0; layer <= maxRenderLayer; layer++) {
+                    final StaticEntityModel model = this.setupModels.get(layer);
+                    if (model != null) {
+                        GL11.glColor4f(brightness, 0.0F, 0.0F, 0.4F);
+                        model.render(tessellator);
                     }
-
                 }
-                if((argb >> 24 & 0xff) > 0)
-                {
-                    float r = (float)(argb >> 16 & 0xff) / 255F;
-                    float g = (float)(argb >> 8 & 0xff) / 255F;
-                    float b = (float)(argb & 0xff) / 255F;
-                    float a = (float)(argb >> 24 & 0xff) / 255F;
-                    GL11.glColor4f(r, g, b, a);
-                    mainModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                    if (overlayModel != null) overlayModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                    for(int l = 0; l < MAX_ARMOR_LAYERS; l++)
-                    {
-                        if(prepareArmor(entity, l, partialTick))
-                        {
-                            GL11.glColor4f(r, g, b, a);
-                            armorModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                        }
-                    }
 
+            }
+            if(hasOverlayAlpha) {
+                final float r = Color.redFromInt(argb)/255f;
+                final float g = Color.greenFromInt(argb)/255f;
+                final float b = Color.blueFromInt(argb)/255f;
+                final float a = Color.alphaFromInt(argb)/255f;
+                for(int layer = 0; layer < maxRenderLayer; layer++) {
+                    final StaticEntityModel model = this.setupModels.get(layer);
+                    if (model != null) {
+                        GL11.glColor4f(r, g, b, a);
+                        model.render(tessellator);
+                    }
                 }
-                GL11.glDepthFunc(GL11.GL_LEQUAL);
-                GL11.glDisable(GL11.GL_BLEND);
-                GL11.glEnable(GL11.GL_ALPHA_TEST);
-                GL11.glEnable(GL11.GL_TEXTURE_2D);
             }
-            GL11.glDisable(GL12.GL_RESCALE_NORMAL);
-        }
-        catch(Exception exception)
-        {
-            LOGGER.error("Render exception in class '{}'!", getClass().getSimpleName(), exception);
+            GL11.glDepthFunc(GL11.GL_LEQUAL);
+            GL11.glDisable(GL11.GL_BLEND);
+            GL11.glEnable(GL11.GL_ALPHA_TEST);
+            GL11.glEnable(GL11.GL_TEXTURE_2D);
         }
-        GL11.glEnable(GL11.GL_CULL_FACE);
+
         GL11.glPopMatrix();
+
+        GL11.glEnable(GL11.GL_CULL_FACE);
+        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
         renderSpecials(tessellator, entity, x, y, z);
     }
 
-    protected void translateModel(T entity, double x, double y, double z)
-    {
-        GL11.glTranslatef((float)x, (float)y, (float)z);
-    }
+    protected void preRenderTransform(final @NotNull T entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        GL11.glTranslated(x, y, z);
+        GL11.glRotatef(-getBodyYaw(entity, partialTick) * MathHelper.RAD_TO_DEG, 0, 1, 0);
+        GL11.glScalef(1/ENTITY_RENDER_SCALE, 1/ENTITY_RENDER_SCALE, -1/ENTITY_RENDER_SCALE);
 
-    protected void setupRotations(T entity, float ticksExisted, float bodyYaw, float partialTick)
-    {
-        GL11.glRotatef(180F - bodyYaw, 0.0F, 1.0F, 0.0F);
-        if(entity.deathTime > 0)
-        {
-            float rotationProgress = ((((float)entity.deathTime + partialTick) - 1.0F) / 20F) * 1.6F;
+        if(entity.deathTime > 0) {
+            float rotationProgress = (((entity.deathTime + partialTick) - 1.0F) / 20F) * 1.6F;
             rotationProgress = MathHelper.sqrt_float(rotationProgress);
-            if(rotationProgress > 1.0F)
-            {
+            if(rotationProgress > 1.0F) {
                 rotationProgress = 1.0F;
             }
             GL11.glRotatef(rotationProgress * getMaxDeathRotation(entity), 0.0F, 0.0F, 1.0F);
         }
     }
 
-    protected float getSwingProgress(T entity, float partialTick)
-    {
-        return entity.getSwingProgress(partialTick);
-    }
-
-    protected float limbSway(T entity, float partialTick)
-    {
-        return (float)entity.tickCount + partialTick;
+    protected float getLimbSwing(final @NotNull T entity, final float partialTick) {
+        return entity.walkAnimPos - entity.walkAnimSpeed * (1.0F - partialTick);
     }
 
-    protected void renderAdditional(T entity, float partialTick)
-    {
+    protected float getLimbYaw(final @NotNull T entity, final float partialTick) {
+        float limbYaw = MathHelper.lerp(entity.walkAnimSpeedO, entity.walkAnimSpeed, partialTick);
+        if(limbYaw > 1.0F) {
+            limbYaw = 1.0F;
+        }
+        return limbYaw;
     }
 
-    protected boolean prepareArmor(T entity, int layer, float partialTick)
-    {
-        return false;
+    protected float getLimbPitch(final @NotNull T entity, final float partialTick) {
+        return entity.tickCount + partialTick;
     }
 
-    protected float getMaxDeathRotation(T entity)
-    {
-        return 90F;
+    protected float getBodyYaw(final @NotNull T entity, final float partialTick) {
+        return MathHelper.lerp(entity.yBodyRotO, entity.yBodyRot, partialTick) * MathHelper.DEG_TO_RAD;
     }
 
-    protected int getOverlayColor(T entity, float brightness, float partialTick)
-    {
-        return 0;
+    protected float getHeadYaw(final @NotNull T entity, final float partialTick) {
+        return MathHelper.lerp(entity.yRotO, entity.yRot, partialTick) * MathHelper.DEG_TO_RAD;
     }
 
-    protected void setupScale(T entity, float partialTick)
-    {
+    protected float getHeadPitch(final @NotNull T entity, final float partialTick) {
+        return MathHelper.lerp(entity.xRotO, entity.xRot, partialTick) * MathHelper.DEG_TO_RAD;
     }
 
-    protected void renderSpecials(Tessellator tessellator, T entity, double x, double y, double z)
+    protected void renderSpecials(final @NotNull Tessellator tessellator, final @NotNull T entity, final double x, final double y, final double z)
     {
-        if(mc.canRenderEntityLabel())
-        {
+        if(Minecraft.getMinecraft().canRenderEntityLabel()) {
             renderLivingLabel(tessellator, entity, Integer.toString(entity.id), x, y, z, 64, false);
         }
-        else if (!entity.nickname.isEmpty())
-        {
+        else if (!entity.nickname.isEmpty()) {
             renderLivingLabel(tessellator, entity, entity.getDisplayName(), x, y, z, 64, true);
         }
     }
 
-    protected void renderLivingLabel(Tessellator t, T entity, String s, double x, double y, double z, int maxDistance, boolean depthTest)
+    protected void renderLivingLabel(final @NotNull Tessellator t, final @NotNull T entity, final @NotNull CharSequence text, final double x, final double y, final double z, final int maxDistance, final boolean depthTest)
     {
-        final float f = (float) renderDispatcher.camera.distanceTo(entity);
-        if (f > maxDistance)
+        final float cameraDistance = (float) this.renderDispatcher.camera.distanceTo(entity);
+        if (cameraDistance > maxDistance)
         {
             return;
         }
         final FontRenderer sr = getFont();
-        final float f1 = 1.6F;
-        final float f2 = 0.01666667F * f1;
+        final float scale = 1.6f/60f;
+
         GL11.glPushMatrix();
-        GL11.glTranslatef((float) x + 0.0F, (float) y + entity.getHeadHeight() + 0.8f, (float) z);
+        GL11.glTranslatef((float) x, (float) y + entity.getHeadHeight() + 0.8f, (float) z);
         GL11.glNormal3f(0.0F, 1.0F, 0.0F);
-        GL11.glRotatef(-renderDispatcher.viewLerpYaw, 0.0F, 1.0F, 0.0F);
-        GL11.glRotatef(renderDispatcher.viewLerpPitch, 1.0F, 0.0F, 0.0F);
-        GL11.glScalef(-f2, -f2, f2);
-        GL11.glDisable(2896 /* GL_LIGHTING */);
+        GL11.glRotatef(-this.renderDispatcher.viewLerpYaw, 0.0F, 1.0F, 0.0F);
+        GL11.glRotatef(this.renderDispatcher.viewLerpPitch, 1.0F, 0.0F, 0.0F);
+        GL11.glScalef(-scale, -scale, scale);
+        GL11.glDisable(GL11.GL_LIGHTING);
         GL11.glDepthMask(false);
-        if (!depthTest) GL11.glDisable(2929 /* GL_DEPTH_TEST */);
-        GL11.glEnable(3042 /* GL_BLEND */);
+        if (!depthTest) GL11.glDisable(GL11.GL_DEPTH_TEST);
+        GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-        byte byte0 = 0;
-        GL11.glDisable(3553 /* GL_TEXTURE_2D */);
+        GL11.glDisable(GL11.GL_TEXTURE_2D);
+
         t.startDrawingQuads();
-        final int j = sr.stringWidth(s) / 2;
+        final int halfTextWidth = sr.stringWidth(text) / 2;
         t.setColorRGBA_F(0.0F, 0.0F, 0.0F, 0.25F);
-        t.addVertex(-j - 1, -1 + byte0, 0.0D);
-        t.addVertex(-j - 1, 8 + byte0, 0.0D);
-        t.addVertex(j + 1, 8 + byte0, 0.0D);
-        t.addVertex(j + 1, -1 + byte0, 0.0D);
+        t.addVertex(-halfTextWidth - 1, -1, 0.0D);
+        t.addVertex(-halfTextWidth - 1,  8, 0.0D);
+        t.addVertex( halfTextWidth,      8, 0.0D);
+        t.addVertex( halfTextWidth,     -1, 0.0D);
         t.draw();
-        GL11.glEnable(3553 /* GL_TEXTURE_2D */);
-        sr.render(t, s, -sr.stringWidth(s) / 2, byte0).setColor(0x20ffffff).call();
-        if (!depthTest) GL11.glEnable(2929 /* GL_DEPTH_TEST */);
+
+        GL11.glEnable(GL11.GL_TEXTURE_2D);
+        sr.render(t, text, -halfTextWidth, 0).setColor(0x20ffffff).call();
+        if (!depthTest) GL11.glEnable(GL11.GL_DEPTH_TEST);
         GL11.glDepthMask(true);
-        sr.render(t, s, -sr.stringWidth(s) / 2, byte0).setColor(0xFFFFFF).call();
-        GL11.glEnable(2896 /* GL_LIGHTING */);
-        GL11.glDisable(3042 /* GL_BLEND */);
-        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+        sr.render(t, text, -halfTextWidth, 0).setColor(0xFFFFFF).call();
+        GL11.glEnable(GL11.GL_LIGHTING);
+        GL11.glDisable(GL11.GL_BLEND);
         GL11.glPopMatrix();
     }
-    public void loadEntityTexture(T entity)
+
+    protected int getOverlayColor(final @NotNull T entity, final float brightness, final float partialTick) {
+        return 0;
+    }
+
+    protected float getMaxDeathRotation(final @NotNull T entity)
     {
-        if (!Minecraft.getMinecraft().gameSettings.mobVariants.value)
-        {
+        return 90F;
+    }
+
+    protected int maxRenderLayer(final @NotNull T entity) {
+        return 0;
+    }
+
+    protected abstract @Nullable StaticEntityModel getAndSetupModelForLayer(final @NotNull T entity, float brightness, final float partialTick, final int layer);
+
+    protected void renderAdditional(@NotNull final Tessellator tessellator, final @NotNull T entity, final float partialTick)
+    {
+    }
+
+    public void loadEntityTexture(final @NotNull T entity)
+    {
+        if (!Minecraft.getMinecraft().gameSettings.mobVariants.value) {
             bindTexture(entity.getDefaultEntityTexture());
         }
         else {
             bindTexture(entity.getEntityTexture());
         }
     }
+
+    @Override
+    public @NotNull AABB entityViewBox(@NotNull final T entity) {
+//        return this.entityModel.visibleBounds().cloneMove(entity.x, entity.y, entity.z);
+        return super.entityViewBox(entity);
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBiped.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBiped.java
index b7a882126..6b9b0d62e 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBiped.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBiped.java
@@ -1,53 +1,158 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.block.model.BlockModel;
+import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
-import net.minecraft.client.render.model.ModelBiped;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.IItemHolding;
 import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.monster.MobZombieArmored;
 import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 import org.useless.dragonfly.DisplayPos;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererBiped<T extends Mob> extends MobRenderer<T>
-{
-	protected ModelBiped modelBipedMain;
-
-
-	public MobRendererBiped(ModelBiped model, float shadowSize)
-    {
-        super(model, shadowSize);
-
-        this.modelBipedMain = model;
-	}
-
-	@Override
-	protected void renderAdditional(T entity, float partialTick) {
-		if (entity instanceof IItemHolding) {
-			IItemHolding itemHolder = (IItemHolding) entity;
-			ItemStack itemstack = itemHolder.getHeldItem();
-			if(itemstack != null) {
-				GL11.glPushMatrix();
-				if (((IItemHolding) entity).isLeftHanded()) {
-					modelBipedMain.armLeft.translateTo(0.0625F);
-					GL11.glRotatef(-90, 1, 0, 0);
-					GL11.glRotatef(180, 0, 1, 0);
-					GL11.glScalef(-1, 1, 1);
-					GL11.glTranslatef(1/16f, 2/16f, -10f/16f);
-					ItemModelDispatcher.getInstance().getDispatch(itemstack)
-						.render(Tessellator.instance, entity, itemstack, DisplayPos.THIRD_PERSON_LEFT_HAND, true, 1, entity.getBrightness(partialTick), 1f, partialTick, true);
-				} else {
-					modelBipedMain.armRight.translateTo(0.0625F);
-					GL11.glRotatef(-90, 1, 0, 0);
-					GL11.glScalef(-1, 1, -1);
-					GL11.glTranslatef(1/16f, 2/16f, -10f/16f);
-					ItemModelDispatcher.getInstance().getDispatch(itemstack)
-						.render(Tessellator.instance, entity, itemstack, DisplayPos.THIRD_PERSON_RIGHT_HAND, true, 1, entity.getBrightness(partialTick), 1f, partialTick, false);
-				}
-				GL11.glPopMatrix();
-			}
-		}
-	}
+public abstract class MobRendererBiped<T extends Mob> extends MobRenderer<T> {
+
+    public MobRendererBiped(final float shadowSize) {
+        super(shadowSize);
+    }
+
+    protected abstract @Nullable StaticEntityModel getActiveModel(@NotNull final T entity);
+
+    @Override
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final T entity, final float brightness, final float partialTick, final int layer) {
+       return setupAnimations(entity, getActiveModel(entity), partialTick, layer);
+    }
+
+    protected @Nullable StaticEntityModel setupAnimations(@NotNull final T entity, @Nullable final StaticEntityModel model, final float partialTick, final int layer) {
+        if (model == null) return null;
+        model.resetBones();
+        final BoneTransform rightArm = model.getTransform("rightArm");
+        final BoneTransform leftArm = model.getTransform("leftArm");
+        final BoneTransform rightLeg = model.getTransform("rightLeg");
+        final BoneTransform leftLeg = model.getTransform("leftLeg");
+        final BoneTransform waist = model.getTransform("waist");
+        final BoneTransform head = model.getTransform("head");
+
+        final float bodyYaw = getBodyYaw(entity, partialTick);
+        final float headYaw = getHeadYaw(entity, partialTick) - bodyYaw;
+        final float headPitch = getHeadPitch(entity, partialTick);
+        final float limbSwing = getLimbSwing(entity, partialTick);
+        final float limbYaw = getLimbYaw(entity, partialTick);
+        final float limbPitch = getLimbPitch(entity, partialTick);
+        final float swingProgress = entity.getSwingProgress(partialTick);
+
+        head.rotX = headPitch;
+        head.rotY = headYaw;
+        if (entity.getHeldObject() != null) {
+            final double rotX = Math.cos(limbSwing / 2 * 0.6662F) * 2.0F * limbYaw * 0.125F - 0.65f;
+            rightArm.rotX = rotX;
+            leftArm.rotX = rotX;
+        } else {
+            rightArm.rotX = Math.cos(limbSwing * 0.6662F + Math.PI) * 2.0F * limbYaw * 0.5F;
+            leftArm.rotX = Math.cos(limbSwing * 0.6662F) * 2.0F * limbYaw * 0.5F;
+        }
+        rightLeg.rotX = Math.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+        leftLeg.rotX = Math.cos(limbSwing * 0.6662F + Math.PI) * 1.4F * limbYaw;
+        if(entity.vehicle != null)
+        {
+            rightArm.rotX += -36 * MathHelper.DEG_TO_RAD;
+            leftArm.rotX += -36 * MathHelper.DEG_TO_RAD;
+            rightLeg.rotX = -72 * MathHelper.DEG_TO_RAD;
+            leftLeg.rotX = -72 * MathHelper.DEG_TO_RAD;
+            rightLeg.rotY = 18 * MathHelper.DEG_TO_RAD;
+            leftLeg.rotY = -18 * MathHelper.DEG_TO_RAD;
+        }
+        if (entity instanceof IItemHolding) {
+            final boolean hasItem = ((IItemHolding) entity).getHeldItem() != null;
+            if (hasItem) {
+                if (((IItemHolding) entity).isLeftHanded()) {
+                    leftArm.rotX = (leftArm.rotX * 0.5F) - 18 * MathHelper.DEG_TO_RAD;
+                } else {
+                    rightArm.rotX = (rightArm.rotX * 0.5F) - 18 * MathHelper.DEG_TO_RAD;
+                }
+            }
+
+        }
+        if (entity instanceof IItemHolding && ((IItemHolding) entity).isLeftHanded()) {
+            waist.rotY = Math.sin(Math.sqrt(swingProgress) * Math.PI * -2.0F) * 0.2F;
+
+            float f6 = 1.0F - swingProgress;
+            f6 *= f6;
+            f6 *= f6;
+            f6 = 1.0F - f6;
+            final double f7 = Math.sin(f6 * Math.PI);
+            final double f8 = Math.sin(swingProgress * Math.PI) * -(Math.toRadians(head.rotX) - 0.7F) * 0.75F;
+
+            leftArm.rotX -= f7 * 1.2D + f8;
+            leftArm.rotY += waist.rotY * 2.0F;
+            leftArm.rotZ = Math.sin(swingProgress * Math.PI) * 0.4F;
+        } else {
+            waist.rotY = Math.sin(Math.sqrt(swingProgress) * Math.PI * 2.0F) * 0.2F;
+
+            float f6 = 1.0F - swingProgress;
+            f6 *= f6;
+            f6 *= f6;
+            f6 = 1.0F - f6;
+            final double f7 = Math.sin(f6 * Math.PI);
+            final double f8 = Math.sin(swingProgress * Math.PI) * -(Math.toRadians(head.rotX) - 0.7F) * 0.75F;
+
+            rightArm.rotX -= f7 * 1.2D + f8;
+            rightArm.rotY += waist.rotY * 2.0F;
+            rightArm.rotZ = Math.sin(swingProgress * Math.PI) * -0.4F;
+        }
+
+        if(entity.isSneaking())
+        {
+            waist.rotX = 0.5F;
+            leftLeg.rotX -= 0.5F;
+            rightLeg.rotX -= 0.5F;
+            head.rotX -= 0.5F;
+
+            rightArm.rotX -= 0.4F;
+            leftArm.rotX -= 0.4F;
+            if (entity.getHeldObject() != null) {
+                rightArm.rotX -= 0.4f;
+                leftArm.rotX -= 0.4f;
+            }
+        }
+        rightArm.rotZ += Math.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        leftArm.rotZ -= Math.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        rightArm.rotX += Math.sin(limbPitch * 0.067F) * 0.05F;
+        leftArm.rotX -= Math.sin(limbPitch * 0.067F) * 0.05F;
+
+        return model;
+    }
+
+    @Override
+    protected void renderAdditional(@NotNull final Tessellator tessellator, final @NotNull T entity, final float partialTick) {
+        if (entity instanceof IItemHolding) {
+            final IItemHolding itemHolder = (IItemHolding) entity;
+            final ItemStack itemstack = itemHolder.getHeldItem();
+
+            final StaticEntityModel model = getActiveModel(entity);
+
+            if(itemstack != null) {
+                GL11.glPushMatrix();
+                if (((IItemHolding) entity).isLeftHanded()) {
+                    if (model != null) model.translateToBone("leftItem");
+                    GL11.glScalef(-1, 1, -1);
+                    GL11.glScalef(MobRenderer.ENTITY_RENDER_SCALE, MobRenderer.ENTITY_RENDER_SCALE, MobRenderer.ENTITY_RENDER_SCALE);
+                    ItemModelDispatcher.getInstance().getDispatch(itemstack)
+                        .render(tessellator, entity, itemstack, DisplayPos.THIRD_PERSON_LEFT_HAND, true, 1, LightmapHelper.isLightmapEnabled() ? 1f : entity.getBrightness(partialTick), 1f, partialTick, true);
+                } else {
+
+                    if (model != null) model.translateToBone("rightItem");
+                    GL11.glScalef(-1, 1, 1);
+                    GL11.glScalef(MobRenderer.ENTITY_RENDER_SCALE, MobRenderer.ENTITY_RENDER_SCALE, MobRenderer.ENTITY_RENDER_SCALE);
+                    ItemModelDispatcher.getInstance().getDispatch(itemstack)
+                        .render(tessellator, entity, itemstack, DisplayPos.THIRD_PERSON_RIGHT_HAND, true, 1, LightmapHelper.isLightmapEnabled() ? 1f : entity.getBrightness(partialTick), 1f, partialTick, false);
+                }
+                GL11.glPopMatrix();
+            }
+        }
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBipedArmored.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBipedArmored.java
index 9132a584c..546de215a 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBipedArmored.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererBipedArmored.java
@@ -1,42 +1,107 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.entity.player.PlayerLocal;
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
-import net.minecraft.client.render.model.ModelBiped;
 import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.IArmorWearing;
-import net.minecraft.core.entity.IItemHolding;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.enums.HumanArmorShape;
-import net.minecraft.core.item.*;
+import net.minecraft.core.item.IArmorItem;
+import net.minecraft.core.item.Item;
+import net.minecraft.core.item.ItemQuiver;
+import net.minecraft.core.item.ItemQuiverEndless;
+import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.item.Items;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 import org.useless.dragonfly.DisplayPos;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererBipedArmored<T extends Mob & IArmorWearing<HumanArmorShape>> extends MobRendererBiped<T> {
-    protected ModelBiped modelArmorA;
-    protected ModelBiped modelArmorB;
-
-    public MobRendererBipedArmored(ModelBiped model, float shadowSize) {
-        this(model, new ModelBiped(1.0F), new ModelBiped(0.5f), shadowSize);
+public abstract class MobRendererBipedArmored<T extends Mob & IArmorWearing<HumanArmorShape>> extends MobRendererBiped<T>{
+    public MobRendererBipedArmored(final float shadowSize) {
+        super(shadowSize);
     }
 
-    public MobRendererBipedArmored(ModelBiped model, ModelBiped modelArmorA, ModelBiped modelArmorB, float shadowSize) {
-        super(model, shadowSize);
+    @Override
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final T entity, final float brightness, final float partialTick, final int layer) {
+        if (layer == 0) return super.getAndSetupModelForLayer(entity, brightness, partialTick, layer);
+        final ItemStack itemstack = entity.getItemInArmorSlot(HumanArmorShape.values()[(entity.getNumArmorSlots() - 1) - (layer - 1)]);
+        if (itemstack == null) return null;
 
-        this.modelArmorA = modelArmorA;
-        this.modelArmorB = modelArmorB;
+        final Item item = itemstack.getItem();
+        if (item instanceof ItemQuiver) {
+            bindTexture("/assets/minecraft/textures/armor/quiver.png");
+        } else if (item instanceof ItemQuiverEndless) {
+            bindTexture("/assets/minecraft/textures/armor/quiver_golden.png");
+        } else if (item == Items.ARMOR_BOOTS_ICESKATES) {
+            bindTexture("/assets/minecraft/textures/armor/skates.png");
+        } else if (item instanceof IArmorItem) {
+            final IArmorItem armorItem = (IArmorItem) item;
+            if (armorItem.getArmorMaterial() == null) return null;
+            bindTexture(String.format("/assets/%s/textures/armor/%s_%d.png", armorItem.getArmorMaterial().identifier.namespace, armorItem.getArmorMaterial().identifier.value, (layer != 3 ? 1 : 2)));
+        } else {
+            return null;
+        }
+        final StaticEntityModel model;
+        switch (layer) {
+            case 4:
+                model = getModel("armor.boots");
+                break;
+            case 3:
+                model = getModel("armor.leggings");
+                break;
+            case 2:
+                model = getModel("armor.chestplate");
+                break;
+            case 1:
+                model = getModel("armor.helmet");
+                break;
+            default:
+                return null;
+        }
+        return setupAnimations(entity, model, partialTick, layer);
     }
 
     @Override
-    protected void renderAdditional(T entity, float partialTick) {
+    protected @Nullable StaticEntityModel setupAnimations(@NotNull final T entity, @Nullable final StaticEntityModel model, final float partialTick, final int layer) {
+        final StaticEntityModel model1 = super.setupAnimations(entity, model, partialTick, layer);
+        switch (layer) {
+            case 4:
+                assert model != null;
+                model.getTransform("chest").visible = false;
+            case 3:
+                assert model != null;
+                model.getTransform("head").visible = false;
+                model.getTransform("rightArm").visible = false;
+                model.getTransform("leftArm").visible = false;
+                break;
+            case 2:
+                assert model != null;
+                model.getTransform("head").visible = false;
+                model.getTransform("rightLeg").visible = false;
+                model.getTransform("leftLeg").visible = false;
+                break;
+            case 1:
+                assert model != null;
+                model.getTransform("chest").visible = false;
+                model.getTransform("rightArm").visible = false;
+                model.getTransform("leftArm").visible = false;
+                model.getTransform("rightLeg").visible = false;
+                model.getTransform("leftLeg").visible = false;
+                break;
+        }
+        return model1;
+    }
+
+    protected void renderAdditional(@NotNull final Tessellator tessellator, final @NotNull T entity, final float partialTick) {
         final @Nullable ItemStack stack = entity.getItemInArmorSlot(HumanArmorShape.HEAD);
+
+        final StaticEntityModel model = getActiveModel(entity);
+
         if(stack != null) {
             GL11.glPushMatrix();
-            modelBipedMain.head.translateTo(0.0625F);
+            if (model != null) model.translateToBone("head");
             if (!(stack.getItem() instanceof IArmorItem)) {
                 GL11.glPushMatrix();
                 GL11.glEnable(GL11.GL_CULL_FACE);
@@ -49,87 +114,11 @@ public class MobRendererBipedArmored<T extends Mob & IArmorWearing<HumanArmorSha
             GL11.glPopMatrix();
         }
 
-        super.renderAdditional(entity, partialTick);
+        super.renderAdditional(tessellator, entity, partialTick);
     }
 
     @Override
-    public void render(Tessellator tessellator, T entity, double x, double y, double z, float yaw, float partialTick) {
-        GL11.glEnable(GL11.GL_BLEND);
-        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-
-        if (entity instanceof IItemHolding) {
-            ItemStack itemstack = ((IItemHolding) entity).getHeldItem();
-            if (((IItemHolding) entity).isLeftHanded()) {
-                this.modelArmorA.holdingLeftHand = this.modelArmorB.holdingLeftHand = this.modelBipedMain.holdingLeftHand |= itemstack != null;
-            } else {
-                this.modelArmorA.holdingRightHand = this.modelArmorB.holdingRightHand = this.modelBipedMain.holdingRightHand |= itemstack != null;
-            }
-        }
-        this.modelArmorA.sneaking = this.modelArmorB.sneaking = this.modelBipedMain.sneaking = entity.isSneaking();
-        this.modelArmorA.isRiding = this.modelArmorB.isRiding = this.modelBipedMain.isRiding = entity.isPassenger();
-
-        double realY = y - (double)entity.heightOffset;
-        if(entity.isSneaking() && !(entity instanceof PlayerLocal)) {
-            realY -= 0.125D;
-        }
-
-        super.render(tessellator, entity, x, realY, z, yaw, partialTick);
-
-        this.modelArmorA.holdingLarge = this.modelArmorB.holdingLarge = this.modelBipedMain.holdingLarge = false;
-        this.modelArmorA.sneaking = this.modelArmorB.sneaking = this.modelBipedMain.sneaking = false;
-        this.modelArmorA.holdingRightHand = this.modelArmorB.holdingRightHand = this.modelBipedMain.holdingRightHand = false;
-        this.modelArmorA.holdingLeftHand = this.modelArmorB.holdingLeftHand = this.modelBipedMain.holdingLeftHand = false;
-
-        GL11.glDisable(GL11.GL_BLEND);
-    }
-
-    @Override
-    protected boolean prepareArmor(T entity, int layer, float partialTick) {
-        ItemStack itemstack = entity.getItemInArmorSlot(HumanArmorShape.values()[(entity.getNumArmorSlots() - 1) - layer]);
-        if(itemstack != null)
-        {
-            Item item = itemstack.getItem();
-            if(item instanceof ItemQuiver)
-            {
-                bindTexture("/assets/minecraft/textures/armor/quiver.png");
-                ModelBiped modelBiped = modelArmorA;
-                modelBiped.body.visible = layer == 1 || layer == 2;
-                setArmorModel(modelBiped);
-                return true;
-            }
-            if(item instanceof ItemQuiverEndless)
-            {
-                bindTexture("/assets/minecraft/textures/armor/quiver_golden.png");
-                ModelBiped modelBiped = modelArmorA;
-                modelBiped.body.visible = layer == 1 || layer == 2;
-                setArmorModel(modelBiped);
-                return true;
-            }
-            if(item == Items.ARMOR_BOOTS_ICESKATES)
-            {
-                bindTexture("/assets/minecraft/textures/armor/skates.png");
-                ModelBiped modelBiped = modelArmorA;
-                modelBiped.legRight.visible = layer == 2 || layer == 3;
-                modelBiped.legLeft.visible = layer == 2 || layer == 3;
-                setArmorModel(modelBiped);
-                return true;
-            }
-            if(item instanceof IArmorItem && ((IArmorItem) item).getArmorMaterial() != null)
-            {
-                IArmorItem armorItem = (IArmorItem)item;
-                bindTexture(String.format("/assets/%s/textures/armor/%s_%d.png", armorItem.getArmorMaterial().identifier.namespace, armorItem.getArmorMaterial().identifier.value, (layer != 2 ? 1 : 2)));
-                ModelBiped modelBiped = layer != 2 ? modelArmorA : modelArmorB;
-                modelBiped.head.visible = layer == 0;
-                modelBiped.hair.visible = layer == 0;
-                modelBiped.body.visible = layer == 1 || layer == 2;
-                modelBiped.armRight.visible = layer == 1;
-                modelBiped.armLeft.visible = layer == 1;
-                modelBiped.legRight.visible = layer == 2 || layer == 3;
-                modelBiped.legLeft.visible = layer == 2 || layer == 3;
-                setArmorModel(modelBiped);
-                return true;
-            }
-        }
-        return false;
+    protected int maxRenderLayer(@NotNull final T entity) {
+        return 4;
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererButterfly.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererButterfly.java
index d782a3b58..491d6b2fa 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererButterfly.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererButterfly.java
@@ -5,6 +5,7 @@ import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.animal.MobButterfly;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
 
@@ -13,21 +14,21 @@ import java.util.Random;
 public class MobRendererButterfly extends EntityRenderer<MobButterfly> {
     private static final Random sizeRandom = new Random();
     @Override
-    public void render(Tessellator tessellator, MobButterfly butterfly, double x, double y, double z, float yaw, float partialTick) {
+    public void render(@NotNull final Tessellator tessellator, @NotNull final MobButterfly butterfly, final double x, final double y, final double z, final float yaw, final float partialTick) {
         // 0.45 -> 0.8
         sizeRandom.setSeed((long) butterfly.getSkinVariant() << 16);
-        float scale = 0.45f + (sizeRandom.nextFloat() * 0.35f);
-        float yRot = MathHelper.lerp(butterfly.yRotO, butterfly.yRot, partialTick);
-        drawButterfly(tessellator, butterfly.tickCount, scale, yRot, x, y, z, partialTick, renderDispatcher.textureManager, getTexture(butterfly));
+        final float scale = 0.45f + (sizeRandom.nextFloat() * 0.35f);
+        final float yRot = MathHelper.lerp(butterfly.yRotO, butterfly.yRot, partialTick);
+        drawButterfly(tessellator, butterfly.tickCount, scale, yRot, x, y, z, partialTick, this.renderDispatcher.textureManager, getTexture(butterfly));
     }
 
     @Override
-    public void renderPreview(Tessellator tessellator, MobButterfly butterfly, double x, double y, double z, float yaw, float partialTick) {
-        float yRot = MathHelper.lerp(butterfly.yRotO, butterfly.yRot, partialTick);
-        drawButterfly(tessellator, butterfly.tickCount, 1.25f, -yRot, x, y + 0.5, z, partialTick, renderDispatcher.textureManager, getTexture(butterfly));
+    public void renderPreview(@NotNull final Tessellator tessellator, @NotNull final MobButterfly butterfly, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        final float yRot = MathHelper.lerp(butterfly.yRotO, butterfly.yRot, partialTick);
+        drawButterfly(tessellator, butterfly.tickCount, 1.25f, -yRot, x, y + 0.5, z, partialTick, this.renderDispatcher.textureManager, getTexture(butterfly));
     }
 
-    public static void drawButterfly(Tessellator tessellator, int ticksAlive, float scale, float yRot, double x, double y, double z, float partialTick, TextureManager textureManager, String texture) {
+    public static void drawButterfly(final Tessellator tessellator, final int ticksAlive, final float scale, final float yRot, final double x, final double y, final double z, final float partialTick, final TextureManager textureManager, final String texture) {
         textureManager.bindTexture(textureManager.loadTexture(texture));
         GL11.glPushMatrix();
         GL11.glTranslatef((float) x, (float) y + 0.25f, (float) z);
@@ -40,10 +41,10 @@ public class MobRendererButterfly extends EntityRenderer<MobButterfly> {
 
         GL11.glRotatef(-22.5f, 1, 0, 0);
 
-        float xOff = -0.5F;
-        float zOff = -0.5F;
+        final float xOff = -0.5F;
+        final float zOff = -0.5F;
 
-        float flapAngle = (MathHelper.sin(ticksAlive + partialTick) + 1) * 22.5f + 5;
+        final float flapAngle = (MathHelper.sin(ticksAlive + partialTick) + 1) * 22.5f + 5;
 
         GL11.glPushMatrix();
         GL11.glRotatef(-flapAngle, 0, 0, 1);
@@ -71,7 +72,7 @@ public class MobRendererButterfly extends EntityRenderer<MobButterfly> {
         GL11.glPopMatrix();
     }
 
-    public String getTexture(MobButterfly butterfly) {
+    public static String getTexture(final MobButterfly butterfly) {
         if (!Minecraft.getMinecraft().gameSettings.mobVariants.value) {
             return butterfly.getDefaultEntityTexture();
         } else {
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererChicken.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererChicken.java
index 76e39da41..329e8e135 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererChicken.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererChicken.java
@@ -1,19 +1,44 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelBase;
 import net.minecraft.core.entity.animal.MobChicken;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
 public class MobRendererChicken extends MobRenderer<MobChicken> {
-    public MobRendererChicken(ModelBase modelbase, float f)
-    {
-        super(modelbase, f);
+
+    public MobRendererChicken(final float shadowSize) {
+        super(shadowSize);
     }
+
     @Override
-    protected float limbSway(MobChicken entity, float partialTick) {
-        float flap = entity.oFlap + (entity.flap - entity.oFlap) * partialTick;
-        float flapSpeed = entity.oFlapSpeed + (entity.flapSpeed - entity.oFlapSpeed) * partialTick;
-        return (MathHelper.sin(flap) + 1.0F) * flapSpeed;
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobChicken entity, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model = getModel("main");
+        model.resetBones();
+
+        final float limbSwing = getLimbSwing(entity, partialTick);
+        final float limbYaw = getLimbYaw(entity, partialTick);
+        final float limbPitch = getLimbPitch(entity, partialTick);
+
+        final BoneTransform leg0 = model.getTransform("leg0");
+        final BoneTransform leg1 = model.getTransform("leg1");
+        final BoneTransform wing0 = model.getTransform("wing0");
+        final BoneTransform wing1 = model.getTransform("wing1");
+
+        leg0.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+        leg1.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+        wing0.rotZ = limbPitch;
+        wing1.rotZ = -limbPitch;
+
+        return model;
     }
 
+    @Override
+    protected float getLimbPitch(@NotNull final MobChicken entity, final float partialTick) {
+        final float flap = MathHelper.lerp(entity.oFlap, entity.flap, partialTick);
+        final float flapSpeed = MathHelper.lerp(entity.oFlapSpeed, entity.flapSpeed, partialTick);
+        return (MathHelper.sin(flap) + 1.0F) * flapSpeed;
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererCow.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererCow.java
deleted file mode 100644
index fd2e3baf8..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererCow.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package net.minecraft.client.render.entity;
-
-import net.minecraft.client.render.model.ModelBase;
-import net.minecraft.core.entity.animal.MobCow;
-
-public class MobRendererCow extends MobRenderer<MobCow>
-{
-    public MobRendererCow(ModelBase modelbase, float f)
-    {
-        super(modelbase, f);
-    }
-
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererCreeper.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererCreeper.java
index 184944a4d..b0c75003f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererCreeper.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererCreeper.java
@@ -1,89 +1,92 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelBase;
-import net.minecraft.client.render.model.ModelCreeper;
 import net.minecraft.core.entity.monster.MobCreeper;
+import net.minecraft.core.util.helper.Color;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererCreeper extends MobRenderer<MobCreeper>
-{
-    public MobRendererCreeper()
-    {
-        super(new ModelCreeper(), 0.5F);
-        chargedModel = new ModelCreeper(2.0F);
+public class MobRendererCreeper extends MobRenderer<MobCreeper> {
+
+    public MobRendererCreeper(final float shadowSize) {
+        super(shadowSize);
+    }
+
+    @Override
+    protected int getOverlayColor(final @NotNull MobCreeper creeper, final float brightness, final float partialTick) {
+        final float step = creeper.getSwelling(partialTick);
+        if ((int)(step * 10.0f) % 2 == 0) { return 0; }
+        return Color.intToIntARGB(MathHelper.clamp((int)(step * 0.2f * 255.0f), 0, 255), 255, 255,255);
     }
 
     @Override
-    protected void setupScale(MobCreeper creeper, float partialTick) {
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobCreeper creeper, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model;
+        if (layer == 1) { // Setup funky powered rendering
+            model = getModel("charged");
+            bindTexture("/assets/minecraft/textures/armor/power.png");
+            final float ticks = creeper.tickCount + partialTick;
+            GL11.glMatrixMode(GL11.GL_TEXTURE);
+            GL11.glLoadIdentity();
+            final float _x = ticks * 0.01F;
+            final float _y = ticks * 0.01F;
+            GL11.glTranslatef(_x, _y, 0.0F);
+            GL11.glMatrixMode(GL11.GL_MODELVIEW);
+            GL11.glEnable(GL11.GL_BLEND);
+            GL11.glColor4f(0.5f, 0.5f, 0.5f, 1.0F);
+            GL11.glDisable(GL11.GL_LIGHTING);
+            GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE);
+        } else if (layer == 2) { // Reset funky powered rendering
+            GL11.glMatrixMode(GL11.GL_TEXTURE);
+            GL11.glLoadIdentity();
+            GL11.glMatrixMode(GL11.GL_MODELVIEW);
+            GL11.glEnable(GL11.GL_LIGHTING);
+            GL11.glDisable(GL11.GL_BLEND);
+            return null;
+        } else {
+            model = getModel("main");
+        }
+        model.resetBones();
+
+        final float bodyYaw = getBodyYaw(creeper, partialTick);
+        final float headYaw = getHeadYaw(creeper, partialTick) - bodyYaw;
+        final float headPitch = getHeadPitch(creeper, partialTick);
+        final float limbSwing = getLimbSwing(creeper, partialTick);
+        final float limbYaw = getLimbYaw(creeper, partialTick);
+
+        final BoneTransform body = model.getTransform("body");
+        final BoneTransform head = model.getTransform("head");
+        head.rotY = headYaw;
+        head.rotX = headPitch;
+
+        final BoneTransform leg0 = model.getTransform("leg0");
+        final BoneTransform leg1 = model.getTransform("leg1");
+        final BoneTransform leg2 = model.getTransform("leg2");
+        final BoneTransform leg3 = model.getTransform("leg3");
+
+        leg0.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+        leg1.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+        leg2.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+        leg3.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+
         float g = creeper.getSwelling(partialTick);
         final float wobble = 1.0f + MathHelper.sin(g * 100.0f) * g * 0.01f;
-        if (g < 0.0f) {
-            g = 0.0f;
-        }
-        if (g > 1.0f) {
-            g = 1.0f;
-        }
+        g = MathHelper.clamp(g, 0, 1);
         g *= g;
         g *= g;
         final float s = (1.0f + g * 0.4f) * wobble;
         final float hs = (1.0f + g * 0.1f) / wobble;
-        GL11.glScalef(s, hs, s);
+        body.scaleX = s;
+        body.scaleY = hs;
+        body.scaleZ = s;
+        return model;
     }
 
     @Override
-    protected int getOverlayColor(MobCreeper creeper, float brightness, float partialTick) {
-        final float step = creeper.getSwelling(partialTick);
-        if ((int)(step * 10.0f) % 2 == 0) {
-            return 0;
-        }
-        int _a = (int)(step * 0.2f * 255.0f);
-        if (_a < 0) {
-            _a = 0;
-        }
-        if (_a > 255) {
-            _a = 255;
-        }
-        final int r = 255;
-        final int g = 255;
-        final int b = 255;
-        return _a << 24 | r << 16 | g << 8 | b;
+    protected int maxRenderLayer(@NotNull final MobCreeper entity) {
+        return entity.getPowered() ? 2 : 0;
     }
-
-    @Override
-    protected boolean prepareArmor(MobCreeper entity, int layer, float partialTick) {
-        if(entity.getPowered())
-        {
-            if(layer == 1)
-            {
-                float f1 = (float)entity.tickCount + partialTick;
-                bindTexture("/armor/power.png");
-                GL11.glMatrixMode(GL11.GL_TEXTURE);
-                GL11.glLoadIdentity();
-                float f2 = f1 * 0.01F;
-                float f3 = f1 * 0.01F;
-                GL11.glTranslatef(f2, f3, 0.0F);
-                setArmorModel(chargedModel);
-                GL11.glMatrixMode(GL11.GL_MODELVIEW);
-                GL11.glEnable(GL11.GL_BLEND);
-                float brightness = 0.5F;
-                GL11.glColor4f(brightness, brightness, brightness, 1.0F);
-                GL11.glDisable(GL11.GL_LIGHTING);
-                GL11.glBlendFunc(1, 1);
-                return true;
-            }
-            if(layer == 2)
-            {
-                GL11.glMatrixMode(GL11.GL_TEXTURE);
-                GL11.glLoadIdentity();
-                GL11.glMatrixMode(GL11.GL_MODELVIEW);
-                GL11.glEnable(GL11.GL_LIGHTING);
-                GL11.glDisable(GL11.GL_BLEND);
-            }
-        }
-        return false;
-    }
-
-
-    private ModelBase chargedModel;
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererFireflyCluster.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererFireflyCluster.java
index 45cb7a74f..6ce9f0fab 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererFireflyCluster.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererFireflyCluster.java
@@ -1,11 +1,12 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.Lighting;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.client.world.WorldClient;
 import net.minecraft.core.entity.animal.MobFireflyCluster;
 import net.minecraft.client.entity.particle.ParticleFirefly;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 
 import java.util.ArrayList;
@@ -14,32 +15,30 @@ import java.util.Random;
 
 public class MobRendererFireflyCluster extends EntityRenderer<MobFireflyCluster> {
 	private final List<ParticleFirefly> fireflies = new ArrayList<>();
-	private final Minecraft mc;
-	private final Random rand = new Random(0);
+    private final Random rand = new Random(0);
 	private long lastTick;
 
 	public MobRendererFireflyCluster() {
 		for (int i = 0; i < 20; i++) {
-			ParticleFirefly fx = new ParticleFirefly(null, rand.nextFloat() - 0.5f, rand.nextFloat() - 0.5f, 0, 0, 0, 0, 0);
+			final ParticleFirefly fx = new ParticleFirefly(WorldClient.EMPTY_WORLD, this.rand.nextFloat() - 0.5f, this.rand.nextFloat() - 0.5f, 0, 0, 0, 0, 0);
 			fx.noPhysics = true;
-			fx.setAge(rand.nextInt(20));
-			fireflies.add(fx);
+			fx.setAge(this.rand.nextInt(20));
+            this.fireflies.add(fx);
 		}
-		mc = Minecraft.getMinecraft();
-		lastTick = System.currentTimeMillis();
+        this.lastTick = System.currentTimeMillis();
 	}
 
 	@Override
-	public void render(Tessellator tessellator, MobFireflyCluster parent, double x, double y, double z, float yaw, float partialTick) {
+	public void render(@NotNull final Tessellator tessellator, @NotNull final MobFireflyCluster parent, final double x, final double y, final double z, final float yaw, final float partialTick) {
 		// Fireflies are rendered as particles which are spawned in the entity class
 	}
 
 	@Override
-	public void renderPreview(Tessellator tessellator, MobFireflyCluster entity, double x, double y, double z, float yaw, float partialTick) {
+	public void renderPreview(@NotNull final Tessellator tessellator, @NotNull final MobFireflyCluster entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
 		super.renderPreview(tessellator, entity, x, y, z, yaw, partialTick);
 
-		long currentTick = System.currentTimeMillis();
-		int storedTicks = (int) ((currentTick - lastTick) / 50.0f);
+		final long currentTick = System.currentTimeMillis();
+		final int storedTicks = (int) ((currentTick - this.lastTick) / 50.0f);
 
 		GL11.glPushMatrix();
 		GL11.glTranslatef(0, 0.75f, 0);
@@ -47,17 +46,17 @@ public class MobRendererFireflyCluster extends EntityRenderer<MobFireflyCluster>
 		GL11.glEnable(GL11.GL_BLEND);
 		Lighting.disable();
 		TextureRegistry.particleAtlas.bind();
-		Tessellator t = Tessellator.instance;
+		final Tessellator t = Tessellator.instance;
 		t.startDrawingQuads();
-		for (int i = 0; i < fireflies.size(); i++) {
-			ParticleFirefly firefly = fireflies.get(i);
+		for (int i = 0; i < this.fireflies.size(); i++) {
+			final ParticleFirefly firefly = this.fireflies.get(i);
 			firefly.renderParticleInGui(t, partialTick);
 			for (int j = 0; j < storedTicks; j++) {
 				firefly.tickGui();
-				lastTick = currentTick;
+                this.lastTick = currentTick;
 			}
 			if (firefly.removed) {
-				fireflies.remove(i);
+                this.fireflies.remove(i);
 				i--;
 			}
 		}
@@ -65,13 +64,13 @@ public class MobRendererFireflyCluster extends EntityRenderer<MobFireflyCluster>
 		GL11.glEnable(GL11.GL_CULL_FACE);
 		GL11.glPopMatrix();
 
-		if (fireflies.size() < 20) {
-			for (int i = fireflies.size(); i < 20; i++) {
-				if (rand.nextInt(4) == 0) continue;
-				ParticleFirefly fx = new ParticleFirefly(null, rand.nextFloat() - 0.5f, rand.nextFloat() - 0.5f, 0, 0, 0, 0, entity.getColor().getId());
+		if (this.fireflies.size() < 20) {
+			for (int i = this.fireflies.size(); i < 20; i++) {
+				if (this.rand.nextInt(4) == 0) continue;
+				final ParticleFirefly fx = new ParticleFirefly(WorldClient.EMPTY_WORLD, this.rand.nextFloat() - 0.5f, this.rand.nextFloat() - 0.5f, 0, 0, 0, 0, entity.getColor().getId());
 				fx.noPhysics = true;
-				fx.setAge(rand.nextInt(20));
-				fireflies.add(fx);
+				fx.setAge(this.rand.nextInt(20));
+                this.fireflies.add(fx);
 			}
 		}
 	}
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGhast.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGhast.java
index 93335d9d6..441354d2f 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGhast.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGhast.java
@@ -1,36 +1,57 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelGhast;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.monster.MobGhast;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererGhast extends MobRenderer<MobGhast>
-{
+public class MobRendererGhast extends MobRenderer<MobGhast> {
 
-    public MobRendererGhast()
-    {
-        super(new ModelGhast(), 0.5F);
+    public MobRendererGhast(final float shadowSize) {
+        super(shadowSize);
     }
 
     @Override
-    public void renderPreview(Tessellator tessellator, MobGhast mobGhast, double x, double y, double z, float yaw, float partialTick) {
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobGhast entity, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model = getModel("main");
+        model.resetBones();
+
+        final BoneTransform body = model.getTransform("body");
+
+        float charge = MathHelper.lerp(entity.attackChargeO, entity.attackCharge, partialTick) / 20F;
+        if(charge < 0.0F) { charge = 0.0F; }
+        charge = 1.0F / (charge * charge * charge * charge * charge * 2.0F + 1.0F);
+        final float sHeight = (8F + charge) / 2.0F;
+        final float sWidth = (8F + 1.0F / charge) / 2.0F;
+
+        final float limbPitch = getLimbPitch(entity, partialTick);
+
+        body.scaleX = sWidth;
+        body.scaleY = sHeight;
+        body.scaleZ = sWidth;
+
+        model.getTransform("tentacles_0").rotX = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float) 0) + 0.4F;
+        model.getTransform("tentacles_1").rotX = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float) 1) + 0.4F;
+        model.getTransform("tentacles_2").rotX = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float) 2) + 0.4F;
+        model.getTransform("tentacles_3").rotX = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float) 3) + 0.4F;
+        model.getTransform("tentacles_4").rotX = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float) 4) + 0.4F;
+        model.getTransform("tentacles_5").rotX = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float) 5) + 0.4F;
+        model.getTransform("tentacles_6").rotX = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float) 6) + 0.4F;
+        model.getTransform("tentacles_7").rotX = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float) 7) + 0.4F;
+        model.getTransform("tentacles_8").rotX = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float) 8) + 0.4F;
+
+        return model;
+    }
+
+    @Override
+    public void renderPreview(@NotNull final Tessellator tessellator, @NotNull final MobGhast mobGhast, final double x, final double y, final double z, final float yaw, final float partialTick) {
         GL11.glPushMatrix();
         GL11.glScalef(0.25f, 0.25f, 0.25f);
         super.renderPreview(tessellator, mobGhast, x, y, z, yaw, partialTick);
         GL11.glPopMatrix();
     }
-
-    @Override
-    protected void setupScale(MobGhast mobGhast, float partialTick) {
-        float charge = ((float) mobGhast.attackChargeO + (float)(mobGhast.attackCharge - mobGhast.attackChargeO) * partialTick) / 20F;
-        if(charge < 0.0F)
-        {
-            charge = 0.0F;
-        }
-        charge = 1.0F / (charge * charge * charge * charge * charge * 2.0F + 1.0F);
-        float f2 = (8F + charge) / 2.0F;
-        float f3 = (8F + 1.0F / charge) / 2.0F;
-        GL11.glScalef(f3, f2, f3);
-    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGiant.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGiant.java
index f618a656c..3912d9bbc 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGiant.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererGiant.java
@@ -1,23 +1,23 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelBase;
-import net.minecraft.core.entity.monster.MobGiant;
+import net.minecraft.core.entity.monster.MobZombie;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 
-public class MobRendererGiant extends MobRenderer<MobGiant>
+public class MobRendererGiant extends MobRendererZombie
 {
+    private final float scale;
 
-    public MobRendererGiant(ModelBase modelbase, float f, float f1)
+    public MobRendererGiant(final float shadowSizeUnscaled, final float scale)
     {
-        super(modelbase, f * f1);
-        scale = f1;
+        super(shadowSizeUnscaled * scale);
+        this.scale = scale;
     }
 
     @Override
-    protected void setupScale(MobGiant entity, float partialTick)
-    {
-        GL11.glScalef(scale, scale, scale);
+    protected void preRenderTransform(@NotNull final MobZombie entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        super.preRenderTransform(entity, x, y, z, yaw, partialTick);
+        GL11.glScalef(this.scale, this.scale, this.scale);
     }
 
-    private float scale;
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererHuman.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererHuman.java
index 6a34d18e2..f87c43905 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererHuman.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererHuman.java
@@ -1,59 +1,46 @@
 package net.minecraft.client.render.entity;
 
 import net.minecraft.client.render.PlayerSkinParser;
-import net.minecraft.client.render.model.ModelBiped;
-import net.minecraft.client.render.model.ModelPlayer;
-import net.minecraft.client.render.model.ModelPlayerSlim;
-import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.monster.MobHuman;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererHuman extends MobRenderer<MobHuman>
+public class MobRendererHuman extends MobRendererBiped<MobHuman>
 {
-    public MobRendererHuman()
-    {
-        super(new ModelPlayer(0.0F), 0.5F);
-        modelBipedMain = (ModelBiped)mainModel;
-//        modelArmorChestplate = new ModelBiped(1.0F);
-//        modelArmor = new ModelBiped(0.5F);
-        modelThick = new ModelPlayer(0.0f);
-        modelSlim = new ModelPlayerSlim(0.0f);
+    public MobRendererHuman() {
+        super(0.5f);
     }
+
     @Override
-    public void render(Tessellator tessellator, MobHuman entity, double x, double y, double z, float yaw, float partialTick) {
-        GL11.glEnable(GL11.GL_BLEND);
-        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-        mainModel = entity.slimModel ? modelSlim : modelThick;
+    protected void preRenderTransform(@NotNull final MobHuman entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        GL11.glTranslated(x, y, z);
+        GL11.glRotatef(-getBodyYaw(entity, partialTick) * MathHelper.RAD_TO_DEG, 0, 1, 0);
+        GL11.glScalef(1/ENTITY_RENDER_SCALE, 1/ENTITY_RENDER_SCALE, -1/ENTITY_RENDER_SCALE);
 
-//        ItemStack itemstack = entity.getHeldItem();
-//        modelArmorChestplate.field_1278_i = modelArmor.field_1278_i = modelBipedMain.field_1278_i = itemstack != null;
-//        modelArmorChestplate.isSneak = modelArmor.isSneak = modelBipedMain.isSneak = entity.isSneaking();
-//        modelArmorChestplate.isRiding = modelArmor.isRiding = modelBipedMain.isRiding = entity.isPassenger();
-        double yRender = y - (double)entity.heightOffset;
-        if(entity.isSneaking())
-        {
-            yRender -= 0.125D;
+        final float scale = 0.9375F;
+        GL11.glScalef(scale, scale, scale);
+
+        if(entity.deathTime > 0) {
+            float rotationProgress = (((entity.deathTime + partialTick) - 1.0F) / 20F) * 1.6F;
+            rotationProgress = MathHelper.sqrt_float(rotationProgress);
+            if(rotationProgress > 1.0F) {
+                rotationProgress = 1.0F;
+            }
+            GL11.glRotatef(rotationProgress * getMaxDeathRotation(entity), 0.0F, 0.0F, 1.0F);
         }
-        super.render(tessellator, entity, x, yRender, z, yaw, partialTick);
-//        modelArmorChestplate.isSneak = modelArmor.isSneak = modelBipedMain.isSneak = false;
-//        modelArmorChestplate.field_1278_i = modelArmor.field_1278_i = modelBipedMain.field_1278_i = false;
-        GL11.glDisable(GL11.GL_BLEND);
     }
+
     @Override
-    protected void setupScale(MobHuman entity, float partialTick)
+    public void loadEntityTexture(final @NotNull MobHuman entity)
     {
-        float scale = 0.9375F;
-        GL11.glScalef(scale, scale, scale);
+        bindDownloadableTexture(entity.skinUrl, entity.getEntityTexture(), PlayerSkinParser.instance);
     }
 
     @Override
-    public void loadEntityTexture(MobHuman entity)
-    {
-        bindDownloadableTexture(entity.skinUrl, entity.getEntityTexture(), PlayerSkinParser.instance);
+    protected @Nullable StaticEntityModel getActiveModel(@NotNull final MobHuman entity) {
+        return entity.slimModel ? getModel("main.slim") : getModel("main");
     }
-    private final ModelBiped modelBipedMain;
-    private final ModelPlayer modelThick;
-    private final ModelPlayer modelSlim;
-//    private final ModelBiped modelArmorChestplate;
-//    private final ModelBiped modelArmor;
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPig.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPig.java
index d0588eece..5c85103b8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPig.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPig.java
@@ -1,26 +1,53 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelBase;
 import net.minecraft.core.entity.animal.MobPig;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererPig extends MobRenderer<MobPig>
-{
+public class MobRendererPig extends MobRendererQuadruped<MobPig> {
 
-    public MobRendererPig(ModelBase modelbase, ModelBase modelbase1, float f)
-    {
-        super(modelbase, f);
-        setArmorModel(modelbase1);
+    public MobRendererPig(final float shadowSize) {
+        super(shadowSize);
     }
 
-    protected boolean renderSaddledPig(MobPig entity, int i, float f)
-    {
-        bindTexture("/assets/minecraft/textures/entity/saddle.png");
-        return i == 0 && entity != null && entity.getSaddled();
+    @Override
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobPig entity, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model;
+        if (layer == 1) {
+            bindTexture("/assets/minecraft/textures/entity/saddle.png");
+            model = getModel("saddle");
+        } else {
+            model = getModel("main");
+        }
+        model.resetBones();
+
+        final BoneTransform head = model.getTransform("head");
+        final BoneTransform leg0 = model.getTransform("leg0");
+        final BoneTransform leg1 = model.getTransform("leg1");
+        final BoneTransform leg2 = model.getTransform("leg2");
+        final BoneTransform leg3 = model.getTransform("leg3");
+
+        final float bodyYaw = getBodyYaw(entity, partialTick);
+        final float headYaw = getHeadYaw(entity, partialTick) - bodyYaw;
+        final float headPitch = getHeadPitch(entity, partialTick);
+        final float limbSwing = getLimbSwing(entity, partialTick);
+        final float limbYaw = getLimbYaw(entity, partialTick);
+
+        head.rotX = headPitch;
+        head.rotY = headYaw;
+        leg0.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+        leg1.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+        leg2.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+        leg3.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+
+        return model;
     }
 
     @Override
-    protected boolean prepareArmor(MobPig entity, int renderPass, float partialTick)
-    {
-        return renderSaddledPig(entity, renderPass, partialTick);
+    protected int maxRenderLayer(@NotNull final MobPig entity) {
+        return entity.getSaddled() ? 1 : 0;
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java
index 0a7a0c9d7..2a77e8ebb 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererPlayer.java
@@ -1,19 +1,16 @@
 package net.minecraft.client.render.entity;
 
 import net.minecraft.client.Minecraft;
-
-import net.minecraft.client.render.TileEntityRenderDispatcher;
 import net.minecraft.client.render.Lighting;
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.PlayerSkinParser;
+import net.minecraft.client.render.TileEntityRenderDispatcher;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
-import net.minecraft.client.render.font.FontRenderer;
-import net.minecraft.client.render.tileentity.TileEntityRenderer;
 import net.minecraft.client.render.camera.EntityCamera;
-import net.minecraft.client.render.model.ModelPlayer;
-import net.minecraft.client.render.model.ModelPlayerSlim;
+import net.minecraft.client.render.font.FontRenderer;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
+import net.minecraft.client.render.tileentity.TileEntityRenderer;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.entity.TileEntity;
 import net.minecraft.core.block.motion.CarriedBlock;
@@ -21,54 +18,54 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.player.gamemode.Gamemode;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.BlocksContainer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
 public class MobRendererPlayer extends MobRendererBipedArmored<Player>
 {
-    private final ModelPlayer modelThick;
-    private final ModelPlayer modelSlim;
-
     private BlocksContainer container = null;
 
     public MobRendererPlayer()
     {
-        super(new ModelPlayer(0.0F), 0.5F);
-        modelThick = new ModelPlayer(0.0f);
-        modelSlim = new ModelPlayerSlim(0.0f);
+        super(0.5F);
+    }
+
+    protected @NotNull StaticEntityModel getActiveModel(final @NotNull Player player, final boolean onlyArms) {
+        if (onlyArms) {
+            return player.slimModel ? getModel("arms.slim") : getModel("arms");
+        } else {
+            return player.slimModel ? getModel("main.slim") : getModel("main");
+        }
     }
 
-    public void drawFirstPersonHand(Player player, boolean isLeft)
+    public void drawFirstPersonHand(final @NotNull Tessellator tessellator, final @NotNull Player player, final boolean isLeft)
     {
-        mainModel = player.slimModel ? modelSlim : modelThick;
-        modelBipedMain = player.slimModel ? modelSlim : modelThick;
+        // TODO rework the transform nightmare that surround these method calls
+        final StaticEntityModel activeModel = getActiveModel(player, true);
+        activeModel.resetBones();
+
+        activeModel.getTransform("leftSleeve").visible = player.playerConfig.sleeveLeftEnabled();
+        activeModel.getTransform("rightSleeve").visible = player.playerConfig.sleeveRightEnabled();
 
-        modelBipedMain.swingProgress = 0.0F;
-        modelBipedMain.isRiding = false;
-        modelBipedMain.setupAnimation(player, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0625F, 1f);
         if (isLeft){
-            modelBipedMain.armLeft.render(0.0625F);
+            activeModel.getTransform("rightArm").visible = false;
         } else {
-            modelBipedMain.armRight.render(0.0625F);
-        }
-        if (modelBipedMain instanceof ModelPlayer)
-        {
-            if (isLeft){
-                ((ModelPlayer)modelBipedMain).bipedLeftArmOverlay.render(0.0625F);
-            } else {
-                ((ModelPlayer)modelBipedMain).bipedRightArmOverlay.render(0.0625F);
-            }
+            activeModel.getTransform("leftArm").visible = false;
         }
+        activeModel.render(tessellator);
     }
 
-    public void drawHeldObject(Player player, float partialTick) {
+    public void drawHeldObject(final Player player, final float partialTick) {
         if (player.getHeldObject() instanceof CarriedBlock) {
-            CarriedBlock carriedBlock = (CarriedBlock)player.getHeldObject();
-            if (container == null || container.world != player.world) {
-                container = new BlocksContainer(player.world);
+            final CarriedBlock carriedBlock = (CarriedBlock)player.getHeldObject();
+            if (this.container == null || this.container.world != player.world) {
+                this.container = new BlocksContainer(player.world);
             }
 
-            Tessellator tessellator = Tessellator.instance;
-            Minecraft mc = Minecraft.getMinecraft();
+            final Tessellator tessellator = Tessellator.instance;
+            final Minecraft mc = Minecraft.getMinecraft();
             TextureRegistry.blockAtlas.bind();
             GL11.glPushMatrix();
             Lighting.disable();
@@ -84,22 +81,22 @@ public class MobRendererPlayer extends MobRendererBipedArmored<Player>
             GL11.glScalef(0.55f, -0.55f, 0.55f);
             GL11.glTranslatef(0, -0.75f, -0.75f);
 
-            int blockX = MathHelper.floor(player.x);
-            int blockY = MathHelper.floor(player.y) + 1;
-            int blockZ = MathHelper.floor(player.z);
+            final int blockX = MathHelper.floor(player.x);
+            final int blockY = MathHelper.floor(player.y) + 1;
+            final int blockZ = MathHelper.floor(player.z);
 
             tessellator.startDrawingQuads();
             tessellator.setTranslation(-blockX -0.5, -blockY -0.5, -blockZ -0.5);
 
-            container.setLightReferenceEntity(player);
-            container.setBlock(blockX, blockY, blockZ, carriedBlock.blockId, carriedBlock.metadata, carriedBlock.entity);
-            BlockModelDispatcher.getInstance().getDispatch(carriedBlock.block()).renderNoCulling(Tessellator.instance, container, blockX, blockY, blockZ);
+            this.container.setLightReferenceEntity(player);
+            this.container.setBlock(blockX, blockY, blockZ, carriedBlock.blockId, carriedBlock.metadata, carriedBlock.entity);
+            BlockModelDispatcher.getInstance().getDispatch(carriedBlock.block()).renderNoCulling(Tessellator.instance, this.container, blockX, blockY, blockZ);
             tessellator.draw();
             tessellator.setTranslation(0, 0, 0);
-            container.setLightReferenceEntity(null);
-            container.clear();
+            this.container.setLightReferenceEntity(null);
+            this.container.clear();
 
-            TileEntityRenderer<TileEntity> renderer = TileEntityRenderDispatcher.instance.getRenderer(carriedBlock.entity);
+            final TileEntityRenderer<TileEntity> renderer = TileEntityRenderDispatcher.instance.getRenderer(carriedBlock.entity);
             if (renderer != null) {
                 carriedBlock.entity.worldObj = player.world;
                 renderer.doRender(tessellator, carriedBlock.entity, -0.5, -0.5, -0.5, partialTick);
@@ -111,24 +108,24 @@ public class MobRendererPlayer extends MobRendererBipedArmored<Player>
         }
     }
     @Override
-    protected void renderSpecials(Tessellator t, Player entity, double x, double y, double z)
+    protected void renderSpecials(final @NotNull Tessellator t, final @NotNull Player entity, final double x, final double y, final double z)
     {
         if (Minecraft.getMinecraft().thePlayer.getGamemode() != Gamemode.spectator && entity.getGamemode() == Gamemode.spectator) {
             return;
         }
-        if(Minecraft.getMinecraft().gameSettings.immersiveMode.drawNames() && renderDispatcher.camera != null) // Render name
+        if(Minecraft.getMinecraft().gameSettings.immersiveMode.drawNames() && this.renderDispatcher.camera != null) // Render name
         {
-            if (renderDispatcher.camera instanceof EntityCamera && ((EntityCamera)renderDispatcher.camera).mob == entity)
+            if (this.renderDispatcher.camera instanceof EntityCamera && ((EntityCamera) this.renderDispatcher.camera).mob == entity)
             {
                 return;
             }
-            float f = 1.6F;
-            float f1 = 0.01666667F * f;
-            float f2 = (float) renderDispatcher.camera.distanceTo(entity); //getting lost on renderManager.livingPlayer
-            float f3 = entity.isSneaking() ? 32F : 64F;
+            final float f = 1.6F;
+            final float f1 = 0.01666667F * f;
+            final float f2 = (float) this.renderDispatcher.camera.distanceTo(entity); //getting lost on renderManager.livingPlayer
+            final float f3 = entity.isSneaking() ? 32F : 64F;
             if(f2 < f3)
             {
-                String s = entity.getDisplayName();
+                final String s = entity.getDisplayName();
                 if(!entity.isSneaking())
                 {
                     if(entity.isPlayerSleeping())
@@ -144,8 +141,8 @@ public class MobRendererPlayer extends MobRendererBipedArmored<Player>
                     GL11.glPushMatrix();
                     GL11.glTranslatef((float) x + 0.0F, (float) y + 2.3F, (float) z);
                     GL11.glNormal3f(0.0F, 1.0F, 0.0F);
-                    GL11.glRotatef(-renderDispatcher.viewLerpYaw, 0.0F, 1.0F, 0.0F);
-                    GL11.glRotatef(renderDispatcher.viewLerpPitch, 1.0F, 0.0F, 0.0F);
+                    GL11.glRotatef(-this.renderDispatcher.viewLerpYaw, 0.0F, 1.0F, 0.0F);
+                    GL11.glRotatef(this.renderDispatcher.viewLerpPitch, 1.0F, 0.0F, 0.0F);
                     GL11.glScalef(-f1, -f1, f1);
                     GL11.glDisable(GL11.GL_LIGHTING);
                     GL11.glTranslatef(0.0F, 0.25F / f1, 0.0F);
@@ -174,32 +171,51 @@ public class MobRendererPlayer extends MobRendererBipedArmored<Player>
     }
 
     @Override
-    protected void setupScale(Player entity, float partialTick)
-    {
-        if (Minecraft.getMinecraft().thePlayer.getGamemode() == Gamemode.spectator && entity.getGamemode() == Gamemode.spectator){
-            GL11.glColor4f(1f, 1f, 1f, 0.25f);
-        } else if (entity.getGamemode() == Gamemode.spectator) {
-            GL11.glColor4f(1f, 1f, 1f, 0.0f);
+    protected void preRenderTransform(@NotNull final Player entity, final double x, final double y, final double z, final float yaw, final float partialTick) {
+        GL11.glTranslated(x, y - entity.getHeightOffset() + entity.getHeadHeight(), z); // TODO the fact that the offset for players is so fucking dumb really needs to be fixed at some point
+
+
+        if(entity.isAlive() && (entity.isPlayerSleeping())) {
+            GL11.glTranslatef(entity.sleepOffX, entity.sleepOffY, entity.sleepOffZ);
+
+            GL11.glScalef(1/ENTITY_RENDER_SCALE, 1/ENTITY_RENDER_SCALE, -1/ENTITY_RENDER_SCALE);
+            GL11.glTranslatef(0, -4.5f, 0);
+
+            GL11.glRotatef(-entity.getBedOrientationInDegrees(), 0.0F, 1.0F, 0.0F);
+            GL11.glRotatef(getMaxDeathRotation(entity), 0.0F, 0.0F, 1.0F);
+            GL11.glRotatef(270F, 0.0F, 1.0F, 0.0F);
+
+        } else {
+            GL11.glRotatef(-getBodyYaw(entity, partialTick) * MathHelper.RAD_TO_DEG, 0, 1, 0);
+            GL11.glScalef(1/ENTITY_RENDER_SCALE, 1/ENTITY_RENDER_SCALE, -1/ENTITY_RENDER_SCALE);
+        }
+
+        if(entity.deathTime > 0) {
+            float rotationProgress = (((entity.deathTime + partialTick) - 1.0F) / 20F) * 1.6F;
+            rotationProgress = MathHelper.sqrt_float(rotationProgress);
+            if(rotationProgress > 1.0F) {
+                rotationProgress = 1.0F;
+            }
+            GL11.glRotatef(rotationProgress * getMaxDeathRotation(entity), 0.0F, 0.0F, 1.0F);
         }
 
-        float scale = 0.9375F;
+
+        final float scale = 0.9375F;
         GL11.glScalef(scale, scale, scale);
 
         if (entity.isDwarf()) {
             GL11.glScalef(0.6f, 0.5f, 0.6f);
         }
+
+
     }
 
     @Override
-    protected void renderAdditional(Player player, float partialTick)
+    protected void renderAdditional(@NotNull final Tessellator tessellator, final @NotNull Player player, final float partialTick)
     {
-        if (Minecraft.getMinecraft().thePlayer.getGamemode() == Gamemode.spectator && player.getGamemode() == Gamemode.spectator){
-            GL11.glColor4f(1f, 1f, 1f, 0.25f);
-        } else if (player.getGamemode() == Gamemode.spectator) {
-            GL11.glColor4f(1f, 1f, 1f, 0.0f);
-        }
+        final StaticEntityModel activeModel = getActiveModel(player, false);
 
-        super.renderAdditional(player, partialTick);
+        super.renderAdditional(tessellator, player, partialTick);
 
         if (player.playerConfig.capeEnabled()) {
             boolean renderCape = bindDownloadableTexture("https://api.betterthanadventure.net/capes?username=" + player.username, null, null);
@@ -210,83 +226,66 @@ public class MobRendererPlayer extends MobRendererBipedArmored<Player>
 
             if(renderCape) {
                 GL11.glPushMatrix();
-                float brightness = (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) ? 1 : player.getBrightness(partialTick);
+                final float brightness = (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) ? 1 : player.getBrightness(partialTick);
                 GL11.glColor4f(brightness, brightness, brightness, 1f);
                 GL11.glTranslatef(0.0F, 0.0F, 0.125F);
-                float yawOff = player.yBodyRotO + (player.yBodyRot - player.yBodyRotO) * partialTick;
-                float bodyAngle = 5;
-                if(player.isSneaking())
-                {
-                    bodyAngle += 25F;
-                }
-                double _xd = player.xdO + (player.xd - player.xdO) * partialTick;
-                double _yd = Math.min(player.ydO + (player.yd - player.ydO) * partialTick, 0);
-                double _zd = player.zd0 + (player.zd - player.zd0) * partialTick;
-                double vel = -1/(3 * Math.hypot(_xd, _zd) + 1) + 1;
-                double moveAng = Math.atan2(_xd, _zd);
-                double yawRad = Math.toRadians(yawOff);
-                double multiplier = 1 - Math.abs((((Math.cos(yawRad) + 1) - (Math.cos(moveAng) + 1) + 2)/2) -1); // Hell code, basically measures how similar the angle you're facing is to the angle you're moving, with it returning 1 if the same angle and 0 if opposite angles
+                final float yawOff = player.yBodyRotO + (player.yBodyRot - player.yBodyRotO) * partialTick;
+                final float bodyAngle = 5;
+                final double xd = MathHelper.lerp(player.xdO, player.xd, partialTick);
+                final double yd = Math.min(MathHelper.lerp(player.ydO, player.yd, partialTick), 0);
+                final double zd = MathHelper.lerp(player.zd0, player.zd, partialTick);
+                final double vel = -1/(3 * Math.hypot(xd, zd) + 1) + 1;
+                final double moveAng = Math.atan2(xd, zd);
+                final double yawRad = Math.toRadians(yawOff);
+                final double multiplier = 1 - Math.abs((((Math.cos(yawRad) + 1) - (Math.cos(moveAng) + 1) + 2)/2) -1); // Hell code, basically measures how similar the angle you're facing is to the angle you're moving, with it returning 1 if the same angle and 0 if opposite angles
                 player.wobbleTimer += (float) (((player.tickCount + partialTick) - player.lastRenderTick)/(30 - 29 * MathHelper.clamp(vel, 0, 1)));
                 player.lastRenderTick = player.tickCount;
-                double wobble = Math.sin(player.wobbleTimer) * (1.5 + 4.5 * vel * multiplier);
-                GL11.glRotatef((float) MathHelper.clamp((MathHelper.clamp(bodyAngle + vel * 100 * multiplier, bodyAngle, 100f) + wobble) - _yd * 60, 0, 180), 1.0F, 0.0F, 0.0F);
-                GL11.glRotatef(0, 0.0F, 0.0F, 1.0F);
-                GL11.glRotatef(0, 0.0F, 1.0F, 0.0F);
-                GL11.glRotatef(180F, 0.0F, 1.0F, 0.0F);
-                modelBipedMain.renderCloak(0.0625F);
+                final double wobble = Math.sin(player.wobbleTimer) * (1.5 + 4.5 * vel * multiplier);
+                activeModel.translateToBone("cape");
+                final StaticEntityModel cape = getModel("cape");
+                cape.getTransform("cape").rotX = -MathHelper.clamp((MathHelper.clamp(bodyAngle + vel * 100 * multiplier, bodyAngle, 100f) + wobble) - yd * 60, 0, 180) * MathHelper.DEG_TO_RAD;
+                cape.render(tessellator);
                 GL11.glPopMatrix();
             }
         }
 
         if (player.getHeldObject() != null) {
-            float walkSpeed = player.walkAnimSpeedO + (player.walkAnimSpeed - player.walkAnimSpeedO) * partialTick;
-            float walkProgress = player.walkAnimPos - player.walkAnimSpeed * (1.0F - partialTick);
+            final float walkSpeed = player.walkAnimSpeedO + (player.walkAnimSpeed - player.walkAnimSpeedO) * partialTick;
+            final float walkProgress = player.walkAnimPos - player.walkAnimSpeed * (1.0F - partialTick);
             GL11.glTranslatef(0, MathHelper.cos(walkProgress/2 * 2/3f)/26f * walkSpeed + 0.1f, 0);
             drawHeldObject(player, partialTick);
         }
     }
 
     @Override
-    protected void setupRotations(Player entity, float ticksExisted, float bodyYaw, float partialTick)
-    {
-        if(entity.isAlive() && entity.isPlayerSleeping())
-        {
-            GL11.glRotatef(entity.getBedOrientationInDegrees(), 0.0F, 1.0F, 0.0F);
-            GL11.glRotatef(getMaxDeathRotation(entity), 0.0F, 0.0F, 1.0F);
-            GL11.glRotatef(270F, 0.0F, 1.0F, 0.0F);
-        } else
-        {
-            super.setupRotations(entity, ticksExisted, bodyYaw, partialTick);
-        }
+    protected @Nullable StaticEntityModel getActiveModel(@NotNull final Player entity) {
+        return entity.slimModel ? getModel("main.slim") : getModel("main");
     }
 
     @Override
-    protected void translateModel(Player entity, double x, double y, double z)
-    {
-        if(entity.isAlive() && entity.isPlayerSleeping())
-        {
-            super.translateModel(entity, x + (double)entity.sleepOffX, y + (double)entity.sleepOffY, z + (double)entity.sleepOffZ);
-        } else
-        {
-            super.translateModel(entity, x, y, z);
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final Player entity, final float brightness, final float partialTick, final int layer) {
+        if (layer == 0) {
+            return setupAnimations(entity, getActiveModel(entity, false), partialTick, layer);
         }
+        return super.getAndSetupModelForLayer(entity, brightness, partialTick, layer);
     }
 
     @Override
-    public void render(Tessellator tessellator, Player entity, double x, double y, double z,
-                       float yaw, float partialTick)
-    {
-        this.mainModel = entity.slimModel ? this.modelSlim : this.modelThick;
-        this.modelBipedMain = entity.slimModel ? this.modelSlim : this.modelThick;
-        this.modelArmorA.holdingLarge = this.modelArmorB.holdingLarge = this.modelBipedMain.holdingLarge = entity.getHeldObject() != null;
-        this.modelArmorA.holdingRightHand = this.modelArmorB.holdingRightHand = this.modelBipedMain.holdingRightHand |= entity.getHeldObject() != null;
-        this.modelArmorA.holdingLeftHand = this.modelArmorB.holdingLeftHand = this.modelBipedMain.holdingLeftHand |= entity.getHeldObject() != null;
-
-        super.render(tessellator, entity, x, y, z, yaw, partialTick);
+    protected @Nullable StaticEntityModel setupAnimations(@NotNull final Player entity, @Nullable final StaticEntityModel model, final float partialTick, final int layer) {
+        final StaticEntityModel model1 = super.setupAnimations(entity, model, partialTick, layer);
+        if (model1 != null && layer == 0) {
+            model1.getTransform("hat").visible = entity.playerConfig.hatEnabled();
+            model1.getTransform("jacket").visible = entity.playerConfig.jacketEnabled();
+            model1.getTransform("leftSleeve").visible = entity.playerConfig.sleeveLeftEnabled();
+            model1.getTransform("rightSleeve").visible = entity.playerConfig.sleeveRightEnabled();
+            model1.getTransform("leftPant").visible = entity.playerConfig.pantLeftEnabled();
+            model1.getTransform("rightPant").visible = entity.playerConfig.pantRightEnabled();
+        }
+        return model1;
     }
 
     @Override
-    public void loadEntityTexture(Player entity) {
+    public void loadEntityTexture(final @NotNull Player entity) {
         bindDownloadableTexture(entity.skinURL, entity.getEntityTexture(), PlayerSkinParser.instance);
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererQuadruped.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererQuadruped.java
new file mode 100644
index 000000000..e2bc5c981
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererQuadruped.java
@@ -0,0 +1,43 @@
+package net.minecraft.client.render.entity;
+
+import net.minecraft.core.entity.Mob;
+import net.minecraft.core.entity.animal.MobCow;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
+public class MobRendererQuadruped<T extends Mob> extends MobRenderer<T> {
+
+    public MobRendererQuadruped(final float shadowSize) {
+        super(shadowSize);
+    }
+
+    @Override
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final T entity, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model = getModel("main");
+        model.resetBones();
+
+        final BoneTransform head = model.getTransform("head");
+        final BoneTransform leg0 = model.getTransform("leg0");
+        final BoneTransform leg1 = model.getTransform("leg1");
+        final BoneTransform leg2 = model.getTransform("leg2");
+        final BoneTransform leg3 = model.getTransform("leg3");
+
+        final float bodyYaw = getBodyYaw(entity, partialTick);
+        final float headYaw = getHeadYaw(entity, partialTick) - bodyYaw;
+        final float headPitch = getHeadPitch(entity, partialTick);
+        final float limbSwing = getLimbSwing(entity, partialTick);
+        final float limbYaw = getLimbYaw(entity, partialTick);
+
+        head.rotX = headPitch;
+        head.rotY = headYaw;
+        leg0.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+        leg1.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+        leg2.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+        leg3.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+
+        return model;
+    }
+}
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererScorpion.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererScorpion.java
index 77841ed69..2eb2f30d1 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererScorpion.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererScorpion.java
@@ -1,30 +1,51 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelScorpion;
 import net.minecraft.core.entity.monster.MobScorpion;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererScorpion extends MobRenderer<MobScorpion>
-{
+public class MobRendererScorpion extends MobRenderer<MobScorpion> {
 
-    public MobRendererScorpion()
-    {
-        super(new ModelScorpion(), 0.5F);
-        setArmorModel(new ModelScorpion());
-    }
-    protected boolean doRenderPass(MobScorpion scorpion, int i, float f)
-    {
-        return i == 0;
+    public MobRendererScorpion(final float shadowSize) {
+        super(shadowSize);
     }
 
     @Override
-    protected float getMaxDeathRotation(MobScorpion entity)
-    {
-        return 180F;
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobScorpion entity, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model = getModel("main");
+        model.resetBones();
+
+        final float limbSwing = getLimbSwing(entity, partialTick);
+        final float limbYaw = getLimbYaw(entity, partialTick);
+
+        final BoneTransform leg0 = model.getTransform("leg0");
+        final BoneTransform leg1 = model.getTransform("leg1");
+        final BoneTransform leg2 = model.getTransform("leg2");
+        final BoneTransform leg3 = model.getTransform("leg3");
+        final BoneTransform leg4 = model.getTransform("leg4");
+        final BoneTransform leg5 = model.getTransform("leg5");
+
+        final float pair1Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + 0.0F) * 0.4F) * limbYaw;
+        final float pair2Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI) * 0.4F) * limbYaw;
+        final float pair3Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI / 2F) * 0.4F) * limbYaw;
+
+        leg0.rotZ = leg2.rotZ = leg4.rotZ = -22.5 * MathHelper.DEG_TO_RAD;
+        leg0.rotY = 30 * MathHelper.DEG_TO_RAD - pair2Y;
+        leg2.rotY = 0 + pair3Y;
+        leg4.rotY = -30 * MathHelper.DEG_TO_RAD + pair2Y;
+
+        leg1.rotZ = leg3.rotZ = leg5.rotZ = 22.5 * MathHelper.DEG_TO_RAD;
+        leg1.rotY = -30 * MathHelper.DEG_TO_RAD + pair1Y;
+        leg3.rotY = 0 - pair3Y;
+        leg5.rotY = 30 * MathHelper.DEG_TO_RAD - pair1Y;
+        return model;
     }
 
     @Override
-    protected boolean prepareArmor(MobScorpion entity, int renderPass, float partialTick)
-    {
-        return doRenderPass(entity, renderPass, partialTick);
+    protected float getMaxDeathRotation(@NotNull final MobScorpion entity) {
+        return 180;
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSheep.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSheep.java
index d5f9ba5be..a10ef2547 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSheep.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSheep.java
@@ -1,136 +1,104 @@
 package net.minecraft.client.render.entity;
 
-import com.mojang.logging.LogUtils;
-import net.minecraft.client.render.model.ModelBase;
-import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.animal.MobSheep;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.core.Global;
-import org.lwjgl.opengl.GL12;
-import org.slf4j.Logger;
+public class MobRendererSheep extends MobRenderer<MobSheep> {
 
-public class MobRendererSheep extends MobRenderer<MobSheep>
-{
-    private static final Logger LOGGER = LogUtils.getLogger();
-    public MobRendererSheep(ModelBase body, ModelBase wool, ModelBase overlay, float f)
-    {
-        super(body, f);
-        setArmorModel(wool);
-        setOverlayModel(overlay, "/assets/minecraft/textures/entity/sheep_overlay.png");
+    public MobRendererSheep(final float shadowSize) {
+        super(shadowSize);
     }
 
     @Override
-    public void render(Tessellator tessellator, MobSheep entity, double x, double y, double z, float yaw, float partialTick) {
-        GL11.glPushMatrix();
-        GL11.glDisable(GL11.GL_CULL_FACE);
-        mainModel.swingProgress = getSwingProgress(entity, partialTick);
-        if (armorModel != null) armorModel.swingProgress = mainModel.swingProgress;
-        if (overlayModel != null) overlayModel.swingProgress = mainModel.swingProgress;
-        mainModel.isRiding = entity.isPassenger();
-        if (armorModel != null) armorModel.isRiding = mainModel.isRiding;
-        if (overlayModel != null) overlayModel.isRiding = mainModel.isRiding;
-        try
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobSheep entity, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model;
+        switch (layer) {
+            case 1:
+                final int colorIndex = entity.getFleeceColor().blockMeta;
+                GL11.glColor3f(brightness * MobSheep.FLEECE_COLOR_TABLE[colorIndex][0], brightness * MobSheep.FLEECE_COLOR_TABLE[colorIndex][1], brightness * MobSheep.FLEECE_COLOR_TABLE[colorIndex][2]);
+                model = getModel("main");
+                bindTexture("/assets/minecraft/textures/entity/sheep/wool_overlay.png");
+                break;
+            case 2:
+                model = getModel("wool");
+                bindTexture("/assets/minecraft/textures/entity/sheep/wool_overlay.png");
+                break;
+            case 0:
+            default:
+                model = getModel("main");
+                break;
+        }
+        model.resetBones();
+
+        final BoneTransform head = model.getTransform("head");
+
+        final BoneTransform leg0 = model.getTransform("leg0");
+        final BoneTransform leg1 = model.getTransform("leg1");
+        final BoneTransform leg2 = model.getTransform("leg2");
+        final BoneTransform leg3 = model.getTransform("leg3");
+
+        final float bodyYaw = getBodyYaw(entity, partialTick);
+        final float headYaw = getHeadYaw(entity, partialTick) - bodyYaw;
+        final float headPitch = getHeadPitch(entity, partialTick);
+        final float limbSwing = getLimbSwing(entity, partialTick);
+        final float limbYaw = getLimbYaw(entity, partialTick);
+
+        leg0.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+        leg1.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+        leg2.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+        leg3.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+
+        final float headBobTime = MathHelper.lerp(entity.prevTimeSheepEating, entity.timeSheepEating, partialTick);
+        // handles head rotation
+        if(entity.getIsSheepEating())
         {
-            float bodyYaw = entity.yBodyRotO + (entity.yBodyRot - entity.yBodyRotO) * partialTick;
-            float headYaw = entity.yRotO + (entity.yRot - entity.yRotO) * partialTick;
-            float headPitch = entity.xRotO + (entity.xRot - entity.xRotO) * partialTick;
-            translateModel(entity, x, y, z);
-            float limbSway = limbSway(entity, partialTick);
-            setupRotations(entity, limbSway, bodyYaw, partialTick);
-            float scale = 0.0625F;
-            GL12.glEnable(GL12.GL_RESCALE_NORMAL);
-            GL11.glScalef(-1F, -1F, 1.0F);
-            setupScale(entity, partialTick);
-            GL11.glTranslatef(0.0F, -24F * scale - 0.0078125F, 0.0F);
-            float walkSpeed = entity.walkAnimSpeedO + (entity.walkAnimSpeed - entity.walkAnimSpeedO) * partialTick;
-            float walkProgress = entity.walkAnimPos - entity.walkAnimSpeed * (1.0F - partialTick);
-            if(walkSpeed > 1.0F)
+            // begin tilting head down
+            // Move head down
+            if (headBobTime < 5)
             {
-                walkSpeed = 1.0F;
+                final float partPercentage = headBobTime / 5;
+                head.rotX = -((headPitch * (1 - partPercentage)) + (60 * partPercentage)) * MathHelper.DEG_TO_RAD;
+                head.rotY = (headYaw * (1 - partPercentage)) * MathHelper.DEG_TO_RAD;
+
+                head.posY = -2.0f * (headBobTime);
             }
-            loadEntityTexture(entity);
-            GL11.glEnable(GL11.GL_ALPHA_TEST);
-            mainModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-            if (overlayModel != null)
+            // hold head in tilted position
+            // Hold head down and bob
+            else if (headBobTime < 35)
             {
-                bindTexture(overlayTexture);
-                overlayModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
+                head.rotX = -60 * MathHelper.DEG_TO_RAD;
+                head.rotY = 0;
+
+                head.posY = -10 + (MathHelper.sin((headBobTime * 0.05f) * 30.5f) / 3.0f);
             }
-            for(int renderPass = 0; renderPass < MAX_ARMOR_LAYERS; renderPass++)
+            // bring head up to normal rotation again
+            // Bring head back up
+            else if (headBobTime < 40)
             {
-                if(prepareArmor(entity, renderPass, partialTick))
-                {
-                    armorModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                    GL11.glDisable(GL11.GL_BLEND);
-                    GL11.glEnable(GL11.GL_ALPHA_TEST);
-                }
-            }
+                final float partPercentage = (headBobTime - 35) / 5;
+                head.rotX = -((headPitch * partPercentage) + (60 * (1 - partPercentage))) * MathHelper.DEG_TO_RAD;
+                head.rotY = headYaw * partPercentage * MathHelper.DEG_TO_RAD;
 
-            renderAdditional(entity, partialTick);
-            float brightness = entity.getBrightness(partialTick);
-            if (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) brightness = 1.0f;
-            if(entity.hurtTime > 0 || entity.deathTime > 0)
-            {
-                GL11.glDisable(GL11.GL_TEXTURE_2D);
-                GL11.glDisable(GL11.GL_ALPHA_TEST);
-                GL11.glEnable(GL11.GL_BLEND);
-                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-                GL11.glDepthFunc(514);
-                if(entity.hurtTime > 0 || entity.deathTime > 0)
-                {
-                    GL11.glColor4f(brightness, 0.0F, 0.0F, 0.4F);
-                    mainModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                    if (overlayModel != null) overlayModel.render(null, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                    for(int k = 0; k < MAX_ARMOR_LAYERS; k++)
-                    {
-                        if(prepareArmor(entity, k, partialTick))
-                        {
-                            GL11.glColor4f(brightness, 0.0F, 0.0F, 0.4F);
-                            armorModel.render(entity, walkProgress, walkSpeed, limbSway, headYaw - bodyYaw, headPitch, scale, partialTick);
-                        }
-                    }
-                }
-                GL11.glDepthFunc(GL11.GL_LEQUAL);
-                GL11.glDisable(GL11.GL_BLEND);
-                GL11.glEnable(GL11.GL_ALPHA_TEST);
-                GL11.glEnable(GL11.GL_TEXTURE_2D);
+                head.posY = -10 + 2 * (headBobTime - 34);
             }
-            GL11.glDisable(GL12.GL_RESCALE_NORMAL);
         }
-        catch(Exception exception)
+        else
         {
-            LOGGER.error("Render exception in class '{}'!", getClass().getSimpleName(), exception);
+            // normal head rotations
+            head.rotX = headPitch * MathHelper.DEG_TO_RAD;
+            head.rotY = headYaw * MathHelper.DEG_TO_RAD;
         }
-        GL11.glEnable(GL11.GL_CULL_FACE);
-        GL11.glPopMatrix();
-        renderSpecials(tessellator, entity, x, y, z);
-    }
 
-    @Override
-    public void onUnload(){
-        overlayModel.onUnload();
+        return model;
     }
 
     @Override
-    protected boolean prepareArmor(MobSheep mobSheep, int renderPass, float partialTick)
-    {
-        if(renderPass == 0 && !mobSheep.getSheared())
-        {
-            bindTexture("/assets/minecraft/textures/entity/sheep_fur.png");
-            float brightness;
-            if(LightmapHelper.isLightmapEnabled() || Global.accessor.isFullbrightEnabled()) {
-                brightness = 1.0f;
-            }else {
-                brightness = mobSheep.getBrightness(partialTick);
-            }
-            int j = mobSheep.getFleeceColor().blockMeta;
-            GL11.glColor3f(brightness * MobSheep.FLEECE_COLOR_TABLE[j][0], brightness * MobSheep.FLEECE_COLOR_TABLE[j][1], brightness * MobSheep.FLEECE_COLOR_TABLE[j][2]);
-            return true;
-        } else
-        {
-            return false;
-        }
+    protected int maxRenderLayer(@NotNull final MobSheep entity) {
+        return entity.getSheared() ? 1 : 2;
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSkeleton.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSkeleton.java
new file mode 100644
index 000000000..8c6d25613
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSkeleton.java
@@ -0,0 +1,48 @@
+package net.minecraft.client.render.entity;
+
+import net.minecraft.core.entity.monster.MobSkeleton;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
+public class MobRendererSkeleton extends MobRendererBipedArmored<MobSkeleton>{
+
+    public MobRendererSkeleton(final float shadowSize) {
+        super(shadowSize);
+    }
+
+    @Override
+    protected @Nullable StaticEntityModel getActiveModel(@NotNull final MobSkeleton entity) {
+        return getModel("main");
+    }
+
+    @Override
+    protected @Nullable StaticEntityModel setupAnimations(@NotNull final MobSkeleton entity, @Nullable final StaticEntityModel model, final float partialTick, final int layer) {
+        if (model == null) return null;
+        final StaticEntityModel model1 = super.setupAnimations(entity, model, partialTick, layer);
+
+        final BoneTransform rightArm = model.getTransform("rightArm");
+        final BoneTransform leftArm = model.getTransform("leftArm");
+
+        final float limbPitch = getLimbPitch(entity, partialTick);
+        final float swingProgress = entity.getSwingProgress(partialTick);
+
+        final float var7 = MathHelper.sin(swingProgress * MathHelper.PI);
+        final float var8 = MathHelper.sin((1.0F - (1.0F - swingProgress) * (1.0F - swingProgress)) * MathHelper.PI);
+        rightArm.rotZ = 0.0F;
+        leftArm.rotZ = 0.0F;
+        rightArm.rotY = -(0.1F - var7 * 0.6F);
+        leftArm.rotY = 0.1F - var7 * 0.6F;
+        rightArm.rotX = -90 * MathHelper.DEG_TO_RAD;
+        leftArm.rotX = -90 * MathHelper.DEG_TO_RAD;
+        rightArm.rotX -= var7 * 1.2F - var8 * 0.4F;
+        leftArm.rotX -= var7 * 1.2F - var8 * 0.4F;
+        rightArm.rotZ += MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        leftArm.rotZ -= MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        rightArm.rotX += MathHelper.sin(limbPitch * 0.067F) * 0.05F;
+        leftArm.rotX -= MathHelper.sin(limbPitch * 0.067F) * 0.05F;
+        return model1;
+    }
+}
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSlime.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSlime.java
index bf97cf25d..7276fbd6a 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSlime.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSlime.java
@@ -1,56 +1,40 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelBase;
 import net.minecraft.core.entity.monster.MobSlime;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
 public class MobRendererSlime extends MobRenderer<MobSlime>
 {
 
-    public MobRendererSlime(ModelBase modelbase, ModelBase modelbase1, float f)
-    {
-        super(modelbase, f);
-        scaleAmount = modelbase1;
+    public MobRendererSlime(final float shadowSize) {
+        super(shadowSize);
     }
 
-    protected boolean renderSlimePassModel(MobSlime entity, int i, float f)
-    {
-        if(i == 0)
-        {
-            setArmorModel(scaleAmount);
-            GL11.glEnable(2977 /*GL_NORMALIZE*/);
-            GL11.glEnable(GL11.GL_BLEND);
-            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-            return true;
-        }
-        if(i == 1)
-        {
-            GL11.glDisable(GL11.GL_BLEND);
-            GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        }
-        return false;
-    }
+    @Override
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobSlime entity, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model = getModel("main");
+        GL11.glEnable(GL12.GL_NORMALIZE);
+        GL11.glEnable(GL11.GL_BLEND);
+        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
 
-    protected void scaleSlime(MobSlime entityslime, float f)
-    {
-        int i = entityslime.getSlimeSize();
-        float f1 = (entityslime.oSquish + (entityslime.squish - entityslime.oSquish) * f) / ((float)i * 0.5F + 1.0F);
-        float f2 = 1.0F / (f1 + 1.0F);
-        float f3 = i;
-        GL11.glScalef(f2 * f3, (1.0F / f2) * f3, f2 * f3);
-    }
+        model.resetBones();
 
-    @Override
-    protected void setupScale(MobSlime entity, float partialTick)
-    {
-        scaleSlime(entity, partialTick);
-    }
+        final int slimeSize = entity.getSlimeSize();
+        final float squishStrength = (MathHelper.lerp(entity.oSquish, entity.squish, partialTick)) / (slimeSize * 0.5F + 1.0F);
+        final float scale = 1.0F / (squishStrength + 1.0F);
 
-    @Override
-    protected boolean prepareArmor(MobSlime entity, int renderPass, float partialTick)
-    {
-        return renderSlimePassModel(entity, renderPass, partialTick);
-    }
+        final BoneTransform cube = model.getTransform("cube");
 
-    private final ModelBase scaleAmount;
+        cube.scaleX = scale * slimeSize;
+        cube.scaleY = (1.0F / scale) * slimeSize;
+        cube.scaleZ = scale * slimeSize;
+
+        return model;
+    }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSnowman.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSnowman.java
new file mode 100644
index 000000000..f6b55c18a
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSnowman.java
@@ -0,0 +1,48 @@
+package net.minecraft.client.render.entity;
+
+import net.minecraft.core.entity.monster.MobSnowman;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
+public class MobRendererSnowman extends MobRendererBiped<MobSnowman>{
+
+    public MobRendererSnowman(final float shadowSize) {
+        super(shadowSize);
+    }
+
+    @Override
+    protected @Nullable StaticEntityModel getActiveModel(@NotNull final MobSnowman entity) {
+        return getModel("main");
+    }
+
+    @Override
+    protected @Nullable StaticEntityModel setupAnimations(@NotNull final MobSnowman entity, @Nullable final StaticEntityModel model, final float partialTick, final int layer) {
+        if (model == null) return null;
+        final StaticEntityModel model1 = super.setupAnimations(entity, model, partialTick, layer);
+
+        final BoneTransform rightArm = model.getTransform("rightArm");
+        final BoneTransform leftArm = model.getTransform("leftArm");
+
+        final float limbPitch = getLimbPitch(entity, partialTick);
+        final float swingProgress = entity.getSwingProgress(partialTick);
+
+        final float var7 = MathHelper.sin(swingProgress * MathHelper.PI);
+        final float var8 = MathHelper.sin((1.0F - (1.0F - swingProgress) * (1.0F - swingProgress)) * MathHelper.PI);
+        rightArm.rotZ = 0.0F;
+        leftArm.rotZ = 0.0F;
+        rightArm.rotY = -(0.1F - var7 * 0.6F);
+        leftArm.rotY = 0.1F - var7 * 0.6F;
+        rightArm.rotX = -90 * MathHelper.DEG_TO_RAD;
+        leftArm.rotX = -90 * MathHelper.DEG_TO_RAD;
+        rightArm.rotX -= var7 * 1.2F - var8 * 0.4F;
+        leftArm.rotX -= var7 * 1.2F - var8 * 0.4F;
+        rightArm.rotZ += MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        leftArm.rotZ -= MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        rightArm.rotX += MathHelper.sin(limbPitch * 0.067F) * 0.05F;
+        leftArm.rotX -= MathHelper.sin(limbPitch * 0.067F) * 0.05F;
+        return model1;
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSpider.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSpider.java
index 45b6bff3a..64a370322 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSpider.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSpider.java
@@ -1,46 +1,106 @@
 package net.minecraft.client.render.entity;
 
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.model.ModelSpider;
 import net.minecraft.core.entity.monster.MobSpider;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererSpider extends MobRenderer<MobSpider>
-{
+public class MobRendererSpider extends MobRenderer<MobSpider> {
 
-    public MobRendererSpider()
-    {
-        super(new ModelSpider(0), 1.0F);
-        setArmorModel(new ModelSpider(0.01f));
+    public MobRendererSpider(final float shadowSize) {
+        super(shadowSize);
     }
-    protected boolean setSpiderEyeBrightness(MobSpider spider, int renderPass, float partialTick)
-    {
-        if(renderPass == 0)
-        {
-            bindTexture("/assets/minecraft/textures/entity/spider/eyes/" + spider.getTextureReference() + ".png");
-            float brightness = spider.getBrightness(1.0f);
-            if(LightmapHelper.isLightmapEnabled()) {
-                LightmapHelper.setLightmapCoord(LightmapHelper.getLightmapCoord(15, 15));
-            }
-            float f1 = (1.0F - brightness) * 0.5F;
+
+    @Override
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobSpider entity, final float brightness, final float partialTick, final int layer) {
+        if (layer == 1) {
+            bindTexture("/assets/minecraft/textures/entity/spider/eyes/" + entity.getTextureReference() + ".png");
+            if(LightmapHelper.isLightmapEnabled()) LightmapHelper.setLightmapCoord(LightmapHelper.getOverbrightLightmapCoord(15));
             GL11.glEnable(GL11.GL_BLEND);
             GL11.glDisable(GL11.GL_ALPHA_TEST);
             GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-            GL11.glColor4f(1.0F, 1.0F, 1.0F, f1);
-            return true;
+            GL11.glColor4f(1.0F, 1.0F, 1.0F, (1.0F - entity.getBrightness(partialTick)) * 0.5F);
         }
 
-        return false;
+        final StaticEntityModel model = getModel("main");
+        model.resetBones();
+
+        final float bodyYaw = getBodyYaw(entity, partialTick);
+        final float headYaw = getHeadYaw(entity, partialTick) - bodyYaw;
+        final float headPitch = getHeadPitch(entity, partialTick);
+        final float limbSwing = getLimbSwing(entity, partialTick);
+        final float limbYaw = getLimbYaw(entity, partialTick);
+
+
+        final BoneTransform head = model.getTransform("head");
+        final BoneTransform leg0 = model.getTransform("leg0");
+        final BoneTransform leg1 = model.getTransform("leg1");
+        final BoneTransform leg2 = model.getTransform("leg2");
+        final BoneTransform leg3 = model.getTransform("leg3");
+        final BoneTransform leg4 = model.getTransform("leg4");
+        final BoneTransform leg5 = model.getTransform("leg5");
+        final BoneTransform leg6 = model.getTransform("leg6");
+        final BoneTransform leg7 = model.getTransform("leg7");
+
+        head.rotX = headPitch;
+        head.rotY = headYaw;
+
+        final double rZ = 45 * MathHelper.DEG_TO_RAD;
+        leg0.rotZ = -rZ;
+        leg1.rotZ =  rZ;
+        leg2.rotZ = -rZ * 0.74F;
+        leg3.rotZ =  rZ * 0.74F;
+        leg4.rotZ = -rZ * 0.74F;
+        leg5.rotZ =  rZ * 0.74F;
+        leg6.rotZ = -rZ;
+        leg7.rotZ =  rZ;
+        final double ry = 22.5 * MathHelper.DEG_TO_RAD;
+        leg0.rotY =  ry * 2.0F;
+        leg1.rotY = -ry * 2.0F;
+        leg2.rotY =  ry;
+        leg3.rotY = -ry;
+        leg4.rotY = -ry;
+        leg5.rotY =  ry;
+        leg6.rotY = -ry * 2.0;
+        leg7.rotY =  ry * 2.0F;
+        final double pair1Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + 0.0F) * 0.4F) * limbYaw;
+        final double pair2Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI) * 0.4F) * limbYaw;
+        final double pair3Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI / 2F) * 0.4F) * limbYaw;
+        final double pair4Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI * 1.5F) * 0.4F) * limbYaw;
+        final double pair1Z = Math.abs(MathHelper.sin(limbSwing * 0.6662F + 0.0F) * 0.4F) * limbYaw;
+        final double pair2Z = Math.abs(MathHelper.sin(limbSwing * 0.6662F + MathHelper.PI) * 0.4F) * limbYaw;
+        final double pair3Z = Math.abs(MathHelper.sin(limbSwing * 0.6662F + MathHelper.PI / 2F) * 0.4F) * limbYaw;
+        final double pair4Z = Math.abs(MathHelper.sin(limbSwing * 0.6662F + MathHelper.PI * 1.5F) * 0.4F) * limbYaw;
+        leg0.rotY += pair1Y;
+        leg1.rotY -= pair1Y;
+        leg2.rotY += pair2Y;
+        leg3.rotY -= pair2Y;
+        leg4.rotY += pair3Y;
+        leg5.rotY -= pair3Y;
+        leg6.rotY += pair4Y;
+        leg7.rotY -= pair4Y;
+        leg0.rotZ += pair1Z;
+        leg1.rotZ -= pair1Z;
+        leg2.rotZ += pair2Z;
+        leg3.rotZ -= pair2Z;
+        leg4.rotZ += pair3Z;
+        leg5.rotZ -= pair3Z;
+        leg6.rotZ += pair4Z;
+        leg7.rotZ -= pair4Z;
+        return model;
     }
 
     @Override
-    protected float getMaxDeathRotation(MobSpider entity)
-    {
-        return 180f;
+    protected float getMaxDeathRotation(@NotNull final MobSpider entity) {
+        return 180;
     }
 
     @Override
-    protected boolean prepareArmor(MobSpider entity, int renderPass, float partialTick) {
-        return setSpiderEyeBrightness(entity, renderPass, partialTick);
+    protected int maxRenderLayer(@NotNull final MobSpider entity) {
+        return 1;
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSquid.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSquid.java
index 10b6e5dfe..ddd6858d4 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSquid.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererSquid.java
@@ -1,40 +1,61 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelBase;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.animal.MobSquid;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererSquid extends MobRenderer<MobSquid>
-{
-    public MobRendererSquid(ModelBase modelbase, float f)
-    {
-        super(modelbase, f);
+public class MobRendererSquid extends MobRenderer<MobSquid> {
+
+    public MobRendererSquid(final float shadowSize) {
+        super(shadowSize);
     }
+
     @Override
-    protected float limbSway(MobSquid squid, float partialTick)
-    {
-        return squid.oldTentacleAngle + (squid.tentacleAngle - squid.oldTentacleAngle) * partialTick;
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobSquid entity, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model = getModel("main");
+        model.resetBones();
+
+        final float limbPitch = getLimbPitch(entity, partialTick);
+        model.getTransform("tentacle1").rotX = limbPitch;
+        model.getTransform("tentacle2").rotX = limbPitch;
+        model.getTransform("tentacle3").rotX = limbPitch;
+        model.getTransform("tentacle4").rotX = limbPitch;
+        model.getTransform("tentacle5").rotX = limbPitch;
+        model.getTransform("tentacle6").rotX = limbPitch;
+        model.getTransform("tentacle7").rotX = limbPitch;
+        model.getTransform("tentacle8").rotX = limbPitch;
+
+        return model;
     }
 
     @Override
-    protected void setupRotations(MobSquid squid, float ticksExisted, float bodyYaw, float partialTick)
+    protected float getLimbPitch(final @NotNull MobSquid squid, final float partialTick)
     {
-        if (squid.isSpecial()) {
-            super.setupRotations(squid, ticksExisted, bodyYaw, partialTick);
+        return MathHelper.lerp(squid.oldTentacleAngle, squid.tentacleAngle, partialTick);
+    }
+
+    @Override
+    protected void preRenderTransform(@NotNull final MobSquid entity, final double x, final double y, final double z, final float _yaw, final float partialTick) {
+        if (entity.isSpecial()) {
+            GL11.glTranslated(0, 1.5, 0);
+            super.preRenderTransform(entity, x, y, z, _yaw, partialTick);
         } else {
-            float pitch = squid.xBodyRotO + (squid.xBodyRot - squid.xBodyRotO) * partialTick;
-            float yaw = squid.zBodyRotO + (squid.zBodyRot - squid.zBodyRotO) * partialTick;
-            GL11.glTranslatef(0.0F, 0.5F, 0.0F);
-            GL11.glRotatef(180F - bodyYaw, 0.0F, 1.0F, 0.0F);
+            GL11.glTranslated(x, y + 0.5, z);
+            GL11.glScalef(1/ MobRenderer.ENTITY_RENDER_SCALE, 1/ MobRenderer.ENTITY_RENDER_SCALE, 1/ MobRenderer.ENTITY_RENDER_SCALE);
+            final float pitch = entity.xBodyRotO + (entity.xBodyRot - entity.xBodyRotO) * partialTick;
+            final float yaw = entity.zBodyRotO + (entity.zBodyRot - entity.zBodyRotO) * partialTick;
+            GL11.glRotatef(180 - getBodyYaw(entity, partialTick) * MathHelper.RAD_TO_DEG, 0.0F, 1.0F, 0.0F);
             GL11.glRotatef(pitch, 1.0F, 0.0F, 0.0F);
             GL11.glRotatef(yaw, 0.0F, 1.0F, 0.0F);
-            GL11.glTranslatef(0.0F, -1.2F, 0.0F);
         }
     }
 
     @Override
-    public void renderPreview(Tessellator tessellator, MobSquid squid, double x, double y, double z, float yaw, float partialTick) {
+    public void renderPreview(@NotNull final Tessellator tessellator, @NotNull final MobSquid squid, final double x, final double y, final double z, final float yaw, final float partialTick) {
         GL11.glPushMatrix();
         GL11.glTranslatef(0.0f, 1.25f, 0.0f);
         super.renderPreview(tessellator,squid, x, y, z, yaw, partialTick);
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererWolf.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererWolf.java
index c270f7617..e6f234536 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererWolf.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererWolf.java
@@ -1,71 +1,140 @@
 package net.minecraft.client.render.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
-import net.minecraft.client.render.model.ModelWolf;
 import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.animal.MobWolf;
-
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.material.ArmorMaterial;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
 import org.useless.dragonfly.DisplayPos;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererWolf extends MobRenderer<MobWolf>
-{
-    private final ModelWolf modelArmor;
-    protected ModelWolf modelWolfMain;
-
-    public MobRendererWolf(ModelWolf modelWolf, float shadowSize)
-    {
-        super(modelWolf, shadowSize);
-        modelWolfMain = modelWolf;
-        modelArmor = new ModelWolf(0.25f);
+public class MobRendererWolf extends MobRenderer<MobWolf> {
+    public MobRendererWolf(final float shadowSize) {
+        super(shadowSize);
     }
 
     @Override
-    protected boolean prepareArmor(MobWolf wolf, int layer, float partialTick) {
-        ArmorMaterial material = wolf.getArmorMaterial();
-        if (material == null) {
-            return false;
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobWolf entity, final float brightness, final float partialTick, final int layer) {
+        final StaticEntityModel model;
+        if (layer == 1) {
+            final ArmorMaterial material = entity.getArmorMaterial();
+            if (material == null) return null;
+            bindTexture(String.format("/assets/%s/textures/armor/wolf/%s.png", material.identifier.namespace, material.identifier.value));
+            model = getModel("armor");
+        } else {
+            model = getModel("main");
+        }
+        model.resetBones();
+
+        final BoneTransform tail = model.getTransform("tail");
+        final BoneTransform bodyUpper = model.getTransform("upperBody");
+        final BoneTransform body = model.getTransform("body");
+        final BoneTransform head = model.getTransform("head");
+        final BoneTransform leg0 = model.getTransform("leg0");
+        final BoneTransform leg1 = model.getTransform("leg1");
+        final BoneTransform leg2 = model.getTransform("leg2");
+        final BoneTransform leg3 = model.getTransform("leg3");
+
+        final float bodyYaw = getBodyYaw(entity, partialTick);
+        final float headYaw = getHeadYaw(entity, partialTick) - bodyYaw;
+        final float headPitch = getHeadPitch(entity, partialTick);
+        final float limbSwing = getLimbSwing(entity, partialTick);
+        final float limbYaw = getLimbYaw(entity, partialTick);
+        final float limbPitch = getLimbPitch(entity, partialTick);
+
+        if(entity.isWolfAngry())
+        {
+            tail.rotY = 0.0F;
+        } else
+        {
+            tail.rotY = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+        }
+        if(entity.isWolfSitting())
+        {
+            body.rotX = -33.5 * MathHelper.DEG_TO_RAD;
+            body.posY = -4.5;
+            body.posZ = -2;
+
+            bodyUpper.rotX = -18 * MathHelper.DEG_TO_RAD;
+            bodyUpper.posY = -3;
+
+            leg0.rotX = -90 * MathHelper.DEG_TO_RAD;
+            leg0.posY = -7;
+            leg0.posZ = -3;
+
+            leg1.rotX = -90 * MathHelper.DEG_TO_RAD;
+            leg1.posY = -7;
+            leg1.posZ = -3;
+
+            leg2.rotX = -22.5 * MathHelper.DEG_TO_RAD;
+            leg2.posY = -1;
+
+            leg3.rotX = -22.5 * MathHelper.DEG_TO_RAD;
+            leg3.posY = -1;
+
+            tail.posY = -9;
+            tail.posZ = -3;
+        } else
+        {
+            leg0.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+            leg1.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+            leg2.rotX = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
+            leg3.rotX = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
+        }
+        head.rotZ = entity.getInterestedAngle(partialTick) + entity.getShakeAngle(partialTick, 0.0F);
+        bodyUpper.rotZ = entity.getShakeAngle(partialTick, -0.08F);
+        body.rotZ = entity.getShakeAngle(partialTick, -0.16F);
+        tail.rotZ = entity.getShakeAngle(partialTick, -0.2F);
+
+        if(entity.getWolfShaking())
+        {
+            final float shading = brightness * entity.getShadingWhileShaking(partialTick);
+            GL11.glColor3f(shading, shading, shading);
         }
-        bindTexture(String.format("/assets/%s/textures/armor/wolf/%s.png", material.identifier.namespace, material.identifier.value));
-        setArmorModel(modelArmor);
-        return true;
+
+        head.rotX = headPitch;
+        head.rotY = headYaw;
+        tail.rotX = limbPitch;
+
+        return model;
     }
+
     @Override
-    protected float limbSway(MobWolf wolf, float partialTick)
+    protected int maxRenderLayer(@NotNull final MobWolf entity) {
+        return entity.getArmorMaterial() != null ? 1 : 0;
+    }
+
+    @Override
+    protected float getLimbPitch(final @NotNull MobWolf wolf, final float partialTick)
     {
         if(wolf.isWolfAngry())
         {
-            return 88 * (MathHelper.PI / 180F);
+            return 88 * MathHelper.DEG_TO_RAD;
         }
         else if(wolf.isWolfTamed())
         {
             return (0.55F - (float)(wolf.getMaxHealth() - wolf.getHealth()) * 0.02F) * MathHelper.PI;
-        }
-        else
+        } else
         {
-            return 36 * (MathHelper.PI / 180F);
+            return 36 * MathHelper.DEG_TO_RAD;
         }
     }
 
     @Override
-    protected void renderAdditional(MobWolf entity, float partialTick){
-        ItemStack itemstack = entity.getHeldItem();
+    protected void renderAdditional(@NotNull final Tessellator tessellator, final @NotNull MobWolf entity, final float partialTick){
+        final ItemStack itemstack = entity.getHeldItem();
 
-        if(itemstack != null && itemstack.getItem() != null) {
+        if(itemstack != null) {
             GL11.glPushMatrix();
-            modelWolfMain.wolfHeadMain.translateTo(0.0625F);
-            GL11.glScalef(1, -1, 1);
-            GL11.glTranslatef(0.5f/16f, -2.5f/16f, -2/16f);
-            GL11.glRotatef(-2.5f, 0, 0, 1);
-            GL11.glRotatef(45, 0, 1, 0);
-            GL11.glRotatef(-90, 1, 0, 0);
+            getModel("main").translateToBone("mouthItem");
+            GL11.glScalef(MobRenderer.ENTITY_RENDER_SCALE, -MobRenderer.ENTITY_RENDER_SCALE, MobRenderer.ENTITY_RENDER_SCALE);
             GL11.glEnable(GL12.GL_RESCALE_NORMAL);
             GL11.glEnable(GL11.GL_BLEND);
             ItemModelDispatcher.getInstance().getDispatch(itemstack).render(Tessellator.instance, entity, itemstack, DisplayPos.GROUND, Minecraft.getMinecraft().gameSettings.items3D.value, 1, entity.getBrightness(partialTick), 1f, partialTick, true);
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererZombie.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererZombie.java
new file mode 100644
index 000000000..a621872ee
--- /dev/null
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererZombie.java
@@ -0,0 +1,48 @@
+package net.minecraft.client.render.entity;
+
+import net.minecraft.core.entity.monster.MobZombie;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
+public class MobRendererZombie extends MobRendererBipedArmored<MobZombie>{
+
+    public MobRendererZombie(final float shadowSize) {
+        super(shadowSize);
+    }
+
+    @Override
+    protected @Nullable StaticEntityModel getActiveModel(@NotNull final MobZombie entity) {
+        return getModel("main");
+    }
+
+    @Override
+    protected @Nullable StaticEntityModel setupAnimations(@NotNull final MobZombie entity, @Nullable final StaticEntityModel model, final float partialTick, final int layer) {
+        if (model == null) return null;
+        final StaticEntityModel model1 = super.setupAnimations(entity, model, partialTick, layer);
+
+        final BoneTransform rightArm = model.getTransform("rightArm");
+        final BoneTransform leftArm = model.getTransform("leftArm");
+
+        final float limbPitch = getLimbPitch(entity, partialTick);
+        final float swingProgress = entity.getSwingProgress(partialTick);
+
+        final float var7 = MathHelper.sin(swingProgress * MathHelper.PI);
+        final float var8 = MathHelper.sin((1.0F - (1.0F - swingProgress) * (1.0F - swingProgress)) * MathHelper.PI);
+        rightArm.rotZ = 0.0F;
+        leftArm.rotZ = 0.0F;
+        rightArm.rotY = -(0.1F - var7 * 0.6F);
+        leftArm.rotY = 0.1F - var7 * 0.6F;
+        rightArm.rotX = -90 * MathHelper.DEG_TO_RAD;
+        leftArm.rotX = -90 * MathHelper.DEG_TO_RAD;
+        rightArm.rotX -= var7 * 1.2F - var8 * 0.4F;
+        leftArm.rotX -= var7 * 1.2F - var8 * 0.4F;
+        rightArm.rotZ += MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        leftArm.rotZ -= MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        rightArm.rotX += MathHelper.sin(limbPitch * 0.067F) * 0.05F;
+        leftArm.rotX -= MathHelper.sin(limbPitch * 0.067F) * 0.05F;
+        return model1;
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererZombieArmored.java b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererZombieArmored.java
index fabd18273..47dc66c79 100644
--- a/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererZombieArmored.java
+++ b/game/client/src/main/java/net/minecraft/client/render/entity/MobRendererZombieArmored.java
@@ -1,74 +1,112 @@
 package net.minecraft.client.render.entity;
 
-import net.minecraft.client.render.model.ModelZombie;
 import net.minecraft.core.entity.monster.MobZombieArmored;
+import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
-public class MobRendererZombieArmored extends MobRendererBiped<MobZombieArmored>
-{
+public class MobRendererZombieArmored extends MobRendererBipedArmored<MobZombieArmored>{
 
-    private final ModelZombie modelArmorChestplate;
-    private final ModelZombie modelArmor;
+    public MobRendererZombieArmored(final float shadowSize) {
+        super(shadowSize);
+    }
 
-    public MobRendererZombieArmored(ModelZombie model, float shadowSize)
-    {
-        super(model, shadowSize);
-        modelBipedMain = model;
-        modelArmorChestplate = new ModelZombie(1.0F);
-        modelArmor = new ModelZombie(0.5F);
+    @Override
+    protected @Nullable StaticEntityModel getActiveModel(@NotNull final MobZombieArmored entity) {
+        return getModel("main");
     }
 
     @Override
-    protected boolean prepareArmor(MobZombieArmored zombie, int renderPass, float partialTick)
-    {
-        bindTexture("/assets/minecraft/textures/armor/chain" + "_" + (renderPass != 2 ? 1 : 2) + ".png");
-        ModelZombie model = renderPass != 2 ? modelArmorChestplate : modelArmor;
-        model.head.visible = renderPass == 0;
-        model.hair.visible = renderPass == 0;
-        model.body.visible = renderPass == 1 || renderPass == 2;
-        model.armRight.visible = renderPass == 1;
-        model.armLeft.visible = renderPass == 1;
-        model.legRight.visible = renderPass == 2 || renderPass == 3;
-        model.legLeft.visible = renderPass == 2 || renderPass == 3;
+    protected @Nullable StaticEntityModel getAndSetupModelForLayer(@NotNull final MobZombieArmored entity, final float brightness, final float partialTick, final int layer) {
+        if (layer == 0) return setupAnimations(entity, getActiveModel(entity), partialTick, layer);
+
+        bindTexture("/assets/minecraft/textures/armor/chain" + "_" + (layer != 3 ? 1 : 2) + ".png");
 
         // Disable armor pieces depending on health
-        int[] armorBreakPoints = zombie.getArmorBreakPoints();
-        int[] armorBreakOrder = zombie.getArmorBreakOrder();
+        final int[] armorBreakPoints = entity.getArmorBreakPoints();
+        final int[] armorBreakOrder = entity.getArmorBreakOrder();
         for (int i = 0; i < 4; i++)
         {
-            if (zombie.getHealth() <= armorBreakPoints[i])
+            if (entity.getHealth() <= armorBreakPoints[i])
             {
                 hideArmorPiece(armorBreakOrder[i]);
             }
         }
 
-        setArmorModel(model);
-        return true;
+        final StaticEntityModel model;
+        switch (layer) {
+            case 4:
+                model = getModel("armor.boots");
+                break;
+            case 3:
+                model = getModel("armor.leggings");
+                break;
+            case 2:
+                model = getModel("armor.chestplate");
+                break;
+            case 1:
+                model = getModel("armor.helmet");
+                break;
+            default:
+                return null;
+        }
+
+        return setupAnimations(entity, model, partialTick, layer);
     }
 
-    private void hideArmorPiece(int piece)
+    private void hideArmorPiece(final int piece)
     {
-        if (piece == 0)
-        {
-            modelArmorChestplate.head.visible = false;
-            modelArmorChestplate.hair.visible = false;
-        }
-        else if (piece == 1)
-        {
-            modelArmorChestplate.body.visible = false;
-            modelArmorChestplate.armLeft.visible = false;
-            modelArmorChestplate.armRight.visible = false;
-        }
-        else if (piece == 2)
-        {
-            modelArmor.body.visible = false;
-            modelArmor.legLeft.visible = false;
-            modelArmor.legRight.visible = false;
-        }
-        else if (piece == 3)
-        {
-            modelArmorChestplate.legLeft.visible = false;
-            modelArmorChestplate.legRight.visible = false;
-        }
+//        if (piece == 0)
+//        {
+//            modelArmorChestplate.head.visible = false;
+//            modelArmorChestplate.hair.visible = false;
+//        }
+//        else if (piece == 1)
+//        {
+//            modelArmorChestplate.body.visible = false;
+//            modelArmorChestplate.armLeft.visible = false;
+//            modelArmorChestplate.armRight.visible = false;
+//        }
+//        else if (piece == 2)
+//        {
+//            modelArmor.body.visible = false;
+//            modelArmor.legLeft.visible = false;
+//            modelArmor.legRight.visible = false;
+//        }
+//        else if (piece == 3)
+//        {
+//            modelArmorChestplate.legLeft.visible = false;
+//            modelArmorChestplate.legRight.visible = false;
+//        }
     }
 
-}
+    @Override
+    protected @Nullable StaticEntityModel setupAnimations(@NotNull final MobZombieArmored entity, @Nullable final StaticEntityModel model, final float partialTick, final int layer) {
+        if (model == null) return null;
+        final StaticEntityModel model1 = super.setupAnimations(entity, model, partialTick, layer);
+
+        final BoneTransform rightArm = model.getTransform("rightArm");
+        final BoneTransform leftArm = model.getTransform("leftArm");
+
+        final float limbPitch = getLimbPitch(entity, partialTick);
+        final float swingProgress = entity.getSwingProgress(partialTick);
+
+        final float var7 = MathHelper.sin(swingProgress * MathHelper.PI);
+        final float var8 = MathHelper.sin((1.0F - (1.0F - swingProgress) * (1.0F - swingProgress)) * MathHelper.PI);
+        rightArm.rotZ = 0.0F;
+        leftArm.rotZ = 0.0F;
+        rightArm.rotY = -(0.1F - var7 * 0.6F);
+        leftArm.rotY = 0.1F - var7 * 0.6F;
+        rightArm.rotX = -90 * MathHelper.DEG_TO_RAD;
+        leftArm.rotX = -90 * MathHelper.DEG_TO_RAD;
+        rightArm.rotX -= var7 * 1.2F - var8 * 0.4F;
+        leftArm.rotX -= var7 * 1.2F - var8 * 0.4F;
+        rightArm.rotZ += MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        leftArm.rotZ -= MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
+        rightArm.rotX += MathHelper.sin(limbPitch * 0.067F) * 0.05F;
+        leftArm.rotX -= MathHelper.sin(limbPitch * 0.067F) * 0.05F;
+        return model1;
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java
index bb6df22ad..665a70ba6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelBow.java
@@ -31,7 +31,11 @@ public class ItemModelBow extends ItemModelStandard {
         }
         if (nextArrow != null){
             GL11.glPushMatrix();
-            GL11.glRotatef(90, 0, 0, 1);
+            if (mirrorX) {
+                GL11.glRotatef(-90, 0, 0, 1);
+            } else {
+                GL11.glRotatef(90, 0, 0, 1);
+            }
             GL11.glTranslatef(0.0001f, 0.0001f, 0);
             GL11.glScalef(1, 1, 0.999f);
             renderCoordinate(tessellator, ItemModelDispatcher.getInstance().getDispatch(nextArrow).getIcon(holder, nextArrow.getDefaultStack()), items3d, mirrorX);
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelMap.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelMap.java
index 93c192540..70519b93a 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelMap.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelMap.java
@@ -3,7 +3,6 @@ package net.minecraft.client.render.item.model;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.EntityRenderDispatcher;
 import net.minecraft.client.render.ItemRenderer;
-import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.MapItemRenderer;
 import net.minecraft.client.render.PlayerSkinParser;
 import net.minecraft.client.render.entity.EntityRenderer;
@@ -62,14 +61,28 @@ public class ItemModelMap extends ItemModelStandard {
             GL11.glRotatef(-45, 1.0F, 0.0F, 0.0F);
             GL11.glRotatef(90F - 59F, 0.0F, 0.0F, 1.0F);
             GL11.glRotatef(65, 0.0F, 1.0F, 0.0F);
-            playerRenderer.drawFirstPersonHand(mc.thePlayer, true);
+            GL11.glPushMatrix();
+            GL11.glScalef(1/16f, 1/16f, -1/16f);
+            GL11.glTranslatef(0, 16, 0);
+            GL11.glRotatef(180, 1, 0, 0);
+            GL11.glTranslatef(0, -16, 0);
+            GL11.glTranslatef(0, 8, 0);
+            playerRenderer.drawFirstPersonHand(Tessellator.instance, mc.thePlayer, true);
+            GL11.glPopMatrix();
             GL11.glPopMatrix();
             GL11.glPushMatrix();
             GL11.glTranslatef(-0F, -0.6F, 1.1F);
             GL11.glRotatef(-45, 1.0F, 0.0F, 0.0F);
             GL11.glRotatef(-90F + 59F, 0.0F, 0.0F, 1.0F);
             GL11.glRotatef(-65, 0.0F, 1.0F, 0.0F);
-            playerRenderer.drawFirstPersonHand(mc.thePlayer, false);
+            GL11.glPushMatrix();
+            GL11.glScalef(1/16f, 1/16f, -1/16f);
+            GL11.glTranslatef(0, 16, 0);
+            GL11.glRotatef(180, 1, 0, 0);
+            GL11.glTranslatef(0, -16, 0);
+            GL11.glTranslatef(0, 8, 0);
+            playerRenderer.drawFirstPersonHand(Tessellator.instance, mc.thePlayer, false);
+            GL11.glPopMatrix();
             GL11.glPopMatrix();
 
 
diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java
index 96c185e2e..6f1dd850a 100644
--- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java
+++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java
@@ -63,6 +63,7 @@ public class ItemModelStandard extends ItemModel{
     public void render(@NotNull final Tessellator tessellator, @Nullable final Entity holder, @NotNull final ItemStack itemStack, @NotNull final String displayPosId, final boolean items3d, final int clusterSize, final float brightness, final float alpha, final float partialTick, final boolean mirrorX) {
         random.setSeed(187L);
         final DisplayPos displayPos = getDisplayPos(displayPosId);
+
         GL11.glTranslatef(displayPos.tx, displayPos.ty, displayPos.tz);
         GL11.glRotatef(displayPos.rx, 1, 0, 0);
         GL11.glRotatef(displayPos.ry, 0, 1, 0);
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/Cube.java b/game/client/src/main/java/net/minecraft/client/render/model/Cube.java
deleted file mode 100644
index 8ba09a4be..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/Cube.java
+++ /dev/null
@@ -1,291 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.client.GLAllocation;
-import net.minecraft.client.render.Vertex;
-import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.client.render.Polygon;
-import org.lwjgl.opengl.GL11;
-
-public class Cube
-{
-    private Vertex[] vertices;
-    private Polygon[] polygons;
-    private final int textureU;
-    private final int textureV;
-    private final int texWidth;
-    private final int texHeight;
-    public float x;
-    public float y;
-    public float z;
-    public float xRot;
-    public float yRot;
-    public float zRot;
-    private boolean compiled;
-    private int displayList;
-    public boolean mirror;
-    public boolean visible;
-    public boolean neverRender;
-
-
-    public Cube(int u, int v, int texWidth, int texHeight)
-    {
-        compiled = false;
-        displayList = 0;
-        mirror = false;
-        visible = true;
-        neverRender = false;
-        textureU = u;
-        textureV = v;
-        this.texWidth = texWidth;
-        this.texHeight = texHeight;
-    }
-    public Cube(int u, int v)
-    {
-        this(u, v, 64, 32);
-    }
-
-    public void addBox(float minX, float minY, float minZ, int sizeX, int sizeY, int sizeZ)
-    {
-        addBox(minX, minY, minZ, sizeX, sizeY, sizeZ, 0.0F);
-    }
-
-    public void addBox(float minX, float minY, float minZ, int sizeX, int sizeY, int sizeZ, float expandAmount)
-    {
-    	addBox(minX, minY, minZ, sizeX, sizeY, sizeZ, expandAmount, false);
-    }
-
-    public void addBox(float minX, float minY, float minZ, int sizeX, int sizeY, int sizeZ, float expandAmount, boolean flipBottomUV)
-    {
-        vertices = new Vertex[8];
-        polygons = new Polygon[6];
-        float maxX = minX + (float)sizeX;
-        float maxY = minY + (float)sizeY;
-        float maxZ = minZ + (float)sizeZ;
-        minX -= expandAmount;
-        minY -= expandAmount;
-        minZ -= expandAmount;
-        maxX += expandAmount;
-        maxY += expandAmount;
-        maxZ += expandAmount;
-        if(mirror)
-        {
-            float temp = maxX;
-            maxX = minX;
-            minX = temp;
-        }
-        Vertex ptvMinXMinYMinZ = new Vertex(minX, minY, minZ, 0.0F, 0.0F);
-        Vertex ptvMaxXMinYMinZ = new Vertex(maxX, minY, minZ, 0.0F, 8F);
-        Vertex ptvMaxXMaxYMinZ = new Vertex(maxX, maxY, minZ, 8F, 8F);
-        Vertex ptvMinXMaxYMinZ = new Vertex(minX, maxY, minZ, 8F, 0.0F);
-        Vertex ptvMinXMinYMaxZ = new Vertex(minX, minY, maxZ, 0.0F, 0.0F);
-        Vertex ptvMaxXMinYMaxZ = new Vertex(maxX, minY, maxZ, 0.0F, 8F);
-        Vertex ptvMaxXMaxYMaxZ = new Vertex(maxX, maxY, maxZ, 8F, 8F);
-        Vertex ptvMinXMaxYMaxZ = new Vertex(minX, maxY, maxZ, 8F, 0.0F);
-        vertices[0] = ptvMinXMinYMinZ;
-        vertices[1] = ptvMaxXMinYMinZ;
-        vertices[2] = ptvMaxXMaxYMinZ;
-        vertices[3] = ptvMinXMaxYMinZ;
-        vertices[4] = ptvMinXMinYMaxZ;
-        vertices[5] = ptvMaxXMinYMaxZ;
-        vertices[6] = ptvMaxXMaxYMaxZ;
-        vertices[7] = ptvMinXMaxYMaxZ;
-        polygons[0] = new Polygon(
-                new Vertex[] { ptvMaxXMinYMaxZ, ptvMaxXMinYMinZ, ptvMaxXMaxYMinZ, ptvMaxXMaxYMaxZ },
-                textureU + sizeZ + sizeX, textureV + sizeZ,
-                textureU + sizeZ + sizeX + sizeZ, textureV + sizeZ + sizeY,
-                texWidth, texHeight
-        );
-        polygons[1] = new Polygon(
-                new Vertex[] { ptvMinXMinYMinZ, ptvMinXMinYMaxZ, ptvMinXMaxYMaxZ, ptvMinXMaxYMinZ },
-                textureU, textureV + sizeZ,
-                textureU + sizeZ, textureV + sizeZ + sizeY,
-                texWidth, texHeight
-        );
-        polygons[2] = new Polygon(
-                new Vertex[] { ptvMaxXMinYMaxZ, ptvMinXMinYMaxZ, ptvMinXMinYMinZ, ptvMaxXMinYMinZ },
-                textureU + sizeZ, textureV,
-                textureU + sizeZ + sizeX, textureV + sizeZ,
-                texWidth, texHeight
-        );
-        if(flipBottomUV) {
-            polygons[3] = new Polygon(
-                    new Vertex[] { ptvMaxXMaxYMaxZ, ptvMinXMaxYMaxZ, ptvMinXMaxYMinZ, ptvMaxXMaxYMinZ },
-                    textureU + sizeZ + sizeX, textureV,
-                    textureU + sizeZ + sizeX + sizeX, textureV + sizeZ,
-                    texWidth, texHeight
-            );
-            polygons[3].flipNormal = true;
-        }else {
-            polygons[3] = new Polygon(
-                    new Vertex[] { ptvMaxXMaxYMinZ, ptvMinXMaxYMinZ, ptvMinXMaxYMaxZ, ptvMaxXMaxYMaxZ },
-                    textureU + sizeZ + sizeX, textureV,
-                    textureU + sizeZ + sizeX + sizeX, textureV + sizeZ,
-                    texWidth, texHeight
-            );
-        }
-        polygons[4] = new Polygon(
-                new Vertex[] { ptvMaxXMinYMinZ, ptvMinXMinYMinZ, ptvMinXMaxYMinZ, ptvMaxXMaxYMinZ },
-                textureU + sizeZ, textureV + sizeZ,
-                textureU + sizeZ + sizeX, textureV + sizeZ + sizeY,
-                texWidth, texHeight
-        );
-        polygons[5] = new Polygon(
-                new Vertex[] { ptvMinXMinYMaxZ, ptvMaxXMinYMaxZ, ptvMaxXMaxYMaxZ, ptvMinXMaxYMaxZ },
-                textureU + sizeZ + sizeX + sizeZ,
-                textureV + sizeZ, textureU + sizeZ + sizeX + sizeZ + sizeX,
-                textureV + sizeZ + sizeY, texWidth, texHeight
-        );
-        if(mirror)
-        {
-            for (Polygon face : polygons) {
-                face.mirror();
-            }
-        }
-    }
-
-    public void setRotationPoint(float x, float y, float z)
-    {
-        this.x = x;
-        this.y = y;
-        this.z = z;
-    }
-
-    public void setRotationAngle(float x, float y, float z)
-    {
-        xRot = x;
-        yRot = y;
-        zRot = z;
-    }
-
-    public void render(float scale)
-    {
-        if(neverRender)
-        {
-            return;
-        }
-        if(!visible)
-        {
-            return;
-        }
-        if(!compiled)
-        {
-            compile(scale);
-        }
-        if(xRot != 0.0F || yRot != 0.0F || zRot != 0.0F)
-        {
-            GL11.glPushMatrix();
-            GL11.glTranslatef(x * scale, y * scale, z * scale);
-            if(zRot != 0.0F)
-            {
-                GL11.glRotatef(zRot * 57.29578F, 0.0F, 0.0F, 1.0F);
-            }
-            if(yRot != 0.0F)
-            {
-                GL11.glRotatef(yRot * 57.29578F, 0.0F, 1.0F, 0.0F);
-            }
-            if(xRot != 0.0F)
-            {
-                GL11.glRotatef(xRot * 57.29578F, 1.0F, 0.0F, 0.0F);
-            }
-            GL11.glCallList(displayList);
-            GL11.glPopMatrix();
-        } else
-        if(x != 0.0F || y != 0.0F || z != 0.0F)
-        {
-            GL11.glTranslatef(x * scale, y * scale, z * scale);
-            GL11.glCallList(displayList);
-            GL11.glTranslatef(-x * scale, -y * scale, -z * scale);
-        } else
-        {
-            GL11.glCallList(displayList);
-        }
-    }
-
-    public void renderWithRotation(float scale)
-    {
-        if(neverRender)
-        {
-            return;
-        }
-        if(!visible)
-        {
-            return;
-        }
-        if(!compiled)
-        {
-            compile(scale);
-        }
-        GL11.glPushMatrix();
-        GL11.glTranslatef(x * scale, y * scale, z * scale);
-        if(yRot != 0.0F)
-        {
-            GL11.glRotatef(yRot * 57.29578F, 0.0F, 1.0F, 0.0F);
-        }
-        if(xRot != 0.0F)
-        {
-            GL11.glRotatef(xRot * 57.29578F, 1.0F, 0.0F, 0.0F);
-        }
-        if(zRot != 0.0F)
-        {
-            GL11.glRotatef(zRot * 57.29578F, 0.0F, 0.0F, 1.0F);
-        }
-        GL11.glCallList(displayList);
-        GL11.glPopMatrix();
-    }
-
-    public void translateTo(float scale)
-    {
-        if(neverRender)
-        {
-            return;
-        }
-        if(!visible)
-        {
-            return;
-        }
-        if(!compiled)
-        {
-            compile(scale);
-        }
-        if(xRot != 0.0F || yRot != 0.0F || zRot != 0.0F)
-        {
-            GL11.glTranslatef(x * scale, y * scale, z * scale);
-            if(zRot != 0.0F)
-            {
-                GL11.glRotatef(zRot * 57.29578F, 0.0F, 0.0F, 1.0F);
-            }
-            if(yRot != 0.0F)
-            {
-                GL11.glRotatef(yRot * 57.29578F, 0.0F, 1.0F, 0.0F);
-            }
-            if(xRot != 0.0F)
-            {
-                GL11.glRotatef(xRot * 57.29578F, 1.0F, 0.0F, 0.0F);
-            }
-        } else
-        if(x != 0.0F || y != 0.0F || z != 0.0F)
-        {
-            GL11.glTranslatef(x * scale, y * scale, z * scale);
-        }
-    }
-
-    private void compile(float scale)
-    {
-        displayList = GLAllocation.generateDisplayLists(1);
-        GL11.glNewList(displayList, GL11.GL_COMPILE);
-        Tessellator tessellator = Tessellator.instance;
-        for (Polygon polygon : polygons) {
-            polygon.render(tessellator, scale);
-        }
-        GL11.glEndList();
-        compiled = true;
-    }
-
-    public Polygon[] getPolygons() {
-        return polygons;
-    }
-
-    public Vertex[] getVertices() {
-        return vertices;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelBase.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelBase.java
deleted file mode 100644
index 94ddaedc3..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelBase.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import org.jetbrains.annotations.Nullable;
-
-public abstract class ModelBase
-{
-
-    public float swingProgress;
-    public boolean isRiding;
-
-    public ModelBase()
-    {
-        isRiding = false;
-    }
-
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-    }
-
-    protected void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-    }
-
-    public void onUnload(){
-
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelBiped.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelBiped.java
deleted file mode 100644
index ff4ce45b5..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelBiped.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.IItemHolding;
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelBiped extends ModelBase
-{
-    public Cube head;
-    public Cube hair;
-    public Cube body;
-    public Cube armRight;
-    public Cube armLeft;
-    public Cube legRight;
-    public Cube legLeft;
-    public Cube ear;
-    public Cube cloak;
-    public boolean holdingLeftHand;
-    public boolean holdingRightHand;
-    public boolean holdingLarge = false;
-    public boolean sneaking;
-
-
-    public ModelBiped()
-    {
-        this(0.0F);
-    }
-
-    public ModelBiped(float expansion)
-    {
-        this(expansion, 0.0F);
-    }
-
-    public ModelBiped(float expansion, float yRotOffset)
-    {
-        holdingLeftHand = false;
-        holdingRightHand = false;
-        sneaking = false;
-        cloak = new Cube(0, 0);
-        cloak.addBox(-5F, 0.0F, -1F, 10, 16, 1, expansion);
-        ear = new Cube(24, 0);
-        ear.addBox(-3F, -6F, -1F, 6, 6, 1, expansion);
-        head = new Cube(0, 0);
-        head.addBox(-4F, -8F, -4F, 8, 8, 8, expansion);
-        head.setRotationPoint(0.0F, 0.0F + yRotOffset, 0.0F);
-        hair = new Cube(32, 0);
-        hair.addBox(-4F, -8F, -4F, 8, 8, 8, expansion + 0.5F);
-        hair.setRotationPoint(0.0F, 0.0F + yRotOffset, 0.0F);
-        body = new Cube(16, 16);
-        body.addBox(-4F, 0.0F, -2F, 8, 12, 4, expansion);
-        body.setRotationPoint(0.0F, 0.0F + yRotOffset, 0.0F);
-        armRight = new Cube(40, 16);
-        armRight.addBox(-3F, -2F, -2F, 4, 12, 4, expansion);
-        armRight.setRotationPoint(-5F, 2.0F + yRotOffset, 0.0F);
-        armLeft = new Cube(40, 16);
-        armLeft.mirror = true;
-        armLeft.addBox(-1F, -2F, -2F, 4, 12, 4, expansion);
-        armLeft.setRotationPoint(5F, 2.0F + yRotOffset, 0.0F);
-        legRight = new Cube(0, 16);
-        legRight.addBox(-2F, 0.0F, -2F, 4, 12, 4, expansion);
-        legRight.setRotationPoint(-2F, 12F + yRotOffset, 0.0F);
-        legLeft = new Cube(0, 16);
-        legLeft.mirror = true;
-        legLeft.addBox(-2F, 0.0F, -2F, 4, 12, 4, expansion);
-        legLeft.setRotationPoint(2.0F, 12F + yRotOffset, 0.0F);
-    }
-
-    @Override
-    public void render(Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        head.render(scale);
-        body.render(scale);
-        armRight.render(scale);
-        armLeft.render(scale);
-        legRight.render(scale);
-        legLeft.render(scale);
-        hair.render(scale);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        head.yRot = headYaw / 57.29578F; // 1 rad
-        head.xRot = headPitch / 57.29578F; // 1 rad
-        hair.yRot = head.yRot;
-        hair.xRot = head.xRot;
-        if (holdingLarge) {
-            armRight.xRot = MathHelper.cos(limbSwing/2 * 0.6662F) * 2.0F * limbYaw * 0.125F - 0.65f;
-            armLeft.xRot = MathHelper.cos(limbSwing/2 * 0.6662F) * 2.0F * limbYaw * 0.125F - 0.65f;
-        } else {
-            armRight.xRot = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 2.0F * limbYaw * 0.5F;
-            armLeft.xRot = MathHelper.cos(limbSwing * 0.6662F) * 2.0F * limbYaw * 0.5F;
-        }
-        armRight.zRot = 0.0F;
-        armLeft.zRot = 0.0F;
-        legRight.xRot = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
-        legLeft.xRot = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
-        legRight.yRot = 0.0F;
-        legLeft.yRot = 0.0F;
-        if(isRiding)
-        {
-            armRight.xRot += -0.6283185F; // -36 deg
-            armLeft.xRot += -0.6283185F; // -36 deg
-            legRight.xRot = -1.256637F; // -72 deg
-            legLeft.xRot = -1.256637F; // -72 deg
-            legRight.yRot = 0.3141593F; // 18 deg
-            legLeft.yRot = -0.3141593F; // -18 deg
-        }
-        if(holdingLeftHand)
-        {
-            armLeft.xRot = (armLeft.xRot * 0.5F) - 0.3141593F /*18 deg*/;
-        }
-        if(holdingRightHand)
-        {
-            armRight.xRot = (armRight.xRot * 0.5F) - 0.3141593F /*18 deg*/;
-        }
-        armRight.yRot = 0.0F;
-        armLeft.yRot = 0.0F;
-        if(swingProgress > -9990F)
-        {
-            if (mob instanceof IItemHolding && ((IItemHolding) mob).isLeftHanded()) {
-                body.yRot = MathHelper.sin(MathHelper.sqrt_float(swingProgress) * MathHelper.PI * -2.0F) * 0.2F;
-                armRight.z = MathHelper.sin(body.yRot) * 5F;
-                armRight.x = -MathHelper.cos(body.yRot) * 5F;
-                armRight.yRot += body.yRot;
-                armRight.xRot += body.xRot;
-
-                armLeft.z = -MathHelper.sin(body.yRot) * 5F;
-                armLeft.x = MathHelper.cos(body.yRot) * 5F;
-                armLeft.yRot += body.yRot;
-                armLeft.xRot += body.xRot;
-
-                float f6 = 1.0F - swingProgress;
-                f6 *= f6;
-                f6 *= f6;
-                f6 = 1.0F - f6;
-                float f7 = MathHelper.sin(f6 * MathHelper.PI);
-                float f8 = MathHelper.sin(swingProgress * MathHelper.PI) * -(head.xRot - 0.7F) * 0.75F;
-
-                armLeft.xRot -= (double)f7 * 1.2D + (double)f8;
-                armLeft.yRot += body.yRot * 2.0F;
-                armLeft.zRot = MathHelper.sin(swingProgress * MathHelper.PI) * 0.4F;
-            } else {
-                body.yRot = MathHelper.sin(MathHelper.sqrt_float(swingProgress) * MathHelper.PI * 2.0F) * 0.2F;
-                armRight.z = MathHelper.sin(body.yRot) * 5F;
-                armRight.x = -MathHelper.cos(body.yRot) * 5F;
-                armRight.yRot += body.yRot;
-                armRight.xRot += body.xRot;
-
-                armLeft.z = -MathHelper.sin(body.yRot) * 5F;
-                armLeft.x = MathHelper.cos(body.yRot) * 5F;
-                armLeft.yRot += body.yRot;
-                armLeft.xRot += body.xRot;
-
-                float f6 = 1.0F - swingProgress;
-                f6 *= f6;
-                f6 *= f6;
-                f6 = 1.0F - f6;
-                float f7 = MathHelper.sin(f6 * MathHelper.PI);
-                float f8 = MathHelper.sin(swingProgress * MathHelper.PI) * -(head.xRot - 0.7F) * 0.75F;
-
-                armRight.xRot -= (double)f7 * 1.2D + (double)f8;
-                armRight.yRot += body.yRot * 2.0F;
-                armRight.zRot = MathHelper.sin(swingProgress * MathHelper.PI) * -0.4F;
-            }
-
-        }
-        if(sneaking)
-        {
-            body.xRot = 0.5F;
-            legRight.xRot -= 0.0F;
-            legLeft.xRot -= 0.0F;
-            armRight.xRot += 0.4F;
-//            armLeft.xRot += 0.4F;
-            if (holdingLarge) {
-                armRight.xRot -= 0.4f;
-                armLeft.xRot -= 0.5f;
-            }
-            legRight.z = 4F;
-            legLeft.z = 4F;
-            legRight.y = 9F;
-            legLeft.y = 9F;
-            head.y = 1.0F;
-            hair.y = 1.0F;
-        } else
-        {
-            body.xRot = 0.0F;
-            legRight.z = 0.0F;
-            legLeft.z = 0.0F;
-            legRight.y = 12F;
-            legLeft.y = 12F;
-            head.y = 0.0F;
-            hair.y = 0.0F;
-        }
-        armRight.zRot += MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
-        armLeft.zRot -= MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
-        armRight.xRot += MathHelper.sin(limbPitch * 0.067F) * 0.05F;
-        armLeft.xRot -= MathHelper.sin(limbPitch * 0.067F) * 0.05F;
-    }
-
-    public void renderCloak(float scale)
-    {
-        cloak.render(scale);
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelBoat.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelBoat.java
deleted file mode 100644
index 1ec5b8b43..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelBoat.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelBoat extends ModelBase
-{
-    public Cube[] boatSides;
-    public ModelBoat()
-    {
-        boatSides = new Cube[5];
-        boatSides[0] = new Cube(0, 8);
-        boatSides[1] = new Cube(0, 0);
-        boatSides[2] = new Cube(0, 0);
-        boatSides[3] = new Cube(0, 0);
-        boatSides[4] = new Cube(0, 0);
-        byte w = 24;
-        byte d = 6;
-        byte h = 20;
-        byte yOff = 4;
-        boatSides[0].addBox(-w / 2, -h / 2 + 2, -3F, w, h - 4, 4, 0.0F);
-        boatSides[0].setRotationPoint(0.0F, 0 + yOff, 0.0F);
-        boatSides[1].addBox(-w / 2 + 2, -d - 1, -1F, w - 4, d, 2, 0.0F);
-        boatSides[1].setRotationPoint(-w / 2 + 1, 0 + yOff, 0.0F);
-        boatSides[2].addBox(-w / 2 + 2, -d - 1, -1F, w - 4, d, 2, 0.0F);
-        boatSides[2].setRotationPoint(w / 2 - 1, 0 + yOff, 0.0F);
-        boatSides[3].addBox(-w / 2 + 2, -d - 1, -1F, w - 4, d, 2, 0.0F);
-        boatSides[3].setRotationPoint(0.0F, 0 + yOff, -h / 2 + 1);
-        boatSides[4].addBox(-w / 2 + 2, -d - 1, -1F, w - 4, d, 2, 0.0F);
-        boatSides[4].setRotationPoint(0.0F, 0 + yOff, h / 2 - 1);
-        boatSides[0].xRot = MathHelper.PI / 2F;
-        boatSides[1].yRot = MathHelper.PI * 1.5F;
-        boatSides[2].yRot = MathHelper.PI / 2F;
-        boatSides[3].yRot = MathHelper.PI;
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        for(int i = 0; i < 5; i++)
-        {
-            boatSides[i].render(scale);
-        }
-    }
-
-
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelCannonball.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelCannonball.java
deleted file mode 100644
index 4f36e71a7..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelCannonball.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelCannonball extends ModelBase
-{
-
-    public Cube ball;
-
-    public ModelCannonball()
-    {
-        ball = new Cube(0, 0);
-        ball.addBox(0F, 0F, 0F, 8, 8, 8);
-        ball.setRotationPoint(0.0F, 0.0F, 0.0F);
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        ball.render(scale);
-    }
-
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelChicken.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelChicken.java
deleted file mode 100644
index 85e39f891..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelChicken.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelChicken extends ModelBase
-{
-    public Cube head;
-    public Cube body;
-    public Cube rightLeg;
-    public Cube leftLeg;
-    public Cube rightWing;
-    public Cube leftWing;
-    public Cube bill;
-    public Cube chin;
-
-
-    public ModelChicken()
-    {
-        byte yOff = 16;
-        head = new Cube(0, 0);
-        head.addBox(-2F, -6F, -2F, 4, 6, 3, 0.0F);
-        head.setRotationPoint(0.0F, -1 + yOff, -4F);
-        bill = new Cube(14, 0);
-        bill.addBox(-2F, -4F, -4F, 4, 2, 2, 0.0F);
-        bill.setRotationPoint(0.0F, -1 + yOff, -4F);
-        chin = new Cube(14, 4);
-        chin.addBox(-1F, -2F, -3F, 2, 2, 2, 0.0F);
-        chin.setRotationPoint(0.0F, -1 + yOff, -4F);
-        body = new Cube(0, 9);
-        body.addBox(-3F, -4F, -3F, 6, 8, 6, 0.0F);
-        body.setRotationPoint(0.0F, 0 + yOff, 0.0F);
-        rightLeg = new Cube(26, 0);
-        rightLeg.addBox(-1F, 0.0F, -3F, 3, 5, 3);
-        rightLeg.setRotationPoint(-2F, 3 + yOff, 1.0F);
-        leftLeg = new Cube(26, 0);
-        leftLeg.addBox(-1F, 0.0F, -3F, 3, 5, 3);
-        leftLeg.setRotationPoint(1.0F, 3 + yOff, 1.0F);
-        rightWing = new Cube(24, 13);
-        rightWing.addBox(0.0F, 0.0F, -3F, 1, 4, 6);
-        rightWing.setRotationPoint(-4F, -3 + yOff, 0.0F);
-        leftWing = new Cube(24, 13);
-        leftWing.addBox(-1F, 0.0F, -3F, 1, 4, 6);
-        leftWing.setRotationPoint(4F, -3 + yOff, 0.0F);
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        head.render(scale);
-        bill.render(scale);
-        chin.render(scale);
-        body.render(scale);
-        rightLeg.render(scale);
-        leftLeg.render(scale);
-        rightWing.render(scale);
-        leftWing.render(scale);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        head.xRot = headPitch / 57.29578F;
-        head.yRot = headYaw / 57.29578F;
-        bill.xRot = head.xRot;
-        bill.yRot = head.yRot;
-        chin.xRot = head.xRot;
-        chin.yRot = head.yRot;
-        body.xRot = MathHelper.PI / 2F;
-        rightLeg.xRot = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
-        leftLeg.xRot = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
-        rightWing.zRot = limbPitch;
-        leftWing.zRot = -limbPitch;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelCow.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelCow.java
deleted file mode 100644
index ec1ede7d9..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelCow.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelCow extends ModelQuadruped
-{
-    Cube udders;
-    Cube horn1;
-    Cube horn2;
-
-
-    public ModelCow()
-    {
-        super(12, 0.0F);
-        head = new Cube(0, 0);
-        head.addBox(-4F, -4F, -6F, 8, 8, 6, 0.0F);
-        head.setRotationPoint(0.0F, 4F, -8F);
-        horn1 = new Cube(22, 0);
-        horn1.addBox(-5F, -5F, -4F, 1, 3, 1, 0.0F);
-        horn1.setRotationPoint(0.0F, 4F, -8F);
-        horn2 = new Cube(22, 0);
-        horn2.addBox(4F, -5F, -4F, 1, 3, 1, 0.0F);
-        horn2.setRotationPoint(0.0F, 4F, -8F);
-        udders = new Cube(52, 0);
-        udders.addBox(-2F, -3F, 0.0F, 4, 6, 2, 0.0F);
-        udders.setRotationPoint(0.0F, 14F, 6F);
-        udders.xRot = MathHelper.PI / 2F;
-        body = new Cube(18, 4);
-        body.addBox(-6F, -10F, -7F, 12, 18, 10, 0.0F);
-        body.setRotationPoint(0.0F, 5F, 2.0F);
-        leg1.x--;
-        leg2.x++;
-        leg1.z += 0.0F;
-        leg2.z += 0.0F;
-        leg3.x--;
-        leg4.x++;
-        leg3.z--;
-        leg4.z--;
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        super.render(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        horn1.render(scale);
-        horn2.render(scale);
-        udders.render(scale);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        super.setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        horn1.yRot = head.yRot;
-        horn1.xRot = head.xRot;
-        horn2.yRot = head.yRot;
-        horn2.xRot = head.xRot;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelCreeper.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelCreeper.java
deleted file mode 100644
index 8b44b1ec7..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelCreeper.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelCreeper extends ModelBase
-{
-    public Cube head;
-    public Cube hair;
-    public Cube body;
-    public Cube leg1;
-    public Cube leg2;
-    public Cube leg3;
-    public Cube leg4;
-
-
-    public ModelCreeper()
-    {
-        this(0.0F);
-    }
-
-    public ModelCreeper(float expansion)
-    {
-        int yOff = 4;
-        head = new Cube(0, 0);
-        head.addBox(-4F, -6F, -4F, 8, 8, 8, expansion);
-        head.setRotationPoint(0.0F, yOff, 0.0F);
-        hair = new Cube(32, 0);
-        hair.addBox(-4F, -6F, -4F, 8, 8, 8, expansion + 0.5F);
-        hair.setRotationPoint(0.0F, yOff, 0.0F);
-        body = new Cube(16, 16);
-        body.addBox(-4F, 2.0F, -2F, 8, 12, 4, expansion);
-        body.setRotationPoint(0.0F, yOff, 0.0F);
-        leg1 = new Cube(0, 16);
-        leg1.addBox(-2F, 2.0F, -2F, 4, 6, 4, expansion);
-        leg1.setRotationPoint(-2F, 12 + yOff, 4F);
-        leg2 = new Cube(0, 16);
-        leg2.addBox(-2F, 2.0F, -2F, 4, 6, 4, expansion);
-        leg2.setRotationPoint(2.0F, 12 + yOff, 4F);
-        leg3 = new Cube(0, 16);
-        leg3.addBox(-2F, 2.0F, -2F, 4, 6, 4, expansion);
-        leg3.setRotationPoint(-2F, 12 + yOff, -4F);
-        leg4 = new Cube(0, 16);
-        leg4.addBox(-2F, 2.0F, -2F, 4, 6, 4, expansion);
-        leg4.setRotationPoint(2.0F, 12 + yOff, -4F);
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        head.render(scale);
-        body.render(scale);
-        leg1.render(scale);
-        leg2.render(scale);
-        leg3.render(scale);
-        leg4.render(scale);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        head.yRot = headYaw / 57.29578F;
-        head.xRot = headPitch / 57.29578F;
-        leg1.xRot = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
-        leg2.xRot = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
-        leg3.xRot = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
-        leg4.xRot = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelFlag.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelFlag.java
deleted file mode 100644
index e27508e4b..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelFlag.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.client.render.Polygon;
-
-public class ModelFlag {
-    public Cube flagPole;
-    public Cube flagPoleShort;
-    public Cube flag;
-    public Cube flagOverlay;
-    public Cube flagBase;
-
-    public ModelFlag(boolean mirrored)
-    {
-        flagPole = new Cube(0, 0, 64, 48);
-        flagPole.addBox(-1F, -22F, -1F, 2, 33, 2, 0.0F);
-        flagPoleShort = new Cube(0, 0, 64, 48);
-        flagPoleShort.addBox(-1F, -22F, -1F, 2, 16, 2, 0.0F);
-        flag = new Cube(8, 0, 64, 48);
-        flag.addBox(1F, -21F, -0.0F, 24, 16, 0, 0.0F);
-        flagOverlay = new Cube(0, 0, 24, 16);
-        flagOverlay.addBox(1F, -21F, -0.0F, 24, 16, 0, 0.0F);
-        if (mirrored) {
-            Polygon[] faces = flagOverlay.getPolygons();
-            faces[5].mirrorU();
-        }
-        flagBase = new Cube(0, 40, 64, 48);
-        flagBase.addBox(-2F, 11F, -2F, 4, 1, 4, 0.0F);
-    }
-
-    public void renderPole()
-    {
-        flagPole.render(0.0625F);
-    }
-    public void renderPoleShort()
-    {
-        flagPoleShort.render(0.0625F);
-    }
-    public void renderBase()
-    {
-        flagBase.render(0.0625F);
-    }
-    public void renderFlag()
-    {
-        flag.render(0.0625F);
-    }
-    public void renderFlagOverlay()
-    {
-        flagOverlay.render(0.0625F);
-    }
-
-}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelFlagBase.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelFlagBase.java
deleted file mode 100644
index 7b5a5d2d4..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelFlagBase.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package net.minecraft.client.render.model;
-
-public class ModelFlagBase {
-    public Cube flagBase;
-
-    public ModelFlagBase()
-    {
-        flagBase = new Cube(0, 0);
-        flagBase.addBox(-2F, 10F, -2F, 4, 2, 4, 0.0F);
-    }
-
-    public void render()
-    {
-        flagBase.render(0.0625F);
-    }
-}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelGhast.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelGhast.java
deleted file mode 100644
index eae274de4..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelGhast.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Random;
-
-public class ModelGhast extends ModelBase
-{
-
-    Cube body;
-    Cube[] tentacles;
-
-    public ModelGhast()
-    {
-        tentacles = new Cube[9];
-        byte yOff = -16;
-        body = new Cube(0, 0);
-        body.addBox(-8F, -8F, -8F, 16, 16, 16);
-        body.y += 24 + yOff;
-        Random random = new Random(1660L);
-        for(int i = 0; i < tentacles.length; i++)
-        {
-            tentacles[i] = new Cube(0, 0);
-            float xo = (((((float)(i % 3) - (float)((i / 3) % 2) * 0.5F) + 0.25F) / 2.0F) * 2.0F - 1.0F) * 5F;
-            float yo = (((float)(i / 3) / 2.0F) * 2.0F - 1.0F) * 5F;
-            int len = random.nextInt(7) + 8;
-            tentacles[i].addBox(-1F, 0.0F, -1F, 2, len, 2);
-            tentacles[i].x = xo;
-            tentacles[i].z = yo;
-            tentacles[i].y = 31 + yOff;
-        }
-
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        for(int i = 0; i < tentacles.length; i++)
-        {
-            tentacles[i].xRot = 0.2F * MathHelper.sin(limbPitch * 0.3F + (float)i) + 0.4F;
-        }
-
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        body.render(scale);
-        for (Cube tentacle : tentacles) {
-            tentacle.render(scale);
-        }
-
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelMinecart.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelMinecart.java
deleted file mode 100644
index 45e22d331..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelMinecart.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelMinecart extends ModelBase
-{
-
-    public Cube[] sideModels;
-
-    public ModelMinecart()
-    {
-        sideModels = new Cube[7];
-        sideModels[0] = new Cube(0, 10);
-        sideModels[1] = new Cube(0, 0);
-        sideModels[2] = new Cube(0, 0);
-        sideModels[3] = new Cube(0, 0);
-        sideModels[4] = new Cube(0, 0);
-        sideModels[5] = new Cube(44, 10);
-        byte byte0 = 20;
-        byte byte1 = 8;
-        byte byte2 = 16;
-        byte byte3 = 4;
-        sideModels[0].addBox(-byte0 / 2f, -byte2 / 2f, -1F, byte0, byte2, 2, 0.0F);
-        sideModels[0].setRotationPoint(0.0F, 0 + byte3, 0.0F);
-        sideModels[5].addBox(-byte0 / 2f + 1, -byte2 / 2f + 1, -1F, byte0 - 2, byte2 - 2, 1, 0.0F);
-        sideModels[5].setRotationPoint(0.0F, 0 + byte3, 0.0F);
-        sideModels[1].addBox(-byte0 / 2f + 2, -byte1 - 1, -1F, byte0 - 4, byte1, 2, 0.0F);
-        sideModels[1].setRotationPoint(-byte0 / 2 + 1, 0 + byte3, 0.0F);
-        sideModels[2].addBox(-byte0 / 2f + 2, -byte1 - 1, -1F, byte0 - 4, byte1, 2, 0.0F);
-        sideModels[2].setRotationPoint(byte0 / 2 - 1, 0 + byte3, 0.0F);
-        sideModels[3].addBox(-byte0 / 2f + 2, -byte1 - 1, -1F, byte0 - 4, byte1, 2, 0.0F);
-        sideModels[3].setRotationPoint(0.0F, 0 + byte3, -byte2 / 2f + 1);
-        sideModels[4].addBox(-byte0 / 2f + 2, -byte1 - 1, -1F, byte0 - 4, byte1, 2, 0.0F);
-        sideModels[4].setRotationPoint(0.0F, 0 + byte3, byte2 / 2f - 1);
-        sideModels[0].xRot = MathHelper.PI / 2F;
-        sideModels[1].yRot = MathHelper.PI * 1.5F;
-        sideModels[2].yRot = MathHelper.PI / 2F;
-        sideModels[3].yRot = MathHelper.PI;
-        sideModels[5].xRot = -MathHelper.PI / 2F;
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        sideModels[5].y = 4F - limbPitch;
-        for(int i = 0; i < 6; i++)
-        {
-            sideModels[i].render(scale);
-        }
-
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelPig.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelPig.java
deleted file mode 100644
index f8591d002..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelPig.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelPig extends ModelQuadruped
-{
-    public Cube nose;
-
-    public ModelPig()
-    {
-        this(0.0F);
-    }
-
-    public ModelPig(float f)
-    {
-        super(6, f);
-        nose = new Cube(16, 16);
-        nose.addBox(-2.0F, 0.0F, -9.0F, 4, 3, 1);
-        nose.setRotationPoint(0.0F, 12, -6F);
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick) {
-        super.render(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        nose.render(scale);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick) {
-        super.setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        nose.xRot = headPitch / 57.29578F;
-        nose.yRot = headYaw / 57.29578F;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelPigman.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelPigman.java
deleted file mode 100644
index cfda6a811..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelPigman.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelPigman extends ModelBiped {
-    public Cube nose;
-
-    public ModelPigman()
-    {
-        this(0.0F);
-    }
-
-    public ModelPigman(float yRotOffset)
-    {
-        this(6, yRotOffset);
-    }
-
-    public ModelPigman(float expansion, float yRotOffset) {
-        super(expansion, yRotOffset);
-        nose = new Cube(24, 0);
-        nose.addBox(-2.0F, -4.0F, -5.0F, 4, 3, 1);
-        nose.setRotationPoint(0.0F, 0, 0);
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick) {
-        super.render(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        nose.render(scale);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick) {
-        super.setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        nose.xRot = headPitch / 57.29578F;
-        nose.yRot = headYaw / 57.29578F;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayer.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayer.java
deleted file mode 100644
index 70903946e..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayer.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.player.Player;
-import org.jetbrains.annotations.Nullable;
-import org.lwjgl.opengl.GL11;
-
-public class ModelPlayer extends ModelBiped {
-
-    public Cube bipedLeftArmOverlay;
-    public Cube bipedRightArmOverlay;
-    public Cube bipedLeftLegOverlay;
-    public Cube bipedRightLegOverlay;
-    public Cube bipedBodyOverlay;
-
-    public ModelPlayer(float expansion){
-        this(expansion, 0.0F);
-    }
-
-    public ModelPlayer(float expansion, float yRotOffset){
-        holdingLeftHand = false;
-        holdingRightHand = false;
-        sneaking = false;
-        cloak = new Cube(0, 0, 64, 32);
-        cloak.addBox(-5F, 0.0F, -1F, 10, 16, 1, expansion, true);
-        ear = new Cube(24, 0, 64, 64);
-        ear.addBox(-3F, -6F, -1F, 6, 6, 1, expansion, true);
-        bipedLeftArmOverlay = new Cube(48, 48, 64, 64);
-        bipedLeftArmOverlay.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, expansion + 0.25F, true);
-        bipedLeftArmOverlay.setRotationPoint(5.0F, 2.0F, 0.0F);
-        bipedRightArmOverlay = new Cube(40, 32, 64, 64);
-        bipedRightArmOverlay.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, expansion + 0.25F, true);
-        bipedRightArmOverlay.setRotationPoint(-5.0F, 2.0F, 10.0F);
-        bipedLeftLegOverlay = new Cube(0, 48, 64, 64);
-        bipedLeftLegOverlay.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, expansion + 0.25F, true);
-        bipedLeftLegOverlay.setRotationPoint(1.9F, 12.0F, 0.0F);
-        bipedRightLegOverlay = new Cube(0, 32, 64, 64);
-        bipedRightLegOverlay.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, expansion + 0.25F, true);
-        bipedRightLegOverlay.setRotationPoint(-1.9F, 12.0F, 0.0F);
-        bipedBodyOverlay = new Cube(16, 32, 64, 64);
-        bipedBodyOverlay.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, expansion + 0.25F, true);
-        bipedBodyOverlay.setRotationPoint(0.0F, 0.0F, 0.0F);
-        this.armLeft = new Cube(32, 48, 64, 64);
-        this.armLeft.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, expansion, true);
-        this.armLeft.setRotationPoint(5.0F, 2.0F, 0.0F);
-        this.legLeft = new Cube(16, 48, 64, 64);
-        this.legLeft.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, expansion, true);
-        this.legLeft.setRotationPoint(1.9F, 12.0F, 0.0F);
-        head = new Cube(0, 0, 64, 64);
-        head.addBox(-4F, -8F, -4F, 8, 8, 8, expansion, true);
-        head.setRotationPoint(0.0F, 0.0F + yRotOffset, 0.0F);
-        hair = new Cube(32, 0, 64, 64);
-        hair.addBox(-4F, -8F, -4F, 8, 8, 8, expansion + 0.5F, true);
-        hair.setRotationPoint(0.0F, 0.0F + yRotOffset, 0.0F);
-        body = new Cube(16, 16, 64, 64);
-        body.addBox(-4F, 0.0F, -2F, 8, 12, 4, expansion, true);
-        body.setRotationPoint(0.0F, 0.0F + yRotOffset, 0.0F);
-        armRight = new Cube(40, 16, 64, 64);
-        armRight.addBox(-3F, -2F, -2F, 4, 12, 4, expansion, true);
-        armRight.setRotationPoint(-5F, 2.0F + yRotOffset, 0.0F);
-        legRight = new Cube(0, 16, 64, 64);
-        legRight.addBox(-2F, 0.0F, -2F, 4, 12, 4, expansion, true);
-        legRight.setRotationPoint(-2F, 12F + yRotOffset, 0.0F);
-    }
-
-    @Override
-	public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick){
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        head.render(scale);
-        body.render(scale);
-        armRight.render(scale);
-        armLeft.render(scale);
-        legRight.render(scale);
-        legLeft.render(scale);
-        if (mob instanceof Player) {
-            Player player = (Player) mob;
-            if (player.playerConfig.hatEnabled()) hair.render(scale);
-            GL11.glPushMatrix();
-            if (player.playerConfig.sleeveLeftEnabled()) bipedLeftArmOverlay.render(scale);
-            if (player.playerConfig.sleeveRightEnabled()) bipedRightArmOverlay.render(scale);
-            if (player.playerConfig.pantLeftEnabled()) bipedLeftLegOverlay.render(scale);
-            if (player.playerConfig.pantRightEnabled()) bipedRightLegOverlay.render(scale);
-            if (player.playerConfig.jacketEnabled()) bipedBodyOverlay.render(scale);
-            GL11.glPopMatrix();
-        } else {
-            hair.render(scale);
-            GL11.glPushMatrix();
-            bipedLeftArmOverlay.render(scale);
-            bipedRightArmOverlay.render(scale);
-            bipedLeftLegOverlay.render(scale);
-            bipedRightLegOverlay.render(scale);
-            bipedBodyOverlay.render(scale);
-            GL11.glPopMatrix();
-        }
-
-    }
-
-    @Override
-	public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick){
-        super.setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        copyTranslation(this.legLeft, this.bipedLeftLegOverlay);
-        copyTranslation(this.legRight, this.bipedRightLegOverlay);
-        copyTranslation(this.armLeft, this.bipedLeftArmOverlay);
-        copyTranslation(this.armRight, this.bipedRightArmOverlay);
-        copyTranslation(this.body, this.bipedBodyOverlay);
-    }
-
-    public static void copyTranslation(Cube sourceCube, Cube destinationCube)
-    {
-        destinationCube.xRot = sourceCube.xRot;
-        destinationCube.yRot = sourceCube.yRot;
-        destinationCube.zRot = sourceCube.zRot;
-        destinationCube.x = sourceCube.x;
-        destinationCube.y = sourceCube.y;
-        destinationCube.z = sourceCube.z;
-    }
-
-}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayerSlim.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayerSlim.java
deleted file mode 100644
index 12b34f5a5..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelPlayerSlim.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package net.minecraft.client.render.model;
-
-public class ModelPlayerSlim extends ModelPlayer {
-
-    public ModelPlayerSlim(float f) {
-        this(f, 0f);
-    }
-
-    public ModelPlayerSlim(float expansion, float yRotOffset){
-        super(expansion, yRotOffset);
-        bipedLeftArmOverlay = new Cube(48, 48, 64, 64);
-        bipedLeftArmOverlay.addBox(-1.0F, -2.0F, -2.0F, 3, 12, 4, expansion + 0.25F);
-        bipedLeftArmOverlay.setRotationPoint(5.0F, 2.5F, 0.0F);
-        bipedRightArmOverlay = new Cube(40, 32, 64, 64);
-        bipedRightArmOverlay.addBox(-2.0F, -2.0F, -2.0F, 3, 12, 4, expansion + 0.25F);
-        bipedRightArmOverlay.setRotationPoint(-5.0F, 2.5F, 10.0F);
-        armLeft = new Cube(32, 48, 64, 64);
-        armLeft.addBox(-1.0F, -2.0F, -2.0F, 3, 12, 4, expansion);
-        armLeft.setRotationPoint(5.0F, 2.5F, 0.0F);
-        armRight = new Cube(40, 16, 64, 64);
-        armRight.addBox(-2F, -2F, -2F, 3, 12, 4, expansion);
-        armRight.setRotationPoint(-5F, 2.5F + yRotOffset, 0.0F);
-
-    }
-
-}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelQuadruped.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelQuadruped.java
deleted file mode 100644
index be0dda713..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelQuadruped.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelQuadruped extends ModelBase
-{
-    public Cube head;
-    public Cube body;
-    public Cube leg1;
-    public Cube leg2;
-    public Cube leg3;
-    public Cube leg4;
-
-    public ModelQuadruped(int heightOffset, float expand)
-    {
-        head = new Cube(0, 0);
-        head.addBox(-4F, -4F, -8F, 8, 8, 8, expand);
-        head.setRotationPoint(0.0F, 18 - heightOffset, -6F);
-        body = new Cube(28, 8);
-        body.addBox(-5F, -10F, -7F, 10, 16, 8, expand);
-        body.setRotationPoint(0.0F, 17 - heightOffset, 2.0F);
-        leg1 = new Cube(0, 16);
-        leg1.addBox(-2F, 0.0F, -2F, 4, heightOffset, 4, expand);
-        leg1.setRotationPoint(-3F, 24 - heightOffset, 7F);
-        leg2 = new Cube(0, 16);
-        leg2.addBox(-2F, 0.0F, -2F, 4, heightOffset, 4, expand);
-        leg2.setRotationPoint(3F, 24 - heightOffset, 7F);
-        leg3 = new Cube(0, 16);
-        leg3.addBox(-2F, 0.0F, -2F, 4, heightOffset, 4, expand);
-        leg3.setRotationPoint(-3F, 24 - heightOffset, -5F);
-        leg4 = new Cube(0, 16);
-        leg4.addBox(-2F, 0.0F, -2F, 4, heightOffset, 4, expand);
-        leg4.setRotationPoint(3F, 24 - heightOffset, -5F);
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        head.render(scale);
-        body.render(scale);
-        leg1.render(scale);
-        leg2.render(scale);
-        leg3.render(scale);
-        leg4.render(scale);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        head.xRot = headPitch / 57.29578F;
-        head.yRot = headYaw / 57.29578F;
-        body.xRot = MathHelper.PI / 2F;
-        leg1.xRot = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
-        leg2.xRot = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
-        leg3.xRot = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
-        leg4.xRot = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelScorpion.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelScorpion.java
deleted file mode 100644
index 698b7635d..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelScorpion.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-import org.lwjgl.opengl.GL11;
-
-public class ModelScorpion extends ModelBase
-{
-    private final Cube body;
-    private final Cube clawLeft;
-    private final Cube clawRight;
-    private final Cube legLFront;
-    private final Cube legLMid;
-    private final Cube legLBack;
-    private final Cube legRFront;
-    private final Cube legRMid;
-    private final Cube legRBack;
-    private final Cube tail0;
-    private final Cube tail1;
-    private final Cube tail2;
-
-
-    public ModelScorpion()
-    {
-        body = new Cube(0, 0);
-        body.addBox(-2.5F, -4.0F, -5.0F, 5, 3, 10);
-        body.setRotationPoint(0.0F, 0.0F, 0.0F);
-
-        clawLeft = new Cube(20, 0);
-        clawLeft.addBox(1.5F, -3.0F, -10.0F, 3, 2, 6);
-        clawLeft.setRotationPoint(0.0F, 0.0F, 0.0F);
-        clawLeft.setRotationAngle(0.0F, -0.0873F, 0.0F);
-
-        clawRight = new Cube(14, 13);
-        clawRight.addBox(-4.5F, -3.0F, -10.0F, 3, 2, 6);
-        clawRight.setRotationPoint(0.0F, 0.0F, 0.0F);
-        clawRight.setRotationAngle(0.0F, 0.0873F, 0.0F);
-
-        legLFront = new Cube(21, 22);
-        legLFront.addBox(-9.0F, -4.0F, -0.5F, 9, 1, 1);
-        legLFront.setRotationPoint(0.0F, 0.0F, 0.0F);
-        legLFront.setRotationAngle(0.0F, -2.618F, 0.3927F);
-
-        legLMid = new Cube(0, 23);
-        legLMid.addBox(-9.0F, -4.0F, -0.5F, 9, 1, 1);
-        legLMid.setRotationPoint(0.0F, 0.0F, 0.0F);
-        legLMid.setRotationAngle(0.0F, 3.1416F, 0.3927F);
-
-        legLBack = new Cube(0, 25);
-        legLBack.addBox(-9.0F, -4.0F, -0.5F, 9, 1, 1);
-        legLBack.setRotationPoint(0.0F, 0.0F, 0.0F);
-        legLBack.setRotationAngle(0.0F, 2.618F, 0.3927F);
-
-        legRFront = new Cube(21, 22);
-        legRFront.addBox(-9.0F, -4.0F, -0.5F, 9,1, 1);
-        legRFront.setRotationPoint(0.0F, 0.0F, 0.0F);
-        legRFront.setRotationAngle(0.0F, -0.5236F, -0.3927F);
-
-        legRMid = new Cube(0, 25);
-        legRMid.addBox(-9.0F, -4.0F, -0.5F, 9, 1, 1);
-        legRMid.setRotationPoint(0.0F, 0.0F, 0.0F);
-        legRMid.setRotationAngle(0.0F, 0.0F, -0.3927F);
-
-        legRBack = new Cube(19, 24);
-        legRBack.addBox(-9.0F, -4.0F, -0.5F, 9, 1, 1);
-        legRBack.setRotationPoint(0.0F, 0.0F, 0.0F);
-        legRBack.setRotationAngle(0.0F, 0.5236F, -0.3927F);
-
-        tail0 = new Cube(0, 13);
-        tail0.addBox(-1.5F, -1.0F, -4.0F, 3, 2, 8);
-        tail0.setRotationPoint(0.0F, -5.0F, 6.0F);
-        tail0.setRotationAngle(1.0472F, 0.0F, 0.0F);
-
-        tail1 = new Cube(0, 0);
-        tail1.addBox(-1.0F, 2.0F, 2.5F, 2, 6, 2);
-        tail1.setRotationPoint(0.0F, -11.0F, 0.0F);
-        tail1.setRotationAngle(0.7854F, 0.0F, 0.0F);
-
-        tail2 = new Cube(0, 13);
-        tail2.addBox(-1.0F, 0.0F, -1.5F, 2, 4, 1);
-        tail2.setRotationPoint(0.0F, -11.0F, 0.0F);
-        tail2.setRotationAngle(2.138F, 0.0F, 0.0F);
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-
-        GL11.glPushMatrix();
-        GL11.glTranslatef(0, 1.4F, 0);
-
-        body.render(scale);
-        clawLeft.render(scale);
-        clawRight.render(scale);
-        legLFront.render(scale);
-        legLMid.render(scale);
-        legLBack.render(scale);
-        legRFront.render(scale);
-        legRMid.render(scale);
-        legRBack.render(scale);
-        tail0.render(scale);
-        tail1.render(scale);
-        tail2.render(scale);
-        GL11.glPopMatrix();
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        legLFront.setRotationAngle(0.0F, -2.618F, 0.3927F);
-        legLMid.setRotationAngle(0.0F, 3.1416F, 0.3927F);
-        legLBack.setRotationAngle(0.0F, 2.618F, 0.3927F);
-        legRFront.setRotationAngle(0.0F, -0.5236F, -0.3927F);
-        legRMid.setRotationAngle(0.0F, 0.0F, -0.3927F);
-        legRBack.setRotationAngle(0.0F, 0.5236F, -0.3927F);
-
-        float pair1Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + 0.0F) * 0.4F) * limbYaw;
-        float pair2Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI) * 0.4F) * limbYaw;
-        float pair3Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI / 2F) * 0.4F) * limbYaw;
-
-        legLFront.yRot += pair1Y;
-        legLBack.yRot -= pair1Y;
-
-        legRFront.yRot -= pair2Y;
-        legRBack.yRot += pair2Y;
-
-        legLMid.yRot += pair3Y;
-        legRMid.yRot -= pair3Y;
-    }
-}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelSheep.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelSheep.java
deleted file mode 100644
index b93762537..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelSheep.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.animal.MobSheep;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelSheep extends ModelQuadruped
-{
-    boolean isEatingAnimPlaying;
-    float headBobTime;
-
-    public ModelSheep()
-    {
-        super(12, 0.0F);
-        head = new Cube(0, 0);
-        head.addBox(-3F, -4F, -6F, 6, 6, 8, 0.0F);
-        head.setRotationPoint(0.0F, 6F, -8F);
-        body = new Cube(28, 8);
-        body.addBox(-4F, -10F, -7F, 8, 16, 6, 0.0F);
-        body.setRotationPoint(0.0F, 5F, 2.0F);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        super.setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        float desiredRotateAngleX = headPitch / 57.29578F;
-        float desiredRotateAngleY = headYaw / 57.29578F;
-        // handles head rotation
-        if(isEatingAnimPlaying)
-        {
-            // begin tilting head down
-            if (headBobTime < 5)
-            {
-                float partPercentage = headBobTime / 5;
-                head.xRot = (desiredRotateAngleX * (1 - partPercentage)) + (1.0472f * partPercentage);
-                head.yRot = (desiredRotateAngleY * (1 - partPercentage));
-            }
-            //hold head in tilted position
-            else if (headBobTime < 35)
-            {
-                head.xRot = 1.0472f;
-                head.yRot = 0;
-            }
-            // bring head up to normal rotation again
-            else if (headBobTime < 40)
-            {
-                float partPercentage = (headBobTime - 35) / 5;
-                head.xRot = (desiredRotateAngleX * partPercentage) + (1.0472f * (1 - partPercentage));
-                head.yRot = desiredRotateAngleY * partPercentage;
-            }
-        }
-        else
-        {
-            // normal head rotations
-            head.xRot = desiredRotateAngleX;
-            head.yRot = desiredRotateAngleY;
-        }
-
-        if (mob != null) {
-            MobSheep entitySheep = (MobSheep) mob;
-            head.y = 6F;
-            isEatingAnimPlaying = false;
-            if(entitySheep.getIsSheepEating())
-            {
-                headBobTime = entitySheep.prevTimeSheepEating + (entitySheep.timeSheepEating - entitySheep.prevTimeSheepEating) * partialTick;
-                isEatingAnimPlaying = true;
-
-                // Move head down
-                if (headBobTime < 5)
-                {
-                    head.y = 6 + (10 / 5f) * (headBobTime + 1);
-                }
-                // Hold head down and bob
-                else if (headBobTime < 35)
-                {
-                    head.y = 16 + MathHelper.sin((headBobTime * 0.05f) * 30.5f) / 3f;
-                }
-                // Bring head back up
-                else if (headBobTime < 40)
-                {
-                    head.y = 16f - ((10 / 5f) * (headBobTime - 34));
-                }
-            }
-            else
-            {
-                headBobTime = 0;
-            }
-        }
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelSheepOverlay.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelSheepOverlay.java
deleted file mode 100644
index 18ab1b0e9..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelSheepOverlay.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.core.Global;
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.animal.MobSheep;
-import org.jetbrains.annotations.Nullable;
-import org.lwjgl.opengl.GL11;
-
-public class ModelSheepOverlay extends ModelSheep
-{
-
-    public ModelSheepOverlay()
-    {
-        super();
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        super.setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        if (mob != null) {
-            float brightness = mob.getBrightness(limbSwing);
-            if (Global.accessor.isFullbrightEnabled() || LightmapHelper.isLightmapEnabled()) brightness = 1.0f;
-            int j = ((MobSheep)mob).getFleeceColor().blockMeta;
-            GL11.glColor3f(brightness * MobSheep.FLEECE_COLOR_TABLE[j][0], brightness * MobSheep.FLEECE_COLOR_TABLE[j][1], brightness * MobSheep.FLEECE_COLOR_TABLE[j][2]);
-        }
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelSheepWool.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelSheepWool.java
deleted file mode 100644
index 1a7d667ff..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelSheepWool.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package net.minecraft.client.render.model;
-
-public class ModelSheepWool extends ModelSheep
-{
-
-    public ModelSheepWool()
-    {
-        head = new Cube(0, 0);
-        head.addBox(-3F, -4F, -4F, 6, 6, 6, 0.6F);
-        head.setRotationPoint(0.0F, 6F, -8F);
-        body = new Cube(28, 8);
-        body.addBox(-4F, -10F, -7F, 8, 16, 6, 1.75F);
-        body.setRotationPoint(0.0F, 5F, 2.0F);
-        float f = 0.5F;
-        leg1 = new Cube(0, 16);
-        leg1.addBox(-2F, 0.0F, -2F, 4, 6, 4, f);
-        leg1.setRotationPoint(-3F, 12F, 7F);
-        leg2 = new Cube(0, 16);
-        leg2.addBox(-2F, 0.0F, -2F, 4, 6, 4, f);
-        leg2.setRotationPoint(3F, 12F, 7F);
-        leg3 = new Cube(0, 16);
-        leg3.addBox(-2F, 0.0F, -2F, 4, 6, 4, f);
-        leg3.setRotationPoint(-3F, 12F, -5F);
-        leg4 = new Cube(0, 16);
-        leg4.addBox(-2F, 0.0F, -2F, 4, 6, 4, f);
-        leg4.setRotationPoint(3F, 12F, -5F);
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelSign.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelSign.java
deleted file mode 100644
index c1c78edf7..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelSign.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package net.minecraft.client.render.model;
-
-public class ModelSign
-{
-
-    public ModelSign()
-    {
-        signBoard = new Cube(0, 0);
-        signBoard.addBox(-12F, -14F, -1F, 24, 12, 2, 0.0F);
-        signStick = new Cube(0, 14);
-        signStick.addBox(-1F, -2F, -1F, 2, 14, 2, 0.0F);
-    }
-
-    public void render()
-    {
-        signBoard.render(0.0625F);
-        signStick.render(0.0625F);
-    }
-
-    public Cube signBoard;
-    public Cube signStick;
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelSkeleton.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelSkeleton.java
deleted file mode 100644
index 975fad5cd..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelSkeleton.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package net.minecraft.client.render.model;
-
-public class ModelSkeleton extends ModelZombie
-{
-
-    public ModelSkeleton()
-    {
-        float f = 0.0F;
-        armRight = new Cube(40, 16);
-        armRight.addBox(-1F, -2F, -1F, 2, 12, 2, f);
-        armRight.setRotationPoint(-5F, 2.0F, 0.0F);
-        armLeft = new Cube(40, 16);
-        armLeft.mirror = true;
-        armLeft.addBox(-1F, -2F, -1F, 2, 12, 2, f);
-        armLeft.setRotationPoint(5F, 2.0F, 0.0F);
-        legRight = new Cube(0, 16);
-        legRight.addBox(-1F, 0.0F, -1F, 2, 12, 2, f);
-        legRight.setRotationPoint(-2F, 12F, 0.0F);
-        legLeft = new Cube(0, 16);
-        legLeft.mirror = true;
-        legLeft.addBox(-1F, 0.0F, -1F, 2, 12, 2, f);
-        legLeft.setRotationPoint(2.0F, 12F, 0.0F);
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelSlime.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelSlime.java
deleted file mode 100644
index 0523296a3..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelSlime.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelSlime extends ModelBase
-{
-    Cube slimeBodies;
-    Cube slimeRightEye;
-    Cube slimeLeftEye;
-    Cube slimeMouth;
-
-    public ModelSlime(int i)
-    {
-        slimeBodies = new Cube(0, i);
-        slimeBodies.addBox(-4F, 16F, -4F, 8, 8, 8);
-        if(i > 0)
-        {
-            slimeBodies = new Cube(0, i);
-            slimeBodies.addBox(-3F, 17F, -3F, 6, 6, 6);
-            slimeRightEye = new Cube(32, 0);
-            slimeRightEye.addBox(-3.25F, 18F, -3.5F, 2, 2, 2);
-            slimeLeftEye = new Cube(32, 4);
-            slimeLeftEye.addBox(1.25F, 18F, -3.5F, 2, 2, 2);
-            slimeMouth = new Cube(32, 8);
-            slimeMouth.addBox(0.0F, 21F, -3.5F, 1, 1, 1);
-        }
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        slimeBodies.render(scale);
-        if(slimeRightEye != null)
-        {
-            slimeRightEye.render(scale);
-            slimeLeftEye.render(scale);
-            slimeMouth.render(scale);
-        }
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelSpider.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelSpider.java
deleted file mode 100644
index d79e9e19c..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelSpider.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelSpider extends ModelBase
-{
-    public Cube spiderHead;
-    public Cube spiderNeck;
-    public Cube spiderBody;
-    public Cube spiderLeg1;
-    public Cube spiderLeg2;
-    public Cube spiderLeg3;
-    public Cube spiderLeg4;
-    public Cube spiderLeg5;
-    public Cube spiderLeg6;
-    public Cube spiderLeg7;
-    public Cube spiderLeg8;
-
-
-    public ModelSpider(float expandAmount)
-    {
-        int yOff = 15;
-        spiderHead = new Cube(32, 4);
-        spiderHead.addBox(-4F, -4F, -8F, 8, 8, 8, expandAmount);
-        spiderHead.setRotationPoint(0.0F, yOff, -3F);
-        spiderNeck = new Cube(0, 0);
-        spiderNeck.addBox(-3F, -3F, -3F, 6, 6, 6, expandAmount);
-        spiderNeck.setRotationPoint(0.0F, yOff, 0.0F);
-        spiderBody = new Cube(0, 12);
-        spiderBody.addBox(-5F, -4F, -6F, 10, 8, 12, expandAmount);
-        spiderBody.setRotationPoint(0.0F, yOff, 9F);
-        spiderLeg1 = new Cube(18, 0);
-        spiderLeg1.addBox(-15F, -1F, -1F, 16, 2, 2, expandAmount);
-        spiderLeg1.setRotationPoint(-4F, yOff, 2.0F);
-        spiderLeg2 = new Cube(18, 0);
-        spiderLeg2.addBox(-1F, -1F, -1F, 16, 2, 2, expandAmount);
-        spiderLeg2.setRotationPoint(4F, yOff, 2.0F);
-        spiderLeg3 = new Cube(18, 0);
-        spiderLeg3.addBox(-15F, -1F, -1F, 16, 2, 2, expandAmount);
-        spiderLeg3.setRotationPoint(-4F, yOff, 1.0F);
-        spiderLeg4 = new Cube(18, 0);
-        spiderLeg4.addBox(-1F, -1F, -1F, 16, 2, 2, expandAmount);
-        spiderLeg4.setRotationPoint(4F, yOff, 1.0F);
-        spiderLeg5 = new Cube(18, 0);
-        spiderLeg5.addBox(-15F, -1F, -1F, 16, 2, 2, expandAmount);
-        spiderLeg5.setRotationPoint(-4F, yOff, 0.0F);
-        spiderLeg6 = new Cube(18, 0);
-        spiderLeg6.addBox(-1F, -1F, -1F, 16, 2, 2, expandAmount);
-        spiderLeg6.setRotationPoint(4F, yOff, 0.0F);
-        spiderLeg7 = new Cube(18, 0);
-        spiderLeg7.addBox(-15F, -1F, -1F, 16, 2, 2, expandAmount);
-        spiderLeg7.setRotationPoint(-4F, yOff, -1F);
-        spiderLeg8 = new Cube(18, 0);
-        spiderLeg8.addBox(-1F, -1F, -1F, 16, 2, 2, expandAmount);
-        spiderLeg8.setRotationPoint(4F, yOff, -1F);
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        spiderHead.render(scale);
-        spiderNeck.render(scale);
-        spiderBody.render(scale);
-        spiderLeg1.render(scale);
-        spiderLeg2.render(scale);
-        spiderLeg3.render(scale);
-        spiderLeg4.render(scale);
-        spiderLeg5.render(scale);
-        spiderLeg6.render(scale);
-        spiderLeg7.render(scale);
-        spiderLeg8.render(scale);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        spiderHead.yRot = headYaw / 57.29578F;
-        spiderHead.xRot = headPitch / 57.29578F;
-        float f6 = 0.7853982F;
-        spiderLeg1.zRot = -f6;
-        spiderLeg2.zRot = f6;
-        spiderLeg3.zRot = -f6 * 0.74F;
-        spiderLeg4.zRot = f6 * 0.74F;
-        spiderLeg5.zRot = -f6 * 0.74F;
-        spiderLeg6.zRot = f6 * 0.74F;
-        spiderLeg7.zRot = -f6;
-        spiderLeg8.zRot = f6;
-        float f7 = -0F;
-        float f8 = 0.3926991F;
-        spiderLeg1.yRot = f8 * 2.0F + f7;
-        spiderLeg2.yRot = -f8 * 2.0F - f7;
-        spiderLeg3.yRot = f8 + f7;
-        spiderLeg4.yRot = -f8 - f7;
-        spiderLeg5.yRot = -f8 + f7;
-        spiderLeg6.yRot = f8 - f7;
-        spiderLeg7.yRot = -f8 * 2.0F + f7;
-        spiderLeg8.yRot = f8 * 2.0F - f7;
-        float pair1Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + 0.0F) * 0.4F) * limbYaw;
-        float pair2Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI) * 0.4F) * limbYaw;
-        float pair3Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI / 2F) * 0.4F) * limbYaw;
-        float pair4Y = -(MathHelper.cos(limbSwing * 0.6662F * 2.0F + MathHelper.PI * 1.5F) * 0.4F) * limbYaw;
-        float pair1Z = Math.abs(MathHelper.sin(limbSwing * 0.6662F + 0.0F) * 0.4F) * limbYaw;
-        float pair2Z = Math.abs(MathHelper.sin(limbSwing * 0.6662F + MathHelper.PI) * 0.4F) * limbYaw;
-        float pair3Z = Math.abs(MathHelper.sin(limbSwing * 0.6662F + MathHelper.PI / 2F) * 0.4F) * limbYaw;
-        float pair4Z = Math.abs(MathHelper.sin(limbSwing * 0.6662F + MathHelper.PI * 1.5F) * 0.4F) * limbYaw;
-        spiderLeg1.yRot += pair1Y;
-        spiderLeg2.yRot += -pair1Y;
-        spiderLeg3.yRot += pair2Y;
-        spiderLeg4.yRot += -pair2Y;
-        spiderLeg5.yRot += pair3Y;
-        spiderLeg6.yRot += -pair3Y;
-        spiderLeg7.yRot += pair4Y;
-        spiderLeg8.yRot += -pair4Y;
-        spiderLeg1.zRot += pair1Z;
-        spiderLeg2.zRot += -pair1Z;
-        spiderLeg3.zRot += pair2Z;
-        spiderLeg4.zRot += -pair2Z;
-        spiderLeg5.zRot += pair3Z;
-        spiderLeg6.zRot += -pair3Z;
-        spiderLeg7.zRot += pair4Z;
-        spiderLeg8.zRot += -pair4Z;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelSquid.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelSquid.java
deleted file mode 100644
index e17a19cd1..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelSquid.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelSquid extends ModelBase
-{
-    Cube squidBody;
-    Cube[] squidTentacles;
-
-    public ModelSquid()
-    {
-        squidTentacles = new Cube[8];
-        byte yOffs = -16;
-        squidBody = new Cube(0, 0);
-        squidBody.addBox(-6F, -8F, -6F, 12, 16, 12);
-        squidBody.y += 24 + yOffs;
-        for(int i = 0; i < squidTentacles.length; i++)
-        {
-            squidTentacles[i] = new Cube(48, 0);
-            double angle = ((double)i * Math.PI * 2D) / (double)squidTentacles.length;
-            float xo = (float)Math.cos(angle) * 5F;
-            float yo = (float)Math.sin(angle) * 5F;
-            squidTentacles[i].addBox(-1F, 0.0F, -1F, 2, 18, 2);
-            squidTentacles[i].x = xo;
-            squidTentacles[i].z = yo;
-            squidTentacles[i].y = 31 + yOffs;
-            angle = ((double)i * Math.PI * -2D) / (double)squidTentacles.length + (Math.PI/2);
-            squidTentacles[i].yRot = (float)angle;
-        }
-
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        for(int i = 0; i < squidTentacles.length; i++)
-        {
-            squidTentacles[i].xRot = limbPitch;
-        }
-
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        squidBody.render(scale);
-        for(int i = 0; i < squidTentacles.length; i++)
-        {
-            squidTentacles[i].render(scale);
-        }
-
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelWolf.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelWolf.java
deleted file mode 100644
index 235e47e49..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelWolf.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.core.Global;
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.entity.animal.MobWolf;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-import org.lwjgl.opengl.GL11;
-
-public class ModelWolf extends ModelBase
-{
-
-    public Cube wolfHeadMain;
-    public Cube wolfBody;
-    public Cube wolfLeg1;
-    public Cube wolfLeg2;
-    public Cube wolfLeg3;
-    public Cube wolfLeg4;
-    Cube wolfRightEar;
-    Cube wolfLeftEar;
-    Cube wolfSnout;
-    Cube wolfTail;
-    Cube wolfMane;
-
-    public ModelWolf(float expandAmount)
-    {
-        float f1 = 13.5F;
-        wolfHeadMain = new Cube(0, 0);
-        wolfHeadMain.addBox(-3F, -3F, -2F, 6, 6, 4, expandAmount);
-        wolfHeadMain.setRotationPoint(-1F, f1, -7F);
-        wolfBody = new Cube(18, 14);
-        wolfBody.addBox(-4F, -2F, -3F, 6, 9, 6, expandAmount);
-        wolfBody.setRotationPoint(0.0F, 14F, 2.0F);
-        wolfMane = new Cube(21, 0);
-        wolfMane.addBox(-4F, -3F, -3F, 8, 6, 7, expandAmount);
-        wolfMane.setRotationPoint(-1F, 14F, 2.0F);
-        wolfLeg1 = new Cube(0, 18);
-        wolfLeg1.addBox(-1F, 0.0F, -1F, 2, 8, 2, expandAmount);
-        wolfLeg1.setRotationPoint(-2.5F, 16F, 7F);
-        wolfLeg2 = new Cube(0, 18);
-        wolfLeg2.addBox(-1F, 0.0F, -1F, 2, 8, 2, expandAmount);
-        wolfLeg2.setRotationPoint(0.5F, 16F, 7F);
-        wolfLeg3 = new Cube(0, 18);
-        wolfLeg3.addBox(-1F, 0.0F, -1F, 2, 8, 2, expandAmount);
-        wolfLeg3.setRotationPoint(-2.5F, 16F, -4F);
-        wolfLeg4 = new Cube(0, 18);
-        wolfLeg4.addBox(-1F, 0.0F, -1F, 2, 8, 2, expandAmount);
-        wolfLeg4.setRotationPoint(0.5F, 16F, -4F);
-        wolfTail = new Cube(9, 18);
-        wolfTail.addBox(-1F, 0.0F, -1F, 2, 8, 2, expandAmount);
-        wolfTail.setRotationPoint(-1F, 12F, 8F);
-        wolfRightEar = new Cube(16, 14);
-        wolfRightEar.addBox(-3F, -5F, 0.0F, 2, 2, 1, expandAmount);
-        wolfRightEar.setRotationPoint(-1F, f1, -7F);
-        wolfLeftEar = new Cube(16, 14);
-        wolfLeftEar.addBox(1.0F, -5F, 0.0F, 2, 2, 1, expandAmount);
-        wolfLeftEar.setRotationPoint(-1F, f1, -7F);
-        wolfSnout = new Cube(0, 10);
-        wolfSnout.addBox(-2F, 0.0F, -5F, 3, 3, 4, expandAmount);
-        wolfSnout.setRotationPoint(-0.5F, f1, -7F);
-    }
-
-    @Override
-    public void render(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        wolfHeadMain.renderWithRotation(scale);
-        wolfBody.render(scale);
-        wolfLeg1.render(scale);
-        wolfLeg2.render(scale);
-        wolfLeg3.render(scale);
-        wolfLeg4.render(scale);
-        wolfRightEar.renderWithRotation(scale);
-        wolfLeftEar.renderWithRotation(scale);
-        wolfSnout.renderWithRotation(scale);
-        wolfTail.renderWithRotation(scale);
-        wolfMane.render(scale);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick)
-    {
-        if (mob == null) return;
-        MobWolf wolf = (MobWolf) mob;
-        if(wolf.isWolfAngry())
-        {
-            wolfTail.yRot = 0.0F;
-        } else
-        {
-            wolfTail.yRot = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
-        }
-        if(wolf.isWolfSitting())
-        {
-            wolfMane.setRotationPoint(-1F, 16F, -3F);
-            wolfMane.xRot = 1.256637F;
-            wolfMane.yRot = 0.0F;
-            wolfBody.setRotationPoint(0.0F, 18F, 0.0F);
-            wolfBody.xRot = 0.7853982F;
-            wolfTail.setRotationPoint(-1F, 21F, 6F);
-            wolfLeg1.setRotationPoint(-2.5F, 22F, 2.0F);
-            wolfLeg1.xRot = MathHelper.PI * 1.5F;
-            wolfLeg2.setRotationPoint(0.5F, 22F, 2.0F);
-            wolfLeg2.xRot = MathHelper.PI * 1.5F;
-            wolfLeg3.xRot = 5.811947F;
-            wolfLeg3.setRotationPoint(-2.49F, 17F, -4F);
-            wolfLeg4.xRot = 5.811947F;
-            wolfLeg4.setRotationPoint(0.51F, 17F, -4F);
-        } else
-        {
-            wolfBody.setRotationPoint(0.0F, 14F, 2.0F);
-            wolfBody.xRot = MathHelper.PI / 2F;
-            wolfMane.setRotationPoint(-1F, 14F, -3F);
-            wolfMane.xRot = wolfBody.xRot;
-            wolfTail.setRotationPoint(-1F, 12F, 8F);
-            wolfLeg1.setRotationPoint(-2.5F, 16F, 7F);
-            wolfLeg2.setRotationPoint(0.5F, 16F, 7F);
-            wolfLeg3.setRotationPoint(-2.5F, 16F, -4F);
-            wolfLeg4.setRotationPoint(0.5F, 16F, -4F);
-            wolfLeg1.xRot = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
-            wolfLeg2.xRot = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
-            wolfLeg3.xRot = MathHelper.cos(limbSwing * 0.6662F + MathHelper.PI) * 1.4F * limbYaw;
-            wolfLeg4.xRot = MathHelper.cos(limbSwing * 0.6662F) * 1.4F * limbYaw;
-        }
-        float f3 = wolf.getInterestedAngle(partialTick) + wolf.getShakeAngle(partialTick, 0.0F);
-        wolfHeadMain.zRot = f3;
-        wolfRightEar.zRot = f3;
-        wolfLeftEar.zRot = f3;
-        wolfSnout.zRot = f3;
-        wolfMane.zRot = wolf.getShakeAngle(partialTick, -0.08F);
-        wolfBody.zRot = wolf.getShakeAngle(partialTick, -0.16F);
-        wolfTail.zRot = wolf.getShakeAngle(partialTick, -0.2F);
-
-        if(wolf.getWolfShaking())
-        {
-            float brightness = 1.0f;
-            if(LightmapHelper.isLightmapEnabled()) {
-            	LightmapHelper.setLightmapCoord(wolf.getLightmapCoord(partialTick));
-            }else if(Global.accessor.isFullbrightEnabled()) {
-
-            }else {
-            	brightness = wolf.getBrightness(partialTick);
-            }
-            float f4 = brightness * wolf.getShadingWhileShaking(partialTick);
-            GL11.glColor3f(f4, f4, f4);
-        }
-
-
-        wolfHeadMain.xRot = headPitch / 57.29578F;
-        wolfHeadMain.yRot = headYaw / 57.29578F;
-        wolfRightEar.yRot = wolfHeadMain.yRot;
-        wolfRightEar.xRot = wolfHeadMain.xRot;
-        wolfLeftEar.yRot = wolfHeadMain.yRot;
-        wolfLeftEar.xRot = wolfHeadMain.xRot;
-        wolfSnout.yRot = wolfHeadMain.yRot;
-        wolfSnout.xRot = wolfHeadMain.xRot;
-        wolfTail.xRot = limbPitch;
-    }
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelZombie.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelZombie.java
deleted file mode 100644
index 75b7c6de8..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelZombie.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelZombie extends ModelBiped {
-    public ModelZombie() {
-        this(0.0F);
-    }
-
-    public ModelZombie(float var1) {
-        this.parts(var1, 0.0F);
-    }
-
-    public void parts(float expansion, float var2) {
-        this.holdingLeftHand = false;
-        this.holdingRightHand = false;
-        this.sneaking = false;
-        this.cloak = new Cube(0, 0);
-        this.cloak.addBox(-5.0F, 0.0F, -1.0F, 10, 16, 1, expansion);
-        this.ear = new Cube(24, 0);
-        this.ear.addBox(-4.0F, -7.0F, -1.0F, 7, 7, 1, expansion);
-        this.head = new Cube(0, 0);
-        this.head.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, expansion);
-        this.head.setRotationPoint(0.0F, 0.0F + var2, 0.0F);
-        this.hair = new Cube(32, 0);
-        this.hair.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, expansion + 0.5F);
-        this.hair.setRotationPoint(0.0F, 0.0F + var2, 0.0F);
-        this.body = new Cube(16, 16);
-        this.body.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, expansion);
-        this.body.setRotationPoint(0.0F, 0.0F + var2, 0.0F);
-        this.armRight = new Cube(40, 16);
-        this.armRight.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, expansion);
-        this.armRight.setRotationPoint(-5.0F, 2.0F + var2, 0.0F);
-        this.armLeft = new Cube(40, 16);
-        this.armLeft.mirror = true;
-        this.armLeft.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, expansion);
-        this.armLeft.setRotationPoint(5.0F, 2.0F + var2, 0.0F);
-        this.legRight = new Cube(0, 16);
-        this.legRight.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, expansion);
-        this.legRight.setRotationPoint(-2.0F, 12.0F + var2, 0.0F);
-        this.legLeft = new Cube(0, 16);
-        this.legLeft.mirror = true;
-        this.legLeft.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, expansion);
-        this.legLeft.setRotationPoint(2.0F, 12.0F + var2, 0.0F);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick) {
-        super.setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        float var7 = MathHelper.sin(this.swingProgress * 3.1415927F);
-        float var8 = MathHelper.sin((1.0F - (1.0F - this.swingProgress) * (1.0F - this.swingProgress)) * 3.1415927F);
-        this.armRight.zRot = 0.0F;
-        this.armLeft.zRot = 0.0F;
-        this.armRight.yRot = -(0.1F - var7 * 0.6F);
-        this.armLeft.yRot = 0.1F - var7 * 0.6F;
-        this.armRight.xRot = -1.5707964F;
-        this.armLeft.xRot = -1.5707964F;
-        this.armRight.xRot -= var7 * 1.2F - var8 * 0.4F;
-        this.armLeft.xRot -= var7 * 1.2F - var8 * 0.4F;
-        this.armRight.zRot += MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
-        this.armLeft.zRot -= MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
-        this.armRight.xRot += MathHelper.sin(limbPitch * 0.067F) * 0.05F;
-        this.armLeft.xRot -= MathHelper.sin(limbPitch * 0.067F) * 0.05F;
-    }
-}
\ No newline at end of file
diff --git a/game/client/src/main/java/net/minecraft/client/render/model/ModelZombiePigman.java b/game/client/src/main/java/net/minecraft/client/render/model/ModelZombiePigman.java
deleted file mode 100644
index 9473fced1..000000000
--- a/game/client/src/main/java/net/minecraft/client/render/model/ModelZombiePigman.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package net.minecraft.client.render.model;
-
-import net.minecraft.core.entity.Mob;
-import net.minecraft.core.util.helper.MathHelper;
-import org.jetbrains.annotations.Nullable;
-
-public class ModelZombiePigman extends ModelPigman {
-    public ModelZombiePigman() {
-        this(0.0F);
-    }
-
-    public ModelZombiePigman(float var1) {
-        this.parts(var1, 0.0F);
-    }
-
-    public void parts(float var1, float var2) {
-        this.holdingLeftHand = false;
-        this.holdingRightHand = false;
-        this.sneaking = false;
-        this.cloak = new Cube(0, 0);
-        this.cloak.addBox(-5.0F, 0.0F, -1.0F, 10, 16, 1, var1);
-        this.ear = new Cube(24, 0);
-        this.ear.addBox(-4.0F, -7.0F, -1.0F, 7, 7, 1, var1);
-        this.head = new Cube(0, 0);
-        this.head.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, var1);
-        this.head.setRotationPoint(0.0F, 0.0F + var2, 0.0F);
-        this.hair = new Cube(32, 0);
-        this.hair.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, var1 + 0.5F);
-        this.hair.setRotationPoint(0.0F, 0.0F + var2, 0.0F);
-        this.body = new Cube(16, 16);
-        this.body.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, var1);
-        this.body.setRotationPoint(0.0F, 0.0F + var2, 0.0F);
-        this.armRight = new Cube(40, 16);
-        this.armRight.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, var1);
-        this.armRight.setRotationPoint(-5.0F, 2.0F + var2, 0.0F);
-        this.armLeft = new Cube(40, 16);
-        this.armLeft.mirror = true;
-        this.armLeft.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, var1);
-        this.armLeft.setRotationPoint(5.0F, 2.0F + var2, 0.0F);
-        this.legRight = new Cube(0, 16);
-        this.legRight.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, var1);
-        this.legRight.setRotationPoint(-2.0F, 12.0F + var2, 0.0F);
-        this.legLeft = new Cube(0, 16);
-        this.legLeft.mirror = true;
-        this.legLeft.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, var1);
-        this.legLeft.setRotationPoint(2.0F, 12.0F + var2, 0.0F);
-    }
-
-    @Override
-    public void setupAnimation(@Nullable Mob mob, float limbSwing, float limbYaw, float limbPitch, float headYaw, float headPitch, float scale, float partialTick) {
-        super.setupAnimation(mob, limbSwing, limbYaw, limbPitch, headYaw, headPitch, scale, partialTick);
-        float var7 = MathHelper.sin(this.swingProgress * 3.1415927F);
-        float var8 = MathHelper.sin((1.0F - (1.0F - this.swingProgress) * (1.0F - this.swingProgress)) * 3.1415927F);
-        this.armRight.zRot = 0.0F;
-        this.armLeft.zRot = 0.0F;
-        this.armRight.yRot = -(0.1F - var7 * 0.6F);
-        this.armLeft.yRot = 0.1F - var7 * 0.6F;
-        this.armRight.xRot = -1.5707964F;
-        this.armLeft.xRot = -1.5707964F;
-        this.armRight.xRot -= var7 * 1.2F - var8 * 0.4F;
-        this.armLeft.xRot -= var7 * 1.2F - var8 * 0.4F;
-        this.armRight.zRot += MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
-        this.armLeft.zRot -= MathHelper.cos(limbPitch * 0.09F) * 0.05F + 0.05F;
-        this.armRight.xRot += MathHelper.sin(limbPitch * 0.067F) * 0.05F;
-        this.armLeft.xRot -= MathHelper.sin(limbPitch * 0.067F) * 0.05F;
-    }
-
-}
diff --git a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
index 2df4fc084..d7749fae6 100644
--- a/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
+++ b/game/client/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
@@ -4,11 +4,14 @@ import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.keyboard.KeyboardLayout;
+import net.minecraft.client.render.EntityRenderDispatcher;
+import net.minecraft.client.render.TileEntityRenderDispatcher;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
 import net.minecraft.client.sound.SoundRepository;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
+import org.useless.dragonfly.data.entity.mojang.EntityGeometryMojangData;
 
 import java.io.File;
 import java.io.IOException;
@@ -103,6 +106,9 @@ public class TexturePackList
 		SoundRepository.reload();
 		BlockModelDispatcher.getInstance().reload();
 		ItemModelDispatcher.getInstance().reload();
+		EntityGeometryMojangData.Cache.reload(this);
+		EntityRenderDispatcher.instance.reload();
+		TileEntityRenderDispatcher.instance.reload();
 		KeyboardLayout.defaultLayout = new KeyboardLayout();
 		TooltipElement.reloadStyles(this);
 	}
diff --git a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRenderer.java b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRenderer.java
index 4bb35ed7d..be25210ee 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRenderer.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRenderer.java
@@ -5,10 +5,21 @@ import net.minecraft.client.render.TileEntityRenderDispatcher;
 import net.minecraft.client.render.font.FontRenderer;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.entity.TileEntity;
+import net.minecraft.core.block.entity.TileEntityDispatcher;
+import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.world.World;
+import org.jetbrains.annotations.NotNull;
+import org.useless.dragonfly.data.entity.mojang.EntityGeometryMojangData;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
+import java.util.HashMap;
+import java.util.Map;
 
 public abstract class TileEntityRenderer<T extends TileEntity>
 {
+    private final @NotNull Map<@NotNull String, @NotNull StaticEntityModel> modelMap = new HashMap<>();
+    protected TileEntityRenderDispatcher renderDispatcher = null;
+    protected Class<? extends T> appliedClass = null;
 
     public TileEntityRenderer()
     {
@@ -17,26 +28,45 @@ public abstract class TileEntityRenderer<T extends TileEntity>
     public abstract void doRender(Tessellator tessellator, T tileEntity, double x, double y, double z,
                                   float partialTick);
 
-    protected void loadTexture(String texturePath)
+    protected void bindTexture(final String texturePath)
     {
-        TextureManager textureManager = renderDispatcher.textureManager;
+        final TextureManager textureManager = this.renderDispatcher.textureManager;
         textureManager.bindTexture(textureManager.loadTexture(texturePath));
     }
 
-    public void setRenderDispatcher(TileEntityRenderDispatcher renderDispatcher)
+    public void init(@NotNull final Class<? extends T> appliedClass, final @NotNull TileEntityRenderDispatcher renderDispatcher)
     {
         this.renderDispatcher = renderDispatcher;
+        this.appliedClass = appliedClass;
     }
 
-    public void onWorldChanged(World world)
+    public void onWorldChanged(final World world)
     {
     }
 
+    protected @NotNull StaticEntityModel getModel(@NotNull final String localId) {
+        StaticEntityModel model = this.modelMap.get(localId);
+        if (model != null) {
+            return model;
+        }
+        final NamespaceID id = TileEntityDispatcher.getIDFromClass(this.appliedClass);
+        if (id != null) {
+            model = EntityGeometryMojangData.Cache.getModelForEntity(id, localId);
+        } else {
+            model = EntityGeometryMojangData.Cache.getFallbackModel();
+        }
+        this.modelMap.put(localId, model);
+        return model;
+    }
+
+    public final @NotNull TileEntityRenderer<T> setModel(@NotNull final String localId, @NotNull final String modelId, final double inflation) {
+        this.modelMap.put(localId, EntityGeometryMojangData.Cache.getModel(modelId, inflation));
+        return this;
+    }
+
 
     public FontRenderer getFont()
     {
-        return renderDispatcher.getFont();
+        return this.renderDispatcher.getFont();
     }
-
-    protected TileEntityRenderDispatcher renderDispatcher;
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererFlag.java b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererFlag.java
index 3e5d6e048..8f049ddda 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererFlag.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererFlag.java
@@ -2,101 +2,94 @@ package net.minecraft.client.render.tileentity;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.FlagRenderer;
-import net.minecraft.client.render.model.ModelFlag;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.TileEntityFlag;
 
+import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.wind.WindProvider;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
 
 public class TileEntityRendererFlag extends TileEntityRenderer<TileEntityFlag>
 {
 
-	public final Minecraft mc = Minecraft.getMinecraft();
-    private final ModelFlag modelFlag;
-    private final ModelFlag modelFlagMirrored;
-    private static FlagRenderer flagRenderer = null;
-    
-    public TileEntityRendererFlag()
-    {
-        modelFlag = new ModelFlag(false);
-        modelFlagMirrored = new ModelFlag(true);
+    private final @NotNull FlagRenderer flagRenderer = new FlagRenderer(Minecraft.getMinecraft().textureManager);
+    public final Minecraft mc = Minecraft.getMinecraft();
+
+    public TileEntityRendererFlag() {
+        super();
     }
 
     @Override
-    public void doRender(Tessellator tessellator, TileEntityFlag tileEntity, double x, double y, double z, float partialTick) {
-        World theWorld = Minecraft.getMinecraft().currentWorld;
-        int blockUnder = theWorld.getBlockId(tileEntity.x, tileEntity.y - 1, tileEntity.z);
-        boolean shortPole = blockUnder == Blocks.FLAG.id();
+    public void doRender(final @NotNull Tessellator tessellator, @NotNull final TileEntityFlag tileEntity, final double x, final double y, final double z, final float partialTick) {
+        final World theWorld = Minecraft.getMinecraft().currentWorld;
+        final int blockUnder = theWorld.getBlockId(tileEntity.x, tileEntity.y - 1, tileEntity.z);
+        final boolean shortPole = blockUnder == Blocks.FLAG.id();
 
-        WindProvider theWind = mc.currentWorld.getWorldType().getWindManager();
+        final WindProvider theWind = this.mc.currentWorld.getWorldType().getWindManager();
 
-        float windDirection = theWind.getWindDirection(mc.currentWorld, 0.0f, 500.0f, 0.0f) * 360f;
-        float windIntensity = theWind.getWindIntensity(mc.currentWorld, 0.0f, 500.0f, 0.0f);
+        final float windDirection = theWind.getWindDirection(this.mc.currentWorld, 0.0f, 500.0f, 0.0f) * 360f;
+        final float windIntensity = theWind.getWindIntensity(this.mc.currentWorld, 0.0f, 500.0f, 0.0f);
         
-        doRender(tileEntity, x, y, z, partialTick, shortPole, windDirection, windIntensity);
+        doRender(tessellator, tileEntity, x, y, z, partialTick, shortPole, windDirection, windIntensity);
     }
 
     private long lastTick = 0;
-    public void doRender(TileEntityFlag tileEntityFlag, double x, double y, double z, float partialTick, boolean shortPole, float windDirection, float windIntensity)
+    public void doRender(final @NotNull Tessellator tessellator, final @NotNull TileEntityFlag tileEntityFlag, final double x, final double y, final double z, final float partialTick, final boolean shortPole, final float windDirection, final float windIntensity)
     {
-        World theWorld = Minecraft.getMinecraft().currentWorld;
-        if (flagRenderer == null)
-        {
-            flagRenderer = new FlagRenderer(renderDispatcher.textureManager);
-        }
-
-        if (theWorld.getWorldTime() != lastTick) {
-            lastTick = theWorld.getWorldTime();
-            flagRenderer.tick();
+        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+        final World theWorld = this.mc.currentWorld;
+        if (theWorld.getWorldTime() != this.lastTick) {
+            this.lastTick = theWorld.getWorldTime();
+            this.flagRenderer.tick();
         }
         
-        float swayInterpolated = tileEntityFlag.sway + partialTick;
+        final float swayInterpolated = tileEntityFlag.sway + partialTick;
         
         float sway = (float) ((swayInterpolated / 1.5) % (2 * Math.PI));
         sway = (float) (Math.sin(sway) * windIntensity * 2.0f);
         
         GL11.glPushMatrix();
-        final float scale = 1F;
-        GL11.glTranslatef((float) x + 0.5F, (float) y + 0.75F * scale, (float) z + 0.5F);
-        GL11.glScalef(scale, -scale, -scale);
-        loadTexture("/assets/minecraft/textures/entity/flag.png");
-        if (shortPole)
-        {
-            modelFlag.renderPoleShort();
-        }
-        else
-        {
-            modelFlag.renderBase();
-            modelFlag.renderPole();
+        GL11.glTranslatef((float) x + 0.5F, (float) y, (float) z + 0.5F);
+        GL11.glScalef(1/16F, 1/16F, -1/16F);
+        bindTexture("/assets/minecraft/textures/entity/flag.png");
+        final StaticEntityModel flagModel = shortPole ? getModel("pole.short") : getModel("pole.long");
+
+        if (shortPole) {
+            GL11.glTranslatef(0, 18, 0);
         }
-        
-        GL11.glPushMatrix();
-        GL11.glRotatef(windDirection + sway, 0.0f, 1.0f, 0.0f);
-        modelFlag.renderFlag();
-        renderDispatcher.textureManager.bindTexture(flagRenderer.getTexture(tileEntityFlag));
-        GL11.glEnable(GL11.GL_BLEND);
-        GL11.glBlendFunc(GL11.GL_ONE_MINUS_SRC_COLOR, GL11.GL_SRC_COLOR);
+
+        flagModel.getTransform("flag").rotY = (windDirection + sway) * MathHelper.DEG_TO_RAD;
+        flagModel.render(tessellator);
+
+        flagModel.translateToBone("flag");
+        bindTexture("/assets/minecraft/textures/entity/flag_ui.png");
         if (tileEntityFlag.getFlipped()) {
-            modelFlagMirrored.renderFlagOverlay();
+            getModel("cloth.mirror").render(tessellator);
+            GL11.glEnable(GL11.GL_BLEND);
+            GL11.glBlendFunc(GL11.GL_ONE_MINUS_SRC_COLOR, GL11.GL_SRC_COLOR);
+            this.renderDispatcher.textureManager.bindTexture(this.flagRenderer.getTexture(tileEntityFlag));
+            getModel("cloth.mirror").render(tessellator);
         } else {
-            modelFlag.renderFlagOverlay();
+            getModel("cloth").render(tessellator);
+            GL11.glEnable(GL11.GL_BLEND);
+            GL11.glBlendFunc(GL11.GL_ONE_MINUS_SRC_COLOR, GL11.GL_SRC_COLOR);
+            this.renderDispatcher.textureManager.bindTexture(this.flagRenderer.getTexture(tileEntityFlag));
+            getModel("cloth").render(tessellator);
         }
         GL11.glDisable(GL11.GL_BLEND);
+
         GL11.glPopMatrix();
-        final float f4 = 0.01666667F * scale;
-        GL11.glTranslatef(0.0F, 0.5F * scale, 0.07F * scale);
-        GL11.glScalef(f4, -f4, f4);
-        GL11.glNormal3f(0.0F, 0.0F, -1F * f4);
-        GL11.glPopMatrix();
+        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
     }
 
     @Override
-    public void onWorldChanged(World world) {
-        if (flagRenderer != null) {
-            flagRenderer.flushCaches();
-        }
+    public void onWorldChanged(final World world) {
+        this.flagRenderer.flushCaches();
     }
 }
diff --git a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererMobSpawner.java b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererMobSpawner.java
index 90b124037..ff11bfdb8 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererMobSpawner.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererMobSpawner.java
@@ -5,6 +5,7 @@ import java.util.Map;
 
 import net.minecraft.client.render.EntityRenderDispatcher;
 import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.client.world.WorldClient;
 import net.minecraft.core.block.entity.TileEntityMobSpawner;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityDispatcher;
@@ -32,7 +33,7 @@ public class TileEntityRendererMobSpawner extends TileEntityRenderer<TileEntityM
         Entity entity = entityHashMap.get(mobSpawner.getMobId());
         if(entity == null)
         {
-            entity = EntityDispatcher.createEntityInWorld(mobSpawner.getMobId(), null);
+            entity = EntityDispatcher.createEntityInWorld(mobSpawner.getMobId(), WorldClient.EMPTY_WORLD);
             entityHashMap.put(mobSpawner.getMobId(), entity);
         }
         if(entity != null)
diff --git a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererSign.java b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererSign.java
index 345adb7fa..6a77c86eb 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererSign.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererSign.java
@@ -3,7 +3,6 @@ package net.minecraft.client.render.tileentity;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.font.FontRenderer;
-import net.minecraft.client.render.model.ModelSign;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
@@ -12,38 +11,43 @@ import net.minecraft.core.block.Block;
 import net.minecraft.core.block.BlockLogicSign;
 import net.minecraft.core.block.entity.TileEntitySign;
 import net.minecraft.core.enums.EnumSignPicture;
+import net.minecraft.core.util.helper.Color;
 import net.minecraft.core.util.helper.MathHelper;
+import org.jetbrains.annotations.NotNull;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
 public class TileEntityRendererSign extends TileEntityRenderer<TileEntitySign>
 {
 
     private final Minecraft mc = Minecraft.getMinecraft();
-    private final ModelSign modelSign;
+    private final @NotNull StringBuilder builder = new StringBuilder();
 
-    public TileEntityRendererSign()
-    {
-        modelSign = new ModelSign();
+    public TileEntityRendererSign() {
+        super();
     }
 
      @Override
-	public void doRender(Tessellator t, TileEntitySign tileEntity, double x, double y, double z,
-                         float partialTick)
-    {
-        Block<?> block = tileEntity.getBlock();
+	public void doRender(final @NotNull Tessellator t, final @NotNull TileEntitySign tileEntity, final double x, final double y, final double z, final float partialTick) {
+        final Block<?> block = tileEntity.getBlock();
         if (block == null || !(block.getLogic() instanceof BlockLogicSign)) return; // Check to make sure the block for the entity is present before rendering, some edge cases have the tile entity loaded before the block data and can cause a crash
 
         GL11.glEnable(GL12.GL_RESCALE_NORMAL);
         GL11.glPushMatrix();
-        float scale = 2/3f;
-        GL11.glTranslatef((float)x + 0.5F, (float)y + 0.75F * scale, (float)z + 0.5F);
+
+        final StaticEntityModel model;
+
+        final float scale = 2/3f * 1/16f;
+        final float height;
+        GL11.glTranslatef((float)x + 0.5F, (float)y, (float)z + 0.5F);
         if (((BlockLogicSign) block.getLogic()).isFreeStanding) {
-            float angle = (float)(tileEntity.getBlockMeta() * 360) / 16F;
+            final float angle = (float)(tileEntity.getBlockMeta() * 360) / 16F;
             GL11.glRotatef(-angle, 0.0F, 1.0F, 0.0F);
-            modelSign.signStick.visible = true;
+            model = getModel("post");
+            height = 20;
         } else {
-            float angle;
+            final float angle;
             switch (tileEntity.getBlockMeta()) {
                 case BlockLogicSign.SIDE_NORTH:
                     angle = 180F;
@@ -60,27 +64,29 @@ public class TileEntityRendererSign extends TileEntityRenderer<TileEntitySign>
                     break;
             }
             GL11.glRotatef(-angle, 0.0F, 1.0F, 0.0F);
-            GL11.glTranslatef(0.0F, -0.3125F, -0.4375F);
-            modelSign.signStick.visible = false;
+            GL11.glTranslatef(0, 0, -11 * scale);
+            model = getModel("wall");
+            height = 13;
         }
 
         GL11.glPushMatrix();
-        GL11.glScalef(scale, -scale, -scale);
-        loadTexture("/assets/minecraft/textures/entity/sign.png");
-        modelSign.render();
+        GL11.glScalef(scale, scale, -scale);
+        bindTexture("/assets/minecraft/textures/entity/sign.png");
+        model.render(t);
         GL11.glPopMatrix();
 
         // Render overlay
         GL11.glPushMatrix();
-        GL11.glTranslatef(0, 5.3672f/16f, 0.7f/16f);
+        GL11.glTranslatef(0 * scale, height * scale, 1.05f * scale);
+        GL11.glNormal3f(0, 0, 1);
         GL11.glDepthMask(false);
-        EnumSignPicture picture = tileEntity.getPicture();
+        final EnumSignPicture picture = tileEntity.getPicture();
         drawTexturedModalRect(1, 0.5,TextureRegistry.getTexture(picture.getTextureKey()));
         GL11.glPopMatrix();
 
         // Render text
-        FontRenderer sr = getFont();
-        float lightLevel = LightmapHelper.isLightmapEnabled() ? 1 : mc.currentWorld.getLightBrightness(tileEntity.x, tileEntity.y, tileEntity.z);
+        final FontRenderer sr = getFont();
+        float lightLevel = (LightmapHelper.isLightmapEnabled() || this.mc.isFullbrightEnabled()) ? 1 : this.mc.currentWorld.getLightBrightness(tileEntity.x, tileEntity.y, tileEntity.z);
         float lightOffset = 0f;
         if (tileEntity.isGlowing()) {
             lightLevel = 1f;
@@ -92,23 +98,25 @@ public class TileEntityRendererSign extends TileEntityRenderer<TileEntitySign>
         }
 
         GL11.glPushMatrix();
-        float scale2 = 0.01666667F * scale;
-        GL11.glTranslatef(0.0F, 0.5F * scale, 0.065F * scale);
-        GL11.glScalef(scale2, -scale2, scale2);
-        GL11.glDepthMask(false);
+        final float scale2 = 0.2666667f * scale;
+         GL11.glTranslatef(0.0F, 20 * scale, 1.1f * scale);
+         GL11.glScalef(scale2, -scale2, scale2);
+         GL11.glDepthMask(false);
         int color = Colors.allSignColors[tileEntity.getColor().id].getARGB();
-        int r = (int) MathHelper.clamp(((color >> 16) & 0xFF) * lightLevel + lightOffset, 0, 255);
-        int g = (int)MathHelper.clamp(((color >>  8) & 0xFF) * lightLevel + lightOffset, 0, 255);
-        int b = (int)MathHelper.clamp(((color >>  0) & 0xFF) * lightLevel + lightOffset, 0, 255);
-        color = (r << 16) | (g << 8) | (b << 0);
+        final int r = (int) MathHelper.clamp((Color.redFromInt(color) * lightLevel + lightOffset), 0, 255);
+        final int g = (int)MathHelper.clamp((Color.greenFromInt(color) * lightLevel + lightOffset), 0, 255);
+        final int b = (int)MathHelper.clamp((Color.blueFromInt(color) * lightLevel + lightOffset), 0, 255);
+        color = Color.intToIntARGB(0, r, g, b);
         for(int line = 0; line < tileEntity.signText.length; line++)
         {
-            String text = tileEntity.signText[line];
+            this.builder.setLength(0);
             if(line == tileEntity.lineBeingEdited)
             {
-                text = "> " + text + " <";
+                this.builder.append("§+§0> §-").append(tileEntity.signText[line]).append("§+§0 <§-");
+            } else {
+                this.builder.append(tileEntity.signText[line]);
             }
-            sr.render(t, text, -sr.stringWidth(text) / 2, line * 10 - tileEntity.signText.length * 5).setColor(color).call();
+            sr.render(t, this.builder, -sr.stringWidth(this.builder) / 2, line * 10 - tileEntity.signText.length * 5).setColor(color).call();
         }
         GL11.glPopMatrix();
 
@@ -118,10 +126,10 @@ public class TileEntityRendererSign extends TileEntityRenderer<TileEntitySign>
         GL11.glDisable(GL12.GL_RESCALE_NORMAL);
     }
 
-    private void drawTexturedModalRect(double width, double height, IconCoordinate coordinate)
+    private static void drawTexturedModalRect(final double width, final double height, final @NotNull IconCoordinate coordinate)
     {
         coordinate.parentAtlas.bind();
-        Tessellator tessellator = Tessellator.instance;
+        final Tessellator tessellator = Tessellator.instance;
         tessellator.startDrawingQuads();
         tessellator.addVertexWithUV(-width/2,  height/2, 0, coordinate.getIconUMin(),coordinate.getIconVMin());
         tessellator.addVertexWithUV(-width/2, -height/2, 0, coordinate.getIconUMin(),coordinate.getIconVMax());
diff --git a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererStatue.java b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererStatue.java
index b325afe95..bf794ec4c 100644
--- a/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererStatue.java
+++ b/game/client/src/main/java/net/minecraft/client/render/tileentity/TileEntityRendererStatue.java
@@ -3,9 +3,6 @@ package net.minecraft.client.render.tileentity;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
-import net.minecraft.client.render.model.ModelBiped;
-import net.minecraft.client.render.model.ModelPigman;
-import net.minecraft.client.render.model.ModelPlayer;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.Block;
@@ -14,7 +11,6 @@ import net.minecraft.core.block.entity.TileEntityStatue;
 import net.minecraft.core.entity.IArmorWearing;
 import net.minecraft.core.enums.HumanArmorShape;
 import net.minecraft.core.item.*;
-import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import org.jetbrains.annotations.NotNull;
@@ -22,10 +18,13 @@ import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
 import org.useless.dragonfly.DisplayPos;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
 
 import java.util.HashMap;
 import java.util.Map;
 
+import static net.minecraft.client.render.entity.MobRenderer.ENTITY_RENDER_SCALE;
+
 public class TileEntityRendererStatue extends TileEntityRenderer<TileEntityStatue> {
     public static final @NotNull Map<@NotNull Block<?>, @NotNull String> BLOCK_SKIN_MAP = new HashMap<>();
     static {
@@ -38,166 +37,151 @@ public class TileEntityRendererStatue extends TileEntityRenderer<TileEntityStatu
         BLOCK_SKIN_MAP.put(Blocks.STATUE_PIGMAN_LOWER, basePath + "pigman.png");
     }
 
-    private final ModelPlayer model;
-    private final ModelBiped modelArmorA;
-    private final ModelBiped modelArmorB;
-    private final ModelPigman modelPigman;
-
     public TileEntityRendererStatue() {
-        this.model = new ModelPlayer(0.0f);
-        this.modelPigman = new ModelPigman(0.0f, 0.0f);
-        this.modelArmorA = new ModelBiped(1.0f);
-        this.modelArmorB = new ModelBiped(0.5f);
+        super();
     }
 
-    private ModelBiped model(boolean isPigman) {
+    private @NotNull StaticEntityModel model(final boolean isPigman) {
         if (isPigman) {
-            return this.modelPigman;
+            return getModel("main.pigman");
         } else {
-            return this.model;
+            return getModel("main");
         }
     }
 
-    public void renderAt(@Nullable ItemStack heldStack, final int meta, final @NotNull Block<?> lowerBlock, final @NotNull TileEntityStatue.Pose pose, final @Nullable IArmorWearing<HumanArmorShape> armorWearer, double x, double y, double z) {
+    public void renderAt(@NotNull final Tessellator tessellator, @Nullable final ItemStack heldStack, final int meta, final @NotNull Block<?> lowerBlock, final @NotNull TileEntityStatue.Pose pose, final @Nullable IArmorWearing<HumanArmorShape> armorWearer, final double x, final double y, final double z) {
         final boolean isPigman = lowerBlock == Blocks.STATUE_PIGMAN_LOWER;
 
+        final StaticEntityModel model = model(isPigman);
+
         GL12.glEnable(GL12.GL_RESCALE_NORMAL);
-        final float scale = 0.0625f;
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        loadTexture(BLOCK_SKIN_MAP.getOrDefault(lowerBlock, BLOCK_SKIN_MAP.get(Blocks.STATUE_STONE_LOWER)));
+        bindTexture(BLOCK_SKIN_MAP.getOrDefault(lowerBlock, BLOCK_SKIN_MAP.get(Blocks.STATUE_STONE_LOWER)));
         GL11.glPushMatrix();
-        GL11.glTranslated(x + 0.5, y + 1.5, z + 0.5);
-        float rotation = (float)(meta * 360) / 16F;
+        GL11.glTranslated(x + 0.5, y, z + 0.5);
+        final float rotation = (float)(meta * 360) / 16F;
         GL11.glRotatef(-rotation, 0.0F, 1.0F, 0.0F);
-        GL11.glScalef(1, -1, -1);
         GL11.glDisable(GL11.GL_CULL_FACE);
 
             GL11.glPushMatrix();
-            GL11.glScalef(scale, scale, scale);
-            renderModel(this.model(isPigman), pose);
+            GL11.glScalef(1 / ENTITY_RENDER_SCALE, 1 / ENTITY_RENDER_SCALE, -1 / ENTITY_RENDER_SCALE);
+            model.resetBones();
+            renderModel(tessellator, model, pose);
             if (armorWearer != null) {
                 for (int i = 0; i < 4; i++) {
-                    renderArmor(armorWearer, i, pose);
+                    renderArmor(tessellator, armorWearer, i, pose);
                 }
             }
+            renderHeldItem(heldStack, isPigman);
             GL11.glPopMatrix();
 
-        renderHeldItem(heldStack, isPigman);
         GL11.glEnable(GL11.GL_CULL_FACE);
         GL11.glPopMatrix();
         GL12.glDisable(GL12.GL_RESCALE_NORMAL);
     }
 
-    private void renderHeldItem(final @Nullable ItemStack itemStack, boolean isPigman) {
+    private void renderHeldItem(final @Nullable ItemStack itemStack, final boolean isPigman) {
         if(itemStack != null) {
             GL12.glEnable(GL12.GL_RESCALE_NORMAL);
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-            model(isPigman).armRight.translateTo(0.0625F);
-            GL11.glRotatef(-90, 1, 0, 0);
-            GL11.glScalef(-1, 1, -1);
-            GL11.glTranslatef(1/16f, 2/16f, -10f/16f);
+            model(isPigman).translateToBone("rightItem");
+            GL11.glScalef(-1, 1, 1);
+            GL11.glScalef(ENTITY_RENDER_SCALE, ENTITY_RENDER_SCALE, ENTITY_RENDER_SCALE);
             ItemModelDispatcher.getInstance().getDispatch(itemStack).render(Tessellator.instance, null, itemStack, DisplayPos.THIRD_PERSON_RIGHT_HAND, true, 1, 1f, 1f, 1f, false);
             GL11.glEnable(GL11.GL_CULL_FACE);
             GL12.glDisable(GL12.GL_RESCALE_NORMAL);
         }
     }
 
-    private void applyPose(TileEntityStatue.Pose pose, ModelBiped model) {
-        model.armLeft.xRot = pose.leftArmPitch;
-        model.armRight.xRot = pose.rightArmPitch;
-        model.legLeft.xRot = pose.leftLegPitch;
-        model.legRight.xRot = pose.rightLegPitch;
-        model.head.xRot = pose.headPitch;
-        model.head.yRot = pose.headYaw;
-        if (model instanceof ModelPigman) {
-            ((ModelPigman) model).nose.xRot = pose.headPitch;
-            ((ModelPigman) model).nose.yRot = pose.headYaw;
-        }
-    }
 
-    private void renderModel(ModelBiped model, TileEntityStatue.Pose pose) {
-        final float scale = 1.0f;
-
-        model.setupAnimation(null, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, scale, 1f);
-        applyPose(pose, model);
-
-        model.head.render(scale);
-        model.body.render(scale);
-        model.armRight.render(scale);
-        model.armLeft.render(scale);
-        model.legRight.render(scale);
-        model.legLeft.render(scale);
-        model.hair.render(scale);
-        if (model instanceof ModelPigman) {
-            ((ModelPigman) model).nose.render(scale);
-        }
+    private void renderModel(@NotNull final Tessellator tessellator, @NotNull final StaticEntityModel model, @NotNull final TileEntityStatue.Pose pose) {
+        model.getTransform("leftArm").rotX = pose.leftArmPitch;
+        model.getTransform("rightArm").rotX = pose.rightArmPitch;
+        model.getTransform("leftLeg").rotX = pose.leftLegPitch;
+        model.getTransform("rightLeg").rotX = pose.rightLegPitch;
+        model.getTransform("head").rotX = pose.headPitch;
+        model.getTransform("head").rotY = pose.headYaw;
+        model.render(tessellator);
     }
 
     @Override
-    public void doRender(Tessellator tessellator, TileEntityStatue tileEntity, double x, double y, double z,
-                         float partialTick) {
-        renderAt(tileEntity.getHeldItem(), tileEntity.getBlockMeta(), tileEntity.getBlock(), tileEntity.getPose(), tileEntity, x, y, z);
+    public void doRender(@NotNull final Tessellator tessellator, @NotNull final TileEntityStatue tileEntity, final double x, final double y, final double z, final float partialTick) {
+        renderAt(tessellator, tileEntity.getHeldItem(), tileEntity.getBlockMeta(), tileEntity.getBlock(), tileEntity.getPose(), tileEntity, x, y, z);
         renderShadow(Minecraft.getMinecraft().currentWorld, tessellator, tileEntity.x, tileEntity.y, tileEntity.z, x, y, z, 2.0f, partialTick);
     }
 
-    private boolean renderArmor(final @NotNull IArmorWearing<HumanArmorShape> armorWearer, int layer, TileEntityStatue.Pose pose) {
-        ItemStack itemstack = armorWearer.getItemInArmorSlot(HumanArmorShape.values()[(armorWearer.getNumArmorSlots() - 1) - layer]);
+    private boolean renderArmor(final @NotNull Tessellator tessellator, final @NotNull IArmorWearing<? super HumanArmorShape> armorWearer, final int layer, final TileEntityStatue.Pose pose) {
+        final ItemStack itemstack = armorWearer.getItemInArmorSlot(HumanArmorShape.values()[(armorWearer.getNumArmorSlots() - 1) - layer]);
         if (itemstack != null) {
-            Item item = itemstack.getItem();
-            ModelBiped toDraw = null;
+            final Item item = itemstack.getItem();
             if (item instanceof ItemQuiver) {
-                loadTexture("/assets/minecraft/textures/armor/quiver.png");
-                ModelBiped modelBiped = modelArmorA;
-                modelBiped.body.visible = layer == 1 || layer == 2;
-                toDraw = modelBiped;
-            }
-            if (item instanceof ItemQuiverEndless) {
-                loadTexture("/assets/minecraft/textures/armor/quiver_golden.png");
-                ModelBiped modelBiped = modelArmorA;
-                modelBiped.body.visible = layer == 1 || layer == 2;
-                toDraw = modelBiped;
-            }
-            if (item == Items.ARMOR_BOOTS_ICESKATES) {
-                loadTexture("/assets/minecraft/textures/armor/skates.png");
-                ModelBiped modelBiped = modelArmorA;
-                modelBiped.legRight.visible = layer == 2 || layer == 3;
-                modelBiped.legLeft.visible = layer == 2 || layer == 3;
-                toDraw = modelBiped;
-            }
-            if (item instanceof IArmorItem && ((IArmorItem) item).getArmorMaterial() != null) {
-                IArmorItem armorItem = (IArmorItem) item;
-                loadTexture(String.format("/assets/%s/textures/armor/%s_%d.png", armorItem.getArmorMaterial().identifier.namespace, armorItem.getArmorMaterial().identifier.value, (layer != 2 ? 1 : 2)));
-                ModelBiped modelBiped = layer != 2 ? modelArmorA : modelArmorB;
-                modelBiped.head.visible = layer == 0;
-                modelBiped.hair.visible = layer == 0;
-                modelBiped.body.visible = layer == 1 || layer == 2;
-                modelBiped.armRight.visible = layer == 1;
-                modelBiped.armLeft.visible = layer == 1;
-                modelBiped.legRight.visible = layer == 2 || layer == 3;
-                modelBiped.legLeft.visible = layer == 2 || layer == 3;
-                toDraw = modelBiped;
+                bindTexture("/assets/minecraft/textures/armor/quiver.png");
+            } else if (item instanceof ItemQuiverEndless) {
+                bindTexture("/assets/minecraft/textures/armor/quiver_golden.png");
+            } else if (item == Items.ARMOR_BOOTS_ICESKATES) {
+                bindTexture("/assets/minecraft/textures/armor/skates.png");
+            } else if (item instanceof IArmorItem) {
+                final IArmorItem armorItem = (IArmorItem) item;
+                if (armorItem.getArmorMaterial() == null) return false;
+                bindTexture(String.format("/assets/%s/textures/armor/%s_%d.png", armorItem.getArmorMaterial().identifier.namespace, armorItem.getArmorMaterial().identifier.value, (layer != 2 ? 1 : 2)));
+            } else {
+                return false;
             }
 
-            if (toDraw != null) {
-                renderModel(toDraw, pose);
-                return true;
+            final StaticEntityModel model;
+            switch (layer) {
+                case 3:
+                    model = getModel("armor.boots");
+                    model.resetBones();
+                    model.getTransform("chest").visible = false;
+                    model.getTransform("head").visible = false;
+                    model.getTransform("rightArm").visible = false;
+                    model.getTransform("leftArm").visible = false;
+                    break;
+                case 2:
+                    model = getModel("armor.leggings");
+                    model.resetBones();
+                    model.getTransform("head").visible = false;
+                    model.getTransform("rightArm").visible = false;
+                    model.getTransform("leftArm").visible = false;
+                    break;
+                case 1:
+                    model = getModel("armor.chestplate");
+                    model.resetBones();
+                    model.getTransform("head").visible = false;
+                    model.getTransform("rightLeg").visible = false;
+                    model.getTransform("leftLeg").visible = false;
+                    break;
+                case 0:
+                    model = getModel("armor.helmet");
+                    model.resetBones();
+                    model.getTransform("chest").visible = false;
+                    model.getTransform("rightArm").visible = false;
+                    model.getTransform("leftArm").visible = false;
+                    model.getTransform("rightLeg").visible = false;
+                    model.getTransform("leftLeg").visible = false;
+                    break;
+                default:
+                    return false;
             }
+            renderModel(tessellator, model, pose);
+            return true;
         }
         return false;
     }
 
-    private void renderShadow(World world, Tessellator tessellator, int bx, int by, int bz, double rx, double ry, double rz, float opacity, float partialTick)
+    private void renderShadow(final @NotNull World world, final @NotNull Tessellator tessellator, final int bx, final int by, final int bz, final double rx, final double ry, final double rz, final float opacity, final float partialTick)
     {
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-        TextureManager textureManager = renderDispatcher.textureManager;
+        final TextureManager textureManager = this.renderDispatcher.textureManager;
         textureManager.bindTexture(textureManager.loadTexture("/assets/minecraft/textures/misc/shadow.png"));
-        float shadowSize = 0.5f;
-        float shadowOffs = 0.8f / 2.0f;
+        final float shadowSize = 0.5f;
+        final float shadowOffs = 0.8f / 2.0f;
         GL11.glDepthMask(false);
         tessellator.startDrawingQuads();
 
-        int blockId = world.getBlockId(bx, by - 1, bz);
+        final int blockId = world.getBlockId(bx, by - 1, bz);
         if(blockId > 0 && world.getBlockLightValue(bx, by, bz) > 3)
         {
             renderShadowOnBlock(world, tessellator, Blocks.blocksList[blockId], bx, by, bz, rx, ry + (double)shadowOffs, rz, opacity, shadowSize);
@@ -209,8 +193,8 @@ public class TileEntityRendererStatue extends TileEntityRenderer<TileEntityStatu
         GL11.glDepthMask(true);
     }
 
-    private void renderShadowOnBlock(World world, Tessellator tessellator, Block<?> block, int bx, int by, int bz, double rx, double ry, double rz,
-                                     float opacity, float size)
+    private void renderShadowOnBlock(final @NotNull World world, final @NotNull Tessellator tessellator, final Block<?> block, final int bx, final int by, final int bz, final double rx, final double ry, final double rz,
+                                     final float opacity, final float size)
     {
         if(!block.isCubeShaped())
         {
@@ -228,19 +212,19 @@ public class TileEntityRendererStatue extends TileEntityRenderer<TileEntityStatu
             alpha = 1.0D;
         }
         tessellator.setColorRGBA_F(1.0F, 1.0F, 1.0F, (float)alpha);
-        AABB aabb = block.getCollisionBoundingBoxFromPool(world, bx, by - 1, bz);
+        final AABB aabb = block.getCollisionBoundingBoxFromPool(world, bx, by - 1, bz);
         if(aabb == null) {
             return;
         }
-        double xMin = rx - 0.5f;
-        double xMax = rx + (aabb.maxX - aabb.minX) - 0.5f;
-        double yMin = (ry + (aabb.maxY - aabb.minY)) - 1.39;
-        double zMin = rz - 0.5f;
-        double zMax = rz + (aabb.maxZ - aabb.minZ) - 0.5f;
-        float f2 = (float)((rx - xMin) / 2D / (double)size + 0.5D);
-        float f3 = (float)((rx - xMax) / 2D / (double)size + 0.5D);
-        float f4 = (float)((rz - zMin) / 2D / (double)size + 0.5D);
-        float f5 = (float)((rz - zMax) / 2D / (double)size + 0.5D);
+        final double xMin = rx - 0.5f;
+        final double xMax = rx + (aabb.maxX - aabb.minX) - 0.5f;
+        final double yMin = (ry + (aabb.maxY - aabb.minY)) - 1.39;
+        final double zMin = rz - 0.5f;
+        final double zMax = rz + (aabb.maxZ - aabb.minZ) - 0.5f;
+        final float f2 = (float)((rx - xMin) / 2D / (double)size + 0.5D);
+        final float f3 = (float)((rx - xMax) / 2D / (double)size + 0.5D);
+        final float f4 = (float)((rz - zMin) / 2D / (double)size + 0.5D);
+        final float f5 = (float)((rz - zMax) / 2D / (double)size + 0.5D);
         tessellator.addVertexWithUV(xMin + 0.5f, yMin, zMin + 0.5f, f2, f4);
         tessellator.addVertexWithUV(xMin + 0.5f, yMin, zMax + 0.5f, f2, f5);
         tessellator.addVertexWithUV(xMax + 0.5f, yMin, zMax + 0.5f, f3, f5);
diff --git a/game/client/src/main/java/net/minecraft/client/world/WorldClient.java b/game/client/src/main/java/net/minecraft/client/world/WorldClient.java
index b1b6991c4..ab03c6b85 100644
--- a/game/client/src/main/java/net/minecraft/client/world/WorldClient.java
+++ b/game/client/src/main/java/net/minecraft/client/world/WorldClient.java
@@ -20,6 +20,7 @@ import net.minecraft.core.world.weather.IPrecipitation;
 import net.minecraft.core.world.weather.WeatherManager;
 
 public class WorldClient extends World {
+    public static final WorldClient EMPTY_WORLD = new WorldClient();
 
     public WorldClient(LevelStorage saveHandler, String name, long seed, Dimension dimension, WorldType worldType) {
         super(saveHandler, name, seed, dimension, worldType);
diff --git a/game/client/src/main/java/org/useless/dragonfly/data/block/mojang/BlockModelMojangData.java b/game/client/src/main/java/org/useless/dragonfly/data/block/mojang/BlockModelMojangData.java
index 331864413..bf31e01a2 100644
--- a/game/client/src/main/java/org/useless/dragonfly/data/block/mojang/BlockModelMojangData.java
+++ b/game/client/src/main/java/org/useless/dragonfly/data/block/mojang/BlockModelMojangData.java
@@ -22,7 +22,7 @@ import org.slf4j.Logger;
 import org.useless.dragonfly.DisplayPos;
 import org.useless.dragonfly.data.block.BlockModelData;
 import org.useless.dragonfly.models.block.StaticBlockModel;
-import org.useless.dragonfly.models.block.mojang.StaticModelMojang;
+import org.useless.dragonfly.models.block.mojang.StaticBlockModelMojang;
 
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -44,7 +44,7 @@ public class BlockModelMojangData implements BlockModelData {
     protected final static Gson gson = builder().create();
 
     protected static GsonBuilder builder() {
-        GsonBuilder builder = new GsonBuilder();
+        final GsonBuilder builder = new GsonBuilder();
         builder.setPrettyPrinting();
         builder.registerTypeAdapter(BlockModelMojangData.Builder.class, new BlockModelMojangData.Builder.Serializer());
         builder.registerTypeAdapter(Element.Builder.class, new Element.Builder.Serializer());
@@ -102,20 +102,20 @@ public class BlockModelMojangData implements BlockModelData {
     public final @Nullable List<@NotNull Element> elements;
 
     protected BlockModelMojangData(
-        @NotNull TexturePackList texturePackList,
-        @NotNull NamespaceID id,
-        @Nullable String parent,
-        boolean ambientOcclusion,
-        @Nullable Integer renderLayer,
-        @Nullable Map<@NotNull String, @NotNull DisplayPos> displayPositions,
-        @Nullable Map<@NotNull String, @NotNull String> textures,
-        @Nullable Map<@NotNull Direction, @NotNull Integer> particleIndices,
-        @Nullable List<@NotNull Element> elements)
+        @NotNull final TexturePackList texturePackList,
+        @NotNull final NamespaceID id,
+        @Nullable final String parent,
+        final boolean ambientOcclusion,
+        @Nullable final Integer renderLayer,
+        @Nullable final Map<@NotNull String, @NotNull DisplayPos> displayPositions,
+        @Nullable final Map<@NotNull String, @NotNull String> textures,
+        @Nullable final Map<@NotNull Direction, @NotNull Integer> particleIndices,
+        @Nullable final List<@NotNull Element> elements)
     {
         this.modelId = id;
         this.parent = parent;
         if (parent != null) {
-            BlockModelMojangData parentData = BlockModelMojangData.Cache.loadModelData(texturePackList, parent);
+            final BlockModelMojangData parentData = BlockModelMojangData.Cache.loadModelData(texturePackList, parent);
             this.ambientOcclusion = ambientOcclusion;
             if (parentData != null) {
                 this.displayPositions = new HashMap<>();
@@ -151,24 +151,24 @@ public class BlockModelMojangData implements BlockModelData {
 
     @Override
     public @NotNull NamespaceID modelId() {
-        return modelId;
+        return this.modelId;
     }
 
     @Override
     public @NotNull StaticBlockModel asModel() {
-        return new StaticModelMojang(this);
+        return new StaticBlockModelMojang(this);
     }
 
     @Override
     public String toString() {
         return "BlockModelMojangData{" +
-            "modelId=" + modelId +
-            ", parent='" + parent + '\'' +
-            ", ambientOcclusion=" + ambientOcclusion +
-            ", displayPositions=" + displayPositions +
-            ", textures=" + textures +
-            ", particleIndices=" + particleIndices +
-            ", elements=" + elements +
+            "modelId=" + this.modelId +
+            ", parent='" + this.parent + '\'' +
+            ", ambientOcclusion=" + this.ambientOcclusion +
+            ", displayPositions=" + this.displayPositions +
+            ", textures=" + this.textures +
+            ", particleIndices=" + this.particleIndices +
+            ", elements=" + this.elements +
             '}';
     }
 
@@ -182,112 +182,112 @@ public class BlockModelMojangData implements BlockModelData {
         protected @Nullable Map<@NotNull Direction, @NotNull Integer> particleIndices = null;
         protected @Nullable List<Element. @NotNull Builder> elements = null;
 
-        public @NotNull Builder setParent(@Nullable String parent) {
+        public @NotNull Builder setParent(@Nullable final String parent) {
             this.parent = parent;
             return this;
         }
 
-        public @NotNull Builder setAO(boolean ao) {
+        public @NotNull Builder setAO(final boolean ao) {
             this.ambientOcclusion = ao;
             return this;
         }
 
-        public @NotNull Builder setRenderLayer(int renderLayer) {
+        public @NotNull Builder setRenderLayer(final int renderLayer) {
             this.renderLayer = renderLayer;
             return this;
         }
 
-        public @NotNull Builder setDisplay(@NotNull String id, @Nullable DisplayPos displayPos) {
-            if (displayPos == null && displayPosMap != null) {
-                displayPosMap.remove(id);
+        public @NotNull Builder setDisplay(@NotNull final String id, @Nullable final DisplayPos displayPos) {
+            if (displayPos == null && this.displayPosMap != null) {
+                this.displayPosMap.remove(id);
             } else if (displayPos != null) {
                 prepareDisplayPosMap().put(id, displayPos);
             }
             return this;
         }
 
-        public @NotNull Builder setTexture(@NotNull String textureVariable, @NotNull String textureSymbol) {
+        public @NotNull Builder setTexture(@NotNull final String textureVariable, @NotNull final String textureSymbol) {
             prepareTextureMap().put(textureVariable, textureSymbol);
             return this;
         }
 
-        public @NotNull Builder setParticleIndex(@NotNull Direction direction, int index) {
+        public @NotNull Builder setParticleIndex(@NotNull final Direction direction, final int index) {
             prepareParticleIndicesMap().put(direction, index);
             return this;
         }
 
-        public @NotNull Builder addElement(Element. @NotNull Builder elementBuilder) {
+        public @NotNull Builder addElement(final Element. @NotNull Builder elementBuilder) {
             prepareElementsList().add(elementBuilder);
             return this;
         }
 
         private @NotNull Map<@NotNull String, @NotNull DisplayPos> prepareDisplayPosMap() {
-            if (displayPosMap == null) displayPosMap = new HashMap<>();
-            return displayPosMap;
+            if (this.displayPosMap == null) this.displayPosMap = new HashMap<>();
+            return this.displayPosMap;
         }
 
         private @NotNull Map<@NotNull String, @NotNull String> prepareTextureMap() {
-            if (textures == null) textures = new HashMap<>();
-            return textures;
+            if (this.textures == null) this.textures = new HashMap<>();
+            return this.textures;
         }
 
         private @NotNull Map<@NotNull Direction, @NotNull Integer> prepareParticleIndicesMap() {
-            if (particleIndices == null) particleIndices = new HashMap<>();
-            return particleIndices;
+            if (this.particleIndices == null) this.particleIndices = new HashMap<>();
+            return this.particleIndices;
         }
 
         private @NotNull List<Element. @NotNull Builder> prepareElementsList() {
-            if (elements == null) elements = new ArrayList<>();
-            return elements;
+            if (this.elements == null) this.elements = new ArrayList<>();
+            return this.elements;
         }
 
-        protected @NotNull BlockModelMojangData build(@NotNull TexturePackList texturePackList, @NotNull String id) {
+        protected @NotNull BlockModelMojangData build(@NotNull final TexturePackList texturePackList, @NotNull String id) {
             if (!id.contains(":")) {
                 id = DEFAULT_NAMESPACE + ":" + id;
             }
             List<Element> elementList = null;
-            if (elements != null) {
+            if (this.elements != null) {
                 elementList = new ArrayList<>();
-                for (Element.Builder b : elements) {
+                for (final Element.Builder b : this.elements) {
                     elementList.add(b.build());
                 }
             }
             try {
-                return new BlockModelMojangData(texturePackList, new NamespaceID(id), parent, ambientOcclusion, renderLayer, displayPosMap, textures, particleIndices, elementList);
-            } catch (HardIllegalArgumentException e) {
+                return new BlockModelMojangData(texturePackList, new NamespaceID(id), this.parent, this.ambientOcclusion, this.renderLayer, this.displayPosMap, this.textures, this.particleIndices, elementList);
+            } catch (final HardIllegalArgumentException e) {
                 throw new IllegalArgumentException(e);
             }
         }
 
         public static class Serializer implements JsonSerializer<BlockModelMojangData.Builder>, JsonDeserializer<BlockModelMojangData.Builder> {
             @Override
-            public BlockModelMojangData.Builder deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
-                JsonObject object = json.getAsJsonObject();
-                BlockModelMojangData.Builder dataBuilder = new BlockModelMojangData.Builder();
+            public BlockModelMojangData.Builder deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
+                final JsonObject object = json.getAsJsonObject();
+                final BlockModelMojangData.Builder dataBuilder = new BlockModelMojangData.Builder();
                 if (object.has("parent")) dataBuilder.setParent(object.get("parent").getAsString());
                 if (object.has("ambientocclusion")) dataBuilder.setAO(object.get("ambientocclusion").getAsBoolean());
                 if (object.has("renderlayer")) dataBuilder.setRenderLayer(object.get("renderlayer").getAsInt());
                 if (object.has("display")) {
-                    JsonObject display = object.getAsJsonObject("display");
-                    for (Map.Entry<String, JsonElement> e : display.entrySet()) {
+                    final JsonObject display = object.getAsJsonObject("display");
+                    for (final Map.Entry<String, JsonElement> e : display.entrySet()) {
                         dataBuilder.setDisplay(e.getKey(), context.deserialize(e.getValue(), DisplayPos.class));
                     }
                 }
                 if (object.has("textures")) {
-                    JsonObject textures = object.getAsJsonObject("textures");
-                    for (Map.Entry<String, JsonElement> e : textures.entrySet()) {
+                    final JsonObject textures = object.getAsJsonObject("textures");
+                    for (final Map.Entry<String, JsonElement> e : textures.entrySet()) {
                         dataBuilder.setTexture(e.getKey(), e.getValue().getAsString());
                     }
                 }
                 if (object.has("elements")) {
-                    JsonArray elements = object.getAsJsonArray("elements");
-                    for (JsonElement e : elements) {
+                    final JsonArray elements = object.getAsJsonArray("elements");
+                    for (final JsonElement e : elements) {
                         dataBuilder.addElement(context.deserialize(e, Element.Builder.class));
                     }
                 }
                 if (object.has("particles")) {
-                    JsonObject textures = object.getAsJsonObject("particles");
-                    for (Map.Entry<String, JsonElement> e : textures.entrySet()) {
+                    final JsonObject textures = object.getAsJsonObject("particles");
+                    for (final Map.Entry<String, JsonElement> e : textures.entrySet()) {
                         dataBuilder.setParticleIndex(Direction.valueOf(e.getKey().toUpperCase(Locale.ROOT)), e.getValue().getAsInt());
                     }
                 }
@@ -296,7 +296,7 @@ public class BlockModelMojangData implements BlockModelData {
             }
 
             @Override
-            public JsonElement serialize(BlockModelMojangData.Builder src, Type typeOfSrc, JsonSerializationContext context) {
+            public JsonElement serialize(final BlockModelMojangData.Builder src, final Type typeOfSrc, final JsonSerializationContext context) {
                 throw new UnsupportedOperationException();
             }
         }
@@ -308,37 +308,37 @@ public class BlockModelMojangData implements BlockModelData {
 
         protected static final String RESOURCE_PATH = "/assets/%s/models/%s.json";
 
-        public static @Nullable BlockModelMojangData loadModelData(@NotNull TexturePackList texturePackList, @NotNull NamespaceID id) {
-            String s = id.toString();
+        public static @Nullable BlockModelMojangData loadModelData(@NotNull final TexturePackList texturePackList, @NotNull final NamespaceID id) {
+            final String s = id.toString();
             if (modelDataCache.containsKey(s)) return modelDataCache.get(s);
-            BlockModelMojangData.Builder data = loadFromStream(texturePackList.getResourceAsStream(String.format(RESOURCE_PATH, id.namespace, id.value)));
+            final BlockModelMojangData.Builder data = loadFromStream(texturePackList.getResourceAsStream(String.format(RESOURCE_PATH, id.namespace, id.value)));
             if (data == null) {
                 LOGGER.error("Could not locate block model data for id '{}'!", id);
                 return null;
             }
-            BlockModelMojangData model = data.build(texturePackList, id.toString());
+            final BlockModelMojangData model = data.build(texturePackList, id.toString());
             modelDataCache.put(model.modelId().toString(), model);
             return model;
         }
-        public static @Nullable BlockModelMojangData loadModelData(@NotNull TexturePackList texturePackList, @NotNull String id) {
-            String namespace;
-            String value;
+        public static @Nullable BlockModelMojangData loadModelData(@NotNull final TexturePackList texturePackList, @NotNull final String id) {
+            final String namespace;
+            final String value;
             if (!id.contains(":")) {
                 namespace = DEFAULT_NAMESPACE;
                 value = id;
             } else {
-                String[] strings = id.split(":");
+                final String[] strings = id.split(":");
                 if (strings.length != 2) throw new  IllegalArgumentException("Block model id '" + id + "' cannot have more then 1 ':' character!");
                 namespace = strings[0];
                 value = strings[1];
             }
             if (modelDataCache.containsKey(id)) return modelDataCache.get(id);
-            BlockModelMojangData.Builder data = loadFromStream(texturePackList.getResourceAsStream(String.format(RESOURCE_PATH, namespace, value)));
+            final BlockModelMojangData.Builder data = loadFromStream(texturePackList.getResourceAsStream(String.format(RESOURCE_PATH, namespace, value)));
             if (data == null) {
                 LOGGER.error("Could not locate block model data for id '{}'!", id);
                 return null;
             }
-            BlockModelMojangData model = data.build(texturePackList, namespace + ":" + value);
+            final BlockModelMojangData model = data.build(texturePackList, namespace + ":" + value);
             modelDataCache.put(model.modelId().toString(), model);
             return model;
         }
@@ -347,7 +347,7 @@ public class BlockModelMojangData implements BlockModelData {
             modelDataCache.clear();
         }
 
-        protected static @Nullable BlockModelMojangData.Builder loadFromStream(@Nullable InputStream stream) {
+        protected static @Nullable BlockModelMojangData.Builder loadFromStream(@Nullable final InputStream stream) {
             if (stream == null) return null;
             return gson.fromJson(new JsonReader(new InputStreamReader(stream)), BlockModelMojangData.Builder.class);
         }
diff --git a/game/client/src/main/java/org/useless/dragonfly/data/entity/EntityModelData.java b/game/client/src/main/java/org/useless/dragonfly/data/entity/EntityModelData.java
new file mode 100644
index 000000000..8ac337c9c
--- /dev/null
+++ b/game/client/src/main/java/org/useless/dragonfly/data/entity/EntityModelData.java
@@ -0,0 +1,9 @@
+package org.useless.dragonfly.data.entity;
+
+import org.jetbrains.annotations.NotNull;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
+public interface EntityModelData {
+    @NotNull String modelId();
+    @NotNull StaticEntityModel asModel(double inflation);
+}
diff --git a/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/Bone.java b/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/Bone.java
new file mode 100644
index 000000000..1a4970081
--- /dev/null
+++ b/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/Bone.java
@@ -0,0 +1,141 @@
+package org.useless.dragonfly.data.entity.mojang;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.util.GsonHelper;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class Bone {
+    public final @NotNull String name;
+    public final @Nullable String parent;
+    public final double @NotNull [] pivot;
+    public final double @NotNull [] rotation;
+    public final @NotNull Cube @NotNull [] cubes;
+    public final double inflate;
+
+    protected Bone(
+        @NotNull final String name,
+        @Nullable final String parent,
+        final double @NotNull [] pivot,
+        final double @NotNull [] rotation,
+        final double inflate,
+        @NotNull final Collection<Cube.Builder> cubes) {
+        this.name = name;
+        this.parent = parent;
+        this.pivot = pivot;
+        this.rotation = rotation;
+        this.cubes = new Cube[cubes.size()];
+        this.inflate = inflate;
+
+        int i = 0;
+        for (final Cube.Builder builder : cubes) {
+            this.cubes[i] = builder.build();
+            i++;
+        }
+    }
+
+    public static class Builder {
+        private final @NotNull String name;
+        private @Nullable String parent;
+        private final double @NotNull [] pivot;
+        private final double @NotNull [] rotation;
+        private double inflate;
+        private final @NotNull List<Cube. @NotNull  Builder> cubes = new ArrayList<>();
+        private boolean mirror;
+        public Builder(@NotNull final String name) {
+            this.name = name;
+            this.parent = null;
+            this.pivot = new double[]{0, 0, 0};
+            this.rotation = new double[]{0, 0, 0};
+            this.inflate = 0;
+            this.mirror = false;
+        }
+
+        public @NotNull Builder setParent(final @NotNull String parent) {
+            this.parent = parent;
+            return this;
+        }
+
+        public @NotNull Builder setPivot(final double x, final double y, final double z) {
+            this.pivot[0] = x;
+            this.pivot[1] = y;
+            this.pivot[2] = z;
+            return this;
+        }
+
+        public @NotNull Builder setRotation(final double x, final double y, final double z) {
+            this.rotation[0] = x;
+            this.rotation[1] = y;
+            this.rotation[2] = z;
+            return this;
+        }
+
+        public @NotNull Builder setInflation(final double inflation) {
+            this.inflate = inflation;
+            return this;
+        }
+
+        public @NotNull Builder setMirror(final boolean mirror) {
+            this.mirror = mirror;
+            return this;
+        }
+
+        public @NotNull Builder addCube(final @NotNull Cube.Builder cube) {
+            this.cubes.add(cube);
+            return this;
+        }
+
+        protected @NotNull Bone build() {
+            if (this.mirror) {
+                for (final Cube.Builder builder : this.cubes) {
+                    builder.setMirror();
+                }
+            }
+            return new Bone(this.name, this.parent, this.pivot, this.rotation, this.inflate, this.cubes);
+        }
+
+        public static class Serializer implements JsonSerializer<Bone.Builder>, JsonDeserializer<Bone.Builder> {
+
+            @Override
+            public Builder deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
+                final JsonObject object = json.getAsJsonObject();
+                final Builder builder = new Builder(object.get("name").getAsString());
+                if (object.has("parent")) builder.setParent(object.get("parent").getAsString());
+                if (object.has("pivot")) {
+                    final double[] pivot = GsonHelper.getAsDoubleArray(object.get("pivot"), 3);
+                    builder.setPivot(pivot[0], pivot[1], pivot[2]);
+                }
+                if (object.has("rotation")) {
+                    final double[] rotation = GsonHelper.getAsDoubleArray(object.get("rotation"), 3);
+                    builder.setRotation(rotation[0], rotation[1], rotation[2]);
+                }
+                if (object.has("inflate")) builder.setInflation(object.get("inflate").getAsDouble());
+                if (object.has("mirror")) builder.setMirror(object.get("mirror").getAsBoolean());
+                if (object.has("cubes")) {
+                    final JsonArray cubes = object.getAsJsonArray("cubes");
+                    for (final JsonElement e : cubes) {
+                        builder.addCube(context.deserialize(e, Cube.Builder.class));
+                    }
+                }
+                return builder;
+            }
+
+            @Override
+            public JsonElement serialize(final Builder src, final Type typeOfSrc, final JsonSerializationContext context) {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+}
diff --git a/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/Cube.java b/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/Cube.java
new file mode 100644
index 000000000..1a218ddfe
--- /dev/null
+++ b/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/Cube.java
@@ -0,0 +1,180 @@
+package org.useless.dragonfly.data.entity.mojang;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import net.minecraft.core.util.helper.Direction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.useless.util.GsonHelper;
+
+import java.lang.reflect.Type;
+import java.util.Locale;
+import java.util.Map;
+
+public class Cube {
+    public final double @NotNull [] origin;
+    public final double @NotNull [] size;
+    public final @Nullable Face @NotNull [] faces;
+    public final double inflate;
+    public final double @NotNull [] pivot;
+    public final double @Nullable [] rotation;
+
+    protected Cube(final double @NotNull [] origin, final double @NotNull [] size, final @Nullable Face.Builder @NotNull [] faces, final double inflate, final double @NotNull [] pivot, final double @Nullable [] rotation) {
+        this.origin = origin;
+        this.size = size;
+        this.pivot = pivot;
+        this.rotation = rotation;
+        this.faces = new Face[6];
+        for (int i = 0; i < 6; i++) {
+            final Face.Builder builder = faces[i];
+            if (builder == null) continue;
+            this.faces[i] = builder.build();
+        }
+        this.inflate = inflate;
+    }
+
+    public static class Builder {
+        private final double @NotNull [] origin;
+        private final double @NotNull [] size;
+        private final @Nullable Face.Builder @NotNull [] faces;
+        private double inflate;
+        private final double @NotNull [] pivot;
+        private double @Nullable [] rotation = null;
+        private boolean mirror;
+
+        public Builder(
+            final double oX, final double oY, final double oZ,
+            final double sX, final double sY, final double sZ
+        ) {
+            this.origin = new double[]{oX, oY, oZ};
+            this.size = new double[]{sX, sY, sZ};
+            this.faces = new Face.Builder[6];
+            this.inflate = 0;
+            this.pivot = new double[]{0, 0, 0};
+        }
+
+        public Builder(
+            final double @NotNull [] origin,
+            final double @NotNull [] size
+        ) {
+            this.origin = origin;
+            this.size = size;
+            this.faces = new Face.Builder[6];
+            this.inflate = 0;
+            this.pivot = new double[]{0, 0, 0};
+        }
+
+        public @NotNull Builder setFaces(final double u, final double v) {
+            final double sizeX = this.size[0];
+            final double sizeY = this.size[1];
+            final double sizeZ = this.size[2];
+            this.faces[Direction.UP.getId()] = new Face.Builder(u + sizeZ, v, sizeX, sizeZ);
+            this.faces[Direction.DOWN.getId()] = new Face.Builder(u + sizeX + sizeZ, v + sizeZ, sizeX, -sizeZ);
+            this.faces[Direction.NORTH.getId()] = new Face.Builder(u + sizeZ, v + sizeZ, sizeX, sizeY);
+            this.faces[Direction.SOUTH.getId()] = new Face.Builder(u + (sizeZ * 2) + sizeX, v + sizeZ, sizeX, sizeY);
+            this.faces[Direction.EAST.getId()] = new Face.Builder(u, v + sizeZ, sizeZ, sizeY);
+            this.faces[Direction.WEST.getId()] = new Face.Builder(u + sizeZ + sizeX, v + sizeZ, sizeZ, sizeY);
+            return this;
+        }
+
+        public @NotNull Builder setFace(final @NotNull Direction direction, final @Nullable Face.Builder builder) {
+            this.faces[direction.getId()] = builder;
+            return this;
+        }
+
+        public @NotNull Builder setInflation(final double inflation) {
+            this.inflate = inflation;
+            return this;
+        }
+
+        public @NotNull Builder setPivot(final double x, final double y, final double z) {
+            this.pivot[0] = x;
+            this.pivot[1] = y;
+            this.pivot[2] = z;
+            return this;
+        }
+
+        public @NotNull Builder setRotation(final double x, final double y, final double z) {
+            if (this.rotation == null) this.rotation = new double[3];
+            this.rotation[0] = x;
+            this.rotation[1] = y;
+            this.rotation[2] = z;
+            return this;
+        }
+
+        public @NotNull Builder setMirror() {
+            this.mirror = !this.mirror;
+            return this;
+        }
+
+        protected void mirror() {
+            final Face.Builder west = this.faces[Direction.WEST.getId()];
+            this.faces[Direction.WEST.getId()] = this.faces[Direction.EAST.getId()];
+            this.faces[Direction.EAST.getId()] = west;
+            for (final Face.Builder builder : this.faces) {
+                if (builder == null) continue;
+                builder.setMirror();
+            }
+
+        }
+
+        protected @NotNull Cube build()
+        {
+            if (this.mirror) {
+                mirror();
+            }
+            return new Cube(this.origin, this.size, this.faces, this.inflate, this.pivot, this.rotation);
+        }
+
+        public static class Serializer implements JsonSerializer<Cube.Builder>, JsonDeserializer<Cube.Builder> {
+
+            @Override
+            public Builder deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
+                final JsonObject o = json.getAsJsonObject();
+                final double[] origin = GsonHelper.getAsDoubleArray(o.getAsJsonArray("origin"), 3);
+                final double[] size = GsonHelper.getAsDoubleArray(o.getAsJsonArray("size"), 3);
+                final Builder builder = new Builder(origin, size);
+
+                final JsonElement uvElement = o.get("uv");
+                if (uvElement.isJsonArray()) {
+                    final double[] uv = GsonHelper.getAsDoubleArray(uvElement, 2);
+                    builder.setFaces(uv[0], uv[1]);
+                } else if (uvElement.isJsonObject()) {
+                    final JsonObject uvObject = uvElement.getAsJsonObject();
+                    for (final Map.Entry<String, JsonElement> faceEntries : uvObject.entrySet()) {
+                        final Direction direction = Direction.valueOf(faceEntries.getKey().toUpperCase(Locale.ROOT));
+                        builder.setFace(direction, context.deserialize(faceEntries.getValue(), Face.Builder.class));
+                    }
+                }
+
+                if (o.has("inflate")) builder.setInflation(o.get("inflate").getAsDouble());
+
+                if (o.has("pivot")) {
+                    final double[] pivot = GsonHelper.getAsDoubleArray(o.get("pivot"), 3);
+                    builder.setPivot(pivot[0], pivot[1], pivot[2]);
+                }
+
+                if (o.has("rotation")) {
+                    final double[] rotation = GsonHelper.getAsDoubleArray(o.get("rotation"), 3);
+                    builder.setRotation(rotation[0], rotation[1], rotation[2]);
+                }
+
+                if (o.has("mirror") && o.get("mirror").getAsBoolean()) {
+                    builder.setMirror();
+                }
+
+                return builder;
+            }
+
+            @Override
+            public JsonElement serialize(final Builder src, final Type typeOfSrc, final JsonSerializationContext context) {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+}
diff --git a/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/EntityGeometryMojangData.java b/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/EntityGeometryMojangData.java
new file mode 100644
index 000000000..69312810e
--- /dev/null
+++ b/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/EntityGeometryMojangData.java
@@ -0,0 +1,334 @@
+package org.useless.dragonfly.data.entity.mojang;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.mojang.logging.LogUtils;
+import net.minecraft.client.render.texturepack.TexturePack;
+import net.minecraft.client.render.texturepack.TexturePackList;
+import net.minecraft.core.util.HardIllegalArgumentException;
+import net.minecraft.core.util.collection.NamespaceID;
+import net.minecraft.core.util.collection.Pair;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.useless.dragonfly.data.entity.EntityModelData;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+import org.useless.dragonfly.models.entity.mojang.StaticEntityModelMojang;
+import org.useless.util.GsonHelper;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+public class EntityGeometryMojangData implements EntityModelData {
+    public static final @NotNull String CURRENT_VERSION = "1.8.0";
+
+    public static final int DEFAULT_TEX_WIDTH = 64;
+    public static final int DEFAULT_TEX_HEIGHT = 32;
+
+    protected final static Logger LOGGER = LogUtils.getLogger();
+    protected final static Gson gson = builder().create();
+
+    protected static GsonBuilder builder() {
+        final GsonBuilder builder = new GsonBuilder();
+        builder.setPrettyPrinting();
+        builder.registerTypeAdapter(EntityGeometryMojangData.Builder.class, new EntityGeometryMojangData.Builder.Serializer());
+        builder.registerTypeAdapter(Bone.Builder.class, new Bone.Builder.Serializer());
+        builder.registerTypeAdapter(Cube.Builder.class, new Cube.Builder.Serializer());
+        builder.registerTypeAdapter(Face.Builder.class, new Face.Builder.Serializer());
+        return builder;
+    }
+
+    protected final @NotNull String  modelId;
+
+    public final @NotNull String version;
+    public final double vBoundsWidth;
+    public final double vBoundsHeight;
+    public final double @NotNull [] vBoundsOffset;
+    public final int textureWidth;
+    public final int textureHeight;
+    public final @NotNull Map<@NotNull String, @NotNull Bone> bones;
+    protected EntityGeometryMojangData(
+        @NotNull final String modelId,
+        @NotNull final String version,
+        final double vBoundsWidth,
+        final double vBoundsHeight,
+        final double @NotNull [] vBoundsOffset,
+        final int textureWidth,
+        final int textureHeight,
+        @NotNull final Iterable<Bone.@NotNull Builder> bones
+    ) {
+        this.modelId = modelId;
+
+        this.version = version;
+        this.vBoundsWidth = vBoundsWidth;
+        this.vBoundsHeight = vBoundsHeight;
+        this.vBoundsOffset = vBoundsOffset;
+        this.textureWidth = textureWidth;
+        this.textureHeight = textureHeight;
+        this.bones = new HashMap<>();
+
+        for (final Bone.Builder builder : bones) {
+            @NotNull final Bone bone = builder.build();
+            this.bones.put(bone.name, bone);
+        }
+
+    }
+
+    @Override
+    public @NotNull String modelId() {
+        return this.modelId;
+    }
+
+    @Override
+    public @NotNull StaticEntityModel asModel(final double inflation) {
+        return new StaticEntityModelMojang(this, inflation);
+    }
+
+    public static class Builder {
+        private @NotNull String version;
+        private final double vBoundsWidth;
+        private final double vBoundsHeight;
+        private final double @NotNull [] vBoundsOffset;
+        private int texWidth;
+        private int texHeight;
+        private final @NotNull List<Bone. @NotNull Builder> bones = new ArrayList<>();
+
+        public Builder(final double visualBoundsWidth, final double visualBoundsHeight) {
+            this.version = CURRENT_VERSION;
+            this.vBoundsWidth = visualBoundsWidth;
+            this.vBoundsHeight = visualBoundsHeight;
+            this.vBoundsOffset = new double[]{0, 0, 0};
+            this.texWidth = DEFAULT_TEX_WIDTH;
+            this.texHeight = DEFAULT_TEX_HEIGHT;
+        }
+
+        public @NotNull Builder setVersion(@NotNull final String version) {
+            this.version = version;
+            return this;
+        }
+
+//        public @NotNull Builder setVisualBoundsSize(final double visualBoundsWidth, final double visualBoundsHeight) {
+//            this.vBoundsWidth = visualBoundsWidth;
+//            this.vBoundsHeight = visualBoundsHeight;
+//            return this;
+//        }
+
+        public @NotNull Builder setVisualBoundsOffset(final double offX, final double offY, final double offZ) {
+            this.vBoundsOffset[0] = offX;
+            this.vBoundsOffset[1] = offY;
+            this.vBoundsOffset[2] = offZ;
+            return this;
+        }
+
+        public @NotNull Builder setTextureSize(final int texWidth, final int texHeight) {
+            this.texWidth = texWidth;
+            this.texHeight = texHeight;
+            return this;
+        }
+
+        public @NotNull Builder addBone(final @NotNull Bone.Builder boneBuilder) {
+            this.bones.add(boneBuilder);
+            return this;
+        }
+
+        public EntityGeometryMojangData build(@NotNull final String  modelID) {
+            return new EntityGeometryMojangData(modelID, this.version, this.vBoundsWidth, this.vBoundsHeight, this.vBoundsOffset, this.texWidth, this.texHeight, this.bones);
+        }
+
+        public static class Serializer implements JsonSerializer<EntityGeometryMojangData.Builder>, JsonDeserializer<EntityGeometryMojangData.Builder> {
+
+            @Override
+            public Builder deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
+                final JsonObject object = json.getAsJsonObject();
+                final Builder builder;
+                if (object.has("description")) { // New desc layout
+                    final JsonObject description = object.getAsJsonObject("description");
+                    builder = new Builder(description.get("visible_bounds_width").getAsDouble(), description.get("visible_bounds_height").getAsDouble());
+                    if (description.has("visible_bounds_offset")) {
+                        final double[] offset = GsonHelper.getAsDoubleArray(description.get("visible_bounds_offset"), 3);
+                        builder.setVisualBoundsOffset(offset[0], offset[1], offset[2]);
+                    }
+                    if (description.has("texture_width") && description.has("texture_height")) {
+                        final int width = description.get("texture_width").getAsInt();
+                        final int height = description.get("texture_height").getAsInt();
+                        builder.setTextureSize(width, height);
+                    }
+                } else { // Old desc layout
+                    builder = new Builder(object.get("visible_bounds_width").getAsDouble(), object.get("visible_bounds_height").getAsDouble());
+                    if (object.has("visible_bounds_offset")) {
+                        final double[] offset = GsonHelper.getAsDoubleArray(object.get("visible_bounds_offset"), 3);
+                        builder.setVisualBoundsOffset(offset[0], offset[1], offset[2]);
+                    }
+                    if (object.has("texturewidth") && object.has("textureheight")) {
+                        final int width = object.get("texturewidth").getAsInt();
+                        final int height = object.get("textureheight").getAsInt();
+                        builder.setTextureSize(width, height);
+                    }
+                }
+
+                if (object.has("bones")) {
+                    final JsonArray bones = object.getAsJsonArray("bones");
+                    for (final JsonElement e : bones) {
+                        builder.addBone(context.deserialize(e, Bone.Builder.class));
+                    }
+                }
+                return builder;
+            }
+
+            @Override
+            public JsonElement serialize(final Builder src, final Type typeOfSrc, final JsonSerializationContext context) {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+
+    public static class Cache {
+        protected static final Map<String, EntityGeometryMojangData> modelDataCache = new HashMap<>();
+
+        protected static final @NotNull Map<@NotNull NamespaceID, @NotNull Map<@NotNull String, @NotNull Pair<String, Double>>> localModelMappings = new HashMap<>();
+
+        public static @NotNull StaticEntityModel getFallbackModel() {
+            return new EntityGeometryMojangData.Builder(1, 1)
+                .addBone(
+                    new Bone.Builder("cube")
+                        .addCube(new Cube.Builder(-8, 0, -8, 16, 16, 16)
+                            .setFaces(0, 0))
+                ).build("geometry.missing").asModel(0);
+        }
+
+        public static @NotNull StaticEntityModel getModel(@NotNull final String id, final double inflation) {
+            final EntityGeometryMojangData data = getGeometry(id);
+            if (data == null) {
+                LOGGER.error("No model data for model '{}'!", id);
+                return getFallbackModel();
+            }
+            return data.asModel(inflation);
+        }
+
+        public static @NotNull StaticEntityModel getModelForEntity(@NotNull final NamespaceID namespaceID, @NotNull final String localModelId) {
+            if (localModelMappings.containsKey(namespaceID)) {
+                final Map<String, Pair<String, Double>> modelMap = localModelMappings.get(namespaceID);
+                final Pair<String, Double> pair = modelMap.get(localModelId);
+                if (pair == null) return getFallbackModel();
+                return getModel(pair.getLeft(), pair.getRight());
+            }
+            return getFallbackModel();
+        }
+
+        public static @Nullable EntityGeometryMojangData getGeometry(@NotNull final String id) {
+            return modelDataCache.get(id);
+        }
+
+        public static void loadModelsFromResource(final @NotNull InputStream stream) {
+            final JsonObject modelData = JsonParser.parseReader(new InputStreamReader(stream)).getAsJsonObject();
+            final String version = modelData.get("format_version").getAsString();
+            if (modelData.has("minecraft:geometry")) { // Newer style bedrock entity layout
+                final JsonArray geometries = modelData.getAsJsonArray("minecraft:geometry");
+                for (final JsonElement e : geometries) {
+                    final JsonObject object = e.getAsJsonObject();
+                    final String id = object.getAsJsonObject("description").get("identifier").getAsString();
+                    try {
+                        final EntityGeometryMojangData data = gson.fromJson(e, EntityGeometryMojangData.Builder.class).build(id);
+                        modelDataCache.put(data.modelId(), data);
+                    } catch (final Exception ex) {
+                        LOGGER.warn("Failed to load json data with key {} as geometry data!", id, ex);
+                        continue;
+                    }
+                }
+            } else { // Older style bedrock entity layout
+                for (final Map.Entry<String, JsonElement> entry : modelData.entrySet()) {
+                    if ("format_version".equals(entry.getKey())) continue;
+                    final String id = entry.getKey();
+                    try {
+                        final EntityGeometryMojangData data = gson.fromJson(entry.getValue(), EntityGeometryMojangData.Builder.class).build(id);
+                        modelDataCache.put(data.modelId(), data);
+                    } catch (final Exception e) {
+                        LOGGER.warn("Failed to load json data with key {} as geometry data!", entry.getKey(), e);
+                        continue;
+                    }
+                }
+            }
+        }
+
+        public static void reload(@NotNull final TexturePackList packList) {
+            modelDataCache.clear();
+
+            final Collection<TexturePack> packs = new ArrayList<>();
+            packs.add(packList.getDefaultTexturePack());
+            packs.addAll(packList.selectedPacks);
+
+            final Collection<String> modelPaths = new HashSet<>();
+
+            for (final TexturePack pack : packs) {
+                try (final @Nullable InputStream stream = pack.getResourceAsStream("/assets/minecraft/models/entity/models.json")) {
+                    if (stream == null) continue;
+                    final JsonObject manifestObject = JsonParser.parseReader(new InputStreamReader(stream)).getAsJsonObject();
+                    if (manifestObject.has("model_paths")) {
+                        final JsonArray paths = manifestObject.getAsJsonArray("model_paths");
+                        for (final JsonElement e : paths) {
+                            modelPaths.add(e.getAsString());
+                        }
+                    }
+                    if (manifestObject.has("renderers")) {
+                        final JsonObject renderersObj = manifestObject.getAsJsonObject("renderers");
+                        for (final Map.Entry<String, JsonElement> entry : renderersObj.entrySet()) {
+                            final NamespaceID id;
+                            try {
+                                id = new NamespaceID(entry.getKey());
+                            } catch (final HardIllegalArgumentException exception) {
+                                LOGGER.error("Id '{}' is malformed!", entry.getKey(), exception);
+                                continue;
+                            }
+                            localModelMappings.putIfAbsent(id, new HashMap<>());
+                            final Map<String, Pair<String, Double>> modelMappings = localModelMappings.get(id);
+                            final JsonObject mappingsObject = entry.getValue().getAsJsonObject();
+                            for (final Map.Entry<String, JsonElement> mappingEntry : mappingsObject.entrySet()) {
+                                final JsonElement element = mappingEntry.getValue();
+                                if (element.isJsonPrimitive()) {
+                                    modelMappings.put(mappingEntry.getKey(), Pair.of(mappingEntry.getValue().getAsString(), 0D));
+                                } else if (element.isJsonObject()) {
+                                    final JsonObject mapping = element.getAsJsonObject();
+                                    modelMappings.put(mappingEntry.getKey(), Pair.of(mapping.get("model").getAsString(), mapping.has("inflation") ? mapping.get("inflation").getAsDouble() : 0D));
+                                } else {
+                                    LOGGER.warn("Unknown format for element '{}' of key '{}' in pack '{}'", element, mappingEntry.getKey(), pack.packId);
+                                }
+                            }
+                        }
+                    }
+                } catch (final Exception e) {
+                    LOGGER.error("Exception while reading entity models manifest in pack '{}'!", pack.packId, e);
+                }
+            }
+
+            for (final TexturePack pack : packs) {
+                for (final String s : modelPaths) {
+                    try (final @Nullable InputStream stream = pack.getResourceAsStream(s)) {
+                        if (stream == null) continue;
+                        loadModelsFromResource(stream);
+                    } catch (final IOException e) {
+                        LOGGER.warn("Failed to load data for resource at {}!", s, e);
+                    } catch (final Exception e) {
+                        LOGGER.warn("Error occurred when reading load data for resource at {}!", s, e);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/Face.java b/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/Face.java
new file mode 100644
index 000000000..768888366
--- /dev/null
+++ b/game/client/src/main/java/org/useless/dragonfly/data/entity/mojang/Face.java
@@ -0,0 +1,74 @@
+package org.useless.dragonfly.data.entity.mojang;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import org.jetbrains.annotations.NotNull;
+import org.useless.util.GsonHelper;
+
+import java.lang.reflect.Type;
+
+public class Face {
+    public final double @NotNull [] uv;
+    public final double @NotNull [] uv_size;
+    public final int uv_rotation;
+
+    protected Face(final double @NotNull [] uv, final double @NotNull [] uvSize, final int uv_rotation) {
+        this.uv = uv;
+        this.uv_size = uvSize;
+        this.uv_rotation = uv_rotation;
+    }
+
+    public static class Builder {
+        private final double @NotNull [] uv;
+        private final double @NotNull [] uv_size;
+        private int uv_rotation;
+
+        public Builder(final double u, final double v, final double uSize, final double vSize) {
+            this.uv = new double[]{u, v};
+            this.uv_size = new double[]{uSize, vSize};
+            this.uv_rotation = 0;
+        }
+
+        public Builder(final double @NotNull [] uv, final double @NotNull [] uvSize) {
+            this.uv = uv;
+            this.uv_size = uvSize;
+            this.uv_rotation = 0;
+        }
+
+        public @NotNull Builder setUVRotation(final int rotation) {
+            this.uv_rotation = ((rotation + 360) % 360)/90;
+            return this;
+        }
+
+        protected void setMirror() {
+            this.uv[0] += this.uv_size[0];
+            this.uv_size[0] *= -1;
+        }
+
+        protected @NotNull Face build() {
+            return new Face(this.uv, this.uv_size, this.uv_rotation);
+        }
+
+        public static class Serializer implements JsonSerializer<Face.Builder>, JsonDeserializer<Face.Builder> {
+            @Override
+            public Builder deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
+                final JsonObject object = json.getAsJsonObject();
+                final double[] uv = GsonHelper.getAsDoubleArray(object.get("uv"), 2);
+                final double[] uvSize = GsonHelper.getAsDoubleArray(object.get("uv_size"), 2);
+                final Builder builder = new Builder(uv, uvSize);
+                if (object.has("uv_rotation")) builder.setUVRotation(object.get("uv_rotation").getAsInt());
+                return builder;
+            }
+
+            @Override
+            public JsonElement serialize(final Builder src, final Type typeOfSrc, final JsonSerializationContext context) {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+}
diff --git a/game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticModelMojang.java b/game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticBlockModelMojang.java
similarity index 99%
rename from game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticModelMojang.java
rename to game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticBlockModelMojang.java
index 6490736fc..f01219ef5 100644
--- a/game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticModelMojang.java
+++ b/game/client/src/main/java/org/useless/dragonfly/models/block/mojang/StaticBlockModelMojang.java
@@ -43,7 +43,7 @@ import static org.useless.dragonfly.data.block.mojang.CompiledBlockModelMojangDa
 import static org.useless.dragonfly.data.block.mojang.CompiledBlockModelMojangData.C_Element.VERTEX_TOP_LEFT;
 import static org.useless.dragonfly.data.block.mojang.CompiledBlockModelMojangData.C_Element.VERTEX_TOP_RIGHT;
 
-public class StaticModelMojang implements StaticBlockModel {
+public class StaticBlockModelMojang implements StaticBlockModel {
     protected static final Minecraft MC = Minecraft.getMinecraft();
     protected static final LightingCache LIGHTING_CACHE = new LightingCache();
 
@@ -56,7 +56,7 @@ public class StaticModelMojang implements StaticBlockModel {
     protected static final byte[] V_LEF_Z = new byte[] {0, 0, 0, 0, 0, 0};
 
     protected final CompiledBlockModelMojangData compiled;
-    public StaticModelMojang(BlockModelMojangData data) {
+    public StaticBlockModelMojang(BlockModelMojangData data) {
         this.compiled = new CompiledBlockModelMojangData(data);
     }
 
diff --git a/game/client/src/main/java/org/useless/dragonfly/models/entity/BoneTransform.java b/game/client/src/main/java/org/useless/dragonfly/models/entity/BoneTransform.java
new file mode 100644
index 000000000..1e2d3cfc6
--- /dev/null
+++ b/game/client/src/main/java/org/useless/dragonfly/models/entity/BoneTransform.java
@@ -0,0 +1,32 @@
+package org.useless.dragonfly.models.entity;
+
+public final class BoneTransform {
+    public double posX = 0;
+    public double posY = 0;
+    public double posZ = 0;
+
+    public double rotX = 0;
+    public double rotY = 0;
+    public double rotZ = 0;
+
+    public double scaleX = 1;
+    public double scaleY = 1;
+    public double scaleZ = 1;
+
+    public boolean visible = true;
+    public void reset() {
+        this.posX = 0;
+        this.posY = 0;
+        this.posZ = 0;
+
+        this.rotX = 0;
+        this.rotY = 0;
+        this.rotZ = 0;
+
+        this.scaleX = 1;
+        this.scaleY = 1;
+        this.scaleZ = 1;
+
+        this.visible = true;
+    }
+}
diff --git a/game/client/src/main/java/org/useless/dragonfly/models/entity/StaticEntityModel.java b/game/client/src/main/java/org/useless/dragonfly/models/entity/StaticEntityModel.java
new file mode 100644
index 000000000..737efb9db
--- /dev/null
+++ b/game/client/src/main/java/org/useless/dragonfly/models/entity/StaticEntityModel.java
@@ -0,0 +1,13 @@
+package org.useless.dragonfly.models.entity;
+
+import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.core.util.phys.AABB;
+import org.jetbrains.annotations.NotNull;
+
+public interface StaticEntityModel {
+    void resetBones();
+    @NotNull BoneTransform getTransform(@NotNull String boneId);
+    @NotNull AABB visibleBounds();
+    void translateToBone(@NotNull String boneId);
+    void render(@NotNull Tessellator tessellator);
+}
diff --git a/game/client/src/main/java/org/useless/dragonfly/models/entity/mojang/StaticEntityModelMojang.java b/game/client/src/main/java/org/useless/dragonfly/models/entity/mojang/StaticEntityModelMojang.java
new file mode 100644
index 000000000..f5434543a
--- /dev/null
+++ b/game/client/src/main/java/org/useless/dragonfly/models/entity/mojang/StaticEntityModelMojang.java
@@ -0,0 +1,469 @@
+package org.useless.dragonfly.models.entity.mojang;
+
+import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.core.util.helper.Direction;
+import net.minecraft.core.util.helper.MathHelper;
+import net.minecraft.core.util.phys.AABB;
+import org.jetbrains.annotations.NotNull;
+import org.lwjgl.opengl.GL11;
+import org.useless.dragonfly.data.entity.mojang.Bone;
+import org.useless.dragonfly.data.entity.mojang.Cube;
+import org.useless.dragonfly.data.entity.mojang.EntityGeometryMojangData;
+import org.useless.dragonfly.data.entity.mojang.Face;
+import org.useless.dragonfly.models.entity.BoneTransform;
+import org.useless.dragonfly.models.entity.StaticEntityModel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class StaticEntityModelMojang implements StaticEntityModel {
+    private static final BoneTransform DUMMY_TRANSFORM = new BoneTransform();
+    public final @NotNull Map<@NotNull String, @NotNull BoneTransform> transformMap = new HashMap<>();
+    public final @NotNull BoneTransform @NotNull [] transforms;
+    public final @NotNull Bone @NotNull [] bones;
+    public final EntityGeometryMojangData data;
+    public final double inflation;
+    protected final AABB visBounds;
+    public StaticEntityModelMojang(final @NotNull EntityGeometryMojangData data, final double inflation) {
+        this.data = data;
+        this.transforms = new BoneTransform[this.data.bones.size()];
+        this.bones = new Bone[this.data.bones.size()];
+        this.inflation = inflation;
+
+        int i = 0;
+        for (final Map.Entry<String, Bone> entry : this.data.bones.entrySet()) {
+            final BoneTransform transform = new BoneTransform();
+            this.transformMap.put(entry.getKey(), transform);
+            this.transforms[i] = transform;
+            this.bones[i] = entry.getValue();
+            i++;
+        }
+
+        this.visBounds = AABB.getPermanentBB(
+            (this.data.vBoundsOffset[0] - this.data.vBoundsWidth /2),
+            (this.data.vBoundsOffset[1] - this.data.vBoundsHeight/2),
+            (this.data.vBoundsOffset[2] - this.data.vBoundsWidth /2),
+            (this.data.vBoundsOffset[0] + this.data.vBoundsWidth /2),
+            (this.data.vBoundsOffset[1] + this.data.vBoundsHeight/2),
+            (this.data.vBoundsOffset[2] + this.data.vBoundsWidth /2));
+    }
+
+    @Override
+    public void resetBones() {
+        for (int i = 0; i < this.transforms.length; i++) {
+            this.transforms[i].reset();
+        }
+    }
+
+    @Override
+    public @NotNull BoneTransform getTransform(@NotNull final String boneId) {
+        return this.transformMap.getOrDefault(boneId, DUMMY_TRANSFORM);
+    }
+
+    @Override
+    public @NotNull AABB visibleBounds() {
+        return this.visBounds;
+    }
+
+    @Override
+    public void translateToBone(@NotNull final String boneId) {
+        final Bone bone = this.data.bones.get(boneId);
+        if (bone == null) return;
+        boneTransform(bone);
+        GL11.glTranslated(bone.pivot[0], bone.pivot[1], bone.pivot[2]);
+    }
+
+    @Override
+    public void render(@NotNull final Tessellator tessellator) {
+        for (int i = 0; i < this.bones.length; i++) {
+            final Bone bone = this.bones[i];
+            GL11.glPushMatrix();
+            if (!boneTransform(bone)) {
+                renderBone(tessellator, bone);
+            }
+            GL11.glPopMatrix();
+        }
+    }
+
+    protected boolean boneTransform(@NotNull final Bone bone) {
+        boolean hidden = false;
+        final Bone parent = bone.parent != null ? this.data.bones.get(bone.parent) : null;
+        if (parent != null) {
+            hidden |= boneTransform(parent);
+        }
+        final BoneTransform transform = this.transformMap.get(bone.name);
+        hidden |= !transform.visible;
+        GL11.glTranslated(bone.pivot[0], bone.pivot[1], bone.pivot[2]);
+        GL11.glTranslated(transform.posX, transform.posY, transform.posZ);
+        GL11.glRotated(-(transform.rotZ * MathHelper.RAD_TO_DEG) - bone.rotation[2], 0, 0, 1);
+        GL11.glRotated((transform.rotY * MathHelper.RAD_TO_DEG) + bone.rotation[1], 0, 1, 0);
+        GL11.glRotated(-(transform.rotX * MathHelper.RAD_TO_DEG) - bone.rotation[0], 1, 0, 0);
+        GL11.glTranslated(-bone.pivot[0], -bone.pivot[1], -bone.pivot[2]);
+        GL11.glScaled(transform.scaleX, transform.scaleY, transform.scaleZ);
+        return hidden;
+    }
+
+    private final double[] uvsBuffer = new double[8];
+    protected void renderBone(@NotNull final Tessellator tessellator, @NotNull final Bone bone) {
+        tessellator.startDrawingQuads();
+        for (final Cube cube : bone.cubes) {
+            final double minX = cube.origin[0] - (cube.inflate + bone.inflate + this.inflation);
+            final double minY = cube.origin[1] - (cube.inflate + bone.inflate + this.inflation);
+            final double minZ = cube.origin[2] - (cube.inflate + bone.inflate + this.inflation);
+
+            final double maxX = minX + cube.size[0] + (cube.inflate + bone.inflate + this.inflation) * 2;
+            final double maxY = minY + cube.size[1] + (cube.inflate + bone.inflate + this.inflation) * 2;
+            final double maxZ = minZ + cube.size[2] + (cube.inflate + bone.inflate + this.inflation) * 2;
+            
+            if (cube.rotation == null) {
+                // Top
+                Face face = cube.faces[Direction.UP.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMin;
+                    this.uvsBuffer[2] = uMin;
+                    this.uvsBuffer[4] = uMax;
+                    this.uvsBuffer[6] = uMax;
+
+                    this.uvsBuffer[1] = vMin;
+                    this.uvsBuffer[3] = vMax;
+                    this.uvsBuffer[5] = vMax;
+                    this.uvsBuffer[7] = vMin;
+
+                    tessellator.setNormal(0, 1, 0);
+                    tessellator.addVertexWithUV(minX, maxY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(minX, maxY, minZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, maxY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, maxY, maxZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8]);
+                }
+
+                // Bottom
+                face = cube.faces[Direction.DOWN.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMin;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMax;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMax;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMin;
+
+                    tessellator.setNormal(0, -1, 0);
+                    tessellator.addVertexWithUV(minX, minY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, minY, maxZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, minY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(minX, minY, minZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8]);
+                }
+
+                // Front
+                face = cube.faces[Direction.NORTH.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMin;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMax;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMax;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMin;
+
+                    tessellator.setNormal(0, 0, -1);
+                    tessellator.addVertexWithUV(minX, minY, minZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, minY, minZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, maxY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(minX, maxY, minZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8]);
+                }
+
+                // Back
+                face = cube.faces[Direction.SOUTH.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMax;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMin;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMin;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMax;
+
+                    tessellator.setNormal(0, 0, 1);
+                    tessellator.addVertexWithUV(minX, minY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(minX, maxY, maxZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, maxY, maxZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, minY, maxZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8]);
+                }
+
+                // Right
+                face = cube.faces[Direction.WEST.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMax;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMin;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMin;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMax;
+
+                    tessellator.setNormal(1, 0, 0);
+                    tessellator.addVertexWithUV(maxX, minY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, maxY, maxZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, maxY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(maxX, minY, minZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8]);
+                }
+
+                // Left
+                face = cube.faces[Direction.EAST.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMin;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMax;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMax;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMin;
+
+                    tessellator.setNormal(-1, 0, 0);
+                    tessellator.addVertexWithUV(minX, minY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(minX, minY, minZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(minX, maxY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8]);
+                    tessellator.addVertexWithUV(minX, maxY, maxZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8]);
+                }
+            }
+            else {
+                // Top
+                Face face = cube.faces[Direction.UP.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMin;
+                    this.uvsBuffer[2] = uMin;
+                    this.uvsBuffer[4] = uMax;
+                    this.uvsBuffer[6] = uMax;
+
+                    this.uvsBuffer[1] = vMin;
+                    this.uvsBuffer[3] = vMax;
+                    this.uvsBuffer[5] = vMax;
+                    this.uvsBuffer[7] = vMin;
+
+                    tessellator.setNormal(0, 1, 0);
+                    addRotatedVertex(tessellator, minX, maxY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, minX, maxY, minZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, maxY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, maxY, maxZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+
+                }
+
+                // Bottom
+                face = cube.faces[Direction.DOWN.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMin;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMax;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMax;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMin;
+
+                    tessellator.setNormal(0, -1, 0);
+                    addRotatedVertex(tessellator, minX, minY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, minY, maxZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, minY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, minX, minY, minZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                }
+
+                // Front
+                face = cube.faces[Direction.NORTH.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMin;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMax;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMax;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMin;
+
+                    tessellator.setNormal(0, 0, -1);
+                    addRotatedVertex(tessellator, minX, minY, minZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, minY, minZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, maxY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, minX, maxY, minZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                }
+
+                // Back
+                face = cube.faces[Direction.SOUTH.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMax;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMin;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMin;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMax;
+
+                    tessellator.setNormal(0, 0, 1);
+                    addRotatedVertex(tessellator, minX, minY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, minX, maxY, maxZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, maxY, maxZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, minY, maxZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                }
+
+                // Right
+                face = cube.faces[Direction.WEST.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMax;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMin;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMin;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMax;
+
+                    tessellator.setNormal(1, 0, 0);
+                    addRotatedVertex(tessellator, maxX, minY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, maxY, maxZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, maxY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, maxX, minY, minZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                }
+
+                // Left
+                face = cube.faces[Direction.EAST.getId()];
+                if (face != null) {
+                    final double uMin = (face.uv[0]) / this.data.textureWidth;
+                    final double uMax = (face.uv[0] + face.uv_size[0]) / this.data.textureWidth;
+                    final double vMin = (face.uv[1]) / this.data.textureHeight;
+                    final double vMax = (face.uv[1] + face.uv_size[1])  / this.data.textureHeight;
+
+                    this.uvsBuffer[0] = uMin;
+                    this.uvsBuffer[2] = uMax;
+                    this.uvsBuffer[4] = uMax;
+                    this.uvsBuffer[6] = uMin;
+
+                    this.uvsBuffer[1] = vMax;
+                    this.uvsBuffer[3] = vMax;
+                    this.uvsBuffer[5] = vMin;
+                    this.uvsBuffer[7] = vMin;
+
+                    tessellator.setNormal(-1, 0, 0);
+                    addRotatedVertex(tessellator, minX, minY, maxZ, this.uvsBuffer[(face.uv_rotation * 2) % 8], this.uvsBuffer[(1 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, minX, minY, minZ, this.uvsBuffer[(2 + face.uv_rotation * 2) % 8], this.uvsBuffer[(3 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, minX, maxY, minZ, this.uvsBuffer[(4 + face.uv_rotation * 2) % 8], this.uvsBuffer[(5 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                    addRotatedVertex(tessellator, minX, maxY, maxZ, this.uvsBuffer[(6 + face.uv_rotation * 2) % 8], this.uvsBuffer[(7 + face.uv_rotation * 2) % 8], cube.pivot, cube.rotation);
+                }
+            }
+        }
+        tessellator.draw();
+    }
+
+    protected static void addRotatedVertex(@NotNull final Tessellator tessellator, final double x, final double y, final double z, final double u, final double v, final double @NotNull [] pivot, final double @NotNull [] rotation) {
+        double _x = x - pivot[0];
+        double _y = y - pivot[1];
+        double _z = z - pivot[2];
+
+        float sin;
+        float cos;
+        double nx;
+        double ny;
+        double nz;
+
+        // X
+        sin = MathHelper.sin((float) (-rotation[0] * MathHelper.DEG_TO_RAD));
+        cos = MathHelper.cos((float) (-rotation[0] * MathHelper.DEG_TO_RAD));
+        nx = _x;
+        ny = _y * cos - _z * sin;
+        nz = _z * cos + _y * sin;
+        _x = nx;
+        _y = ny;
+        _z = nz;
+
+        // Y
+        sin = MathHelper.sin((float) (-rotation[1] * MathHelper.DEG_TO_RAD));
+        cos = MathHelper.cos((float) (-rotation[1] * MathHelper.DEG_TO_RAD));
+        nx = _x * cos - _z * sin;
+        ny = _y;
+        nz = _z * cos + _x * sin;
+        _x = nx;
+        _y = ny;
+        _z = nz;
+
+        // Z
+        sin = MathHelper.sin((float) (-rotation[2] * MathHelper.DEG_TO_RAD));
+        cos = MathHelper.cos((float) (-rotation[2] * MathHelper.DEG_TO_RAD));
+        nx = _x * cos - _y * sin;
+        ny = _y * cos + _x * sin;
+        nz = _z;
+        _x = nx;
+        _y = ny;
+        _z = nz;
+
+
+        tessellator.addVertexWithUV(_x + pivot[0], _y + pivot[1], _z + pivot[2], u, v);
+    }
+}
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/boat/boat.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/boat/boat.geo.json
new file mode 100644
index 000000000..f782bf9fe
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/boat/boat.geo.json
@@ -0,0 +1,60 @@
+{
+	"format_version": "1.10.0",
+	"geometry.boat": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 3,
+		"visible_bounds_height": 1.5,
+		"visible_bounds_offset": [0, 0.25, 0],
+		"bones": [
+			{
+				"name": "root",
+				"pivot": [0, 0, 0]
+			},
+			{
+				"name": "bottom",
+				"parent": "root",
+				"pivot": [0, -4, 0],
+				"rotation": [90, 0, 0],
+				"cubes": [
+					{"origin": [-12, -12, -2], "size": [24, 16, 4], "uv": [0, 8]}
+				]
+			},
+			{
+				"name": "back",
+				"parent": "root",
+				"pivot": [-9, -4, 0],
+				"rotation": [0, 270, 0],
+				"cubes": [
+					{"origin": [-19, -2, 1], "size": [20, 6, 2], "uv": [0, 0]}
+				]
+			},
+			{
+				"name": "front",
+				"parent": "root",
+				"pivot": [9, -4, 0],
+				"rotation": [0, 90, 0],
+				"cubes": [
+					{"origin": [-1, -2, 1], "size": [20, 6, 2], "uv": [0, 0]}
+				]
+			},
+			{
+				"name": "right",
+				"parent": "root",
+				"pivot": [0, -4, -7],
+				"rotation": [0, 180, 0],
+				"cubes": [
+					{"origin": [-10, -2, -6], "size": [20, 6, 2], "uv": [0, 0]}
+				]
+			},
+			{
+				"name": "left",
+				"parent": "root",
+				"pivot": [0, -4, 7],
+				"cubes": [
+					{"origin": [-10, -2, 8], "size": [20, 6, 2], "uv": [0, 0]}
+				]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/cannonball/cannonball.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/cannonball/cannonball.geo.json
new file mode 100644
index 000000000..35e4064ed
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/cannonball/cannonball.geo.json
@@ -0,0 +1,29 @@
+{
+	"format_version": "1.12.0",
+	"minecraft:geometry": [
+		{
+			"description": {
+				"identifier": "geometry.cannonball",
+				"texture_width": 64,
+				"texture_height": 32,
+				"visible_bounds_width": 2,
+				"visible_bounds_height": 1.5,
+				"visible_bounds_offset": [0, 0.25, 0]
+			},
+			"bones": [
+				{
+					"name": "root",
+					"pivot": [0, 0, 0]
+				},
+				{
+					"name": "ball",
+					"parent": "root",
+					"pivot": [0, 0, 0],
+					"cubes": [
+						{"origin": [-4, -4, -4], "size": [8, 8, 8], "uv": [0, 0]}
+					]
+				}
+			]
+		}
+	]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/chicken/chicken.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/chicken/chicken.geo.json
new file mode 100644
index 000000000..08f151021
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/chicken/chicken.geo.json
@@ -0,0 +1,79 @@
+{
+	"format_version": "1.12.0",
+	"minecraft:geometry": [
+		{
+			"description": {
+				"identifier": "geometry.chicken",
+				"texture_width": 64,
+				"texture_height": 32,
+				"visible_bounds_width": 2,
+				"visible_bounds_height": 2.25,
+				"visible_bounds_offset": [0, 0.875, 0]
+			},
+			"bones": [
+				{
+					"name": "body",
+					"pivot": [0, 8, 0],
+					"rotation": [90, 0, 0],
+					"cubes": [
+						{"origin": [-3, 4, -3], "size": [6, 8, 6], "uv": [0, 9]}
+					]
+				},
+				{
+					"name": "head",
+					"pivot": [0, 9, -4],
+					"cubes": [
+						{"origin": [-2, 9, -6], "size": [4, 6, 3], "uv": [0, 0]}
+					],
+					"locators": {
+						"lead": [0, 9, -4]
+					}
+				},
+				{
+					"name": "comb",
+					"parent": "head",
+					"pivot": [0, 9, -4],
+					"cubes": [
+						{"origin": [-1, 9, -7], "size": [2, 2, 2], "uv": [14, 4]}
+					]
+				},
+				{
+					"name": "beak",
+					"parent": "head",
+					"pivot": [0, 9, -4],
+					"cubes": [
+						{"origin": [-2, 11, -8], "size": [4, 2, 2], "uv": [14, 0]}
+					]
+				},
+				{
+					"name": "leg0",
+					"pivot": [-2, 5, 1],
+					"cubes": [
+						{"origin": [-3, 0, -2], "size": [3, 5, 3], "uv": [26, 0]}
+					]
+				},
+				{
+					"name": "leg1",
+					"pivot": [1, 5, 1],
+					"cubes": [
+						{"origin": [0, 0, -2], "size": [3, 5, 3], "uv": [26, 0]}
+					]
+				},
+				{
+					"name": "wing0",
+					"pivot": [-3, 11, 0],
+					"cubes": [
+						{"origin": [-4, 7, -3], "size": [1, 4, 6], "uv": [24, 13]}
+					]
+				},
+				{
+					"name": "wing1",
+					"pivot": [3, 11, 0],
+					"cubes": [
+						{"origin": [3, 7, -3], "size": [1, 4, 6], "uv": [24, 13]}
+					]
+				}
+			]
+		}
+	]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/cow/cow.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/cow/cow.geo.json
new file mode 100644
index 000000000..e28557297
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/cow/cow.geo.json
@@ -0,0 +1,79 @@
+{
+	"format_version": "1.12.0",
+	"minecraft:geometry": [
+		{
+			"description": {
+				"identifier": "geometry.cow",
+				"texture_width": 64,
+				"texture_height": 32,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 3.125,
+				"visible_bounds_offset": [0, 1.4375, 0]
+			},
+			"bones": [
+				{
+					"name": "body",
+					"pivot": [0, 19, 2],
+					"rotation": [90, 0, 0],
+					"cubes": [
+						{
+							"origin": [-6, 11, -5],
+							"size": [12, 18, 10],
+							"uv": {
+								"north": {"uv": [28, 14], "uv_size": [12, 18]},
+								"east": {"uv": [18, 14], "uv_size": [10, 18]},
+								"south": {"uv": [50, 14], "uv_size": [12, 18]},
+								"west": {"uv": [40, 14], "uv_size": [10, 18]},
+								"up": {"uv": [28, 4], "uv_size": [12, 10]},
+								"down": {"uv": [40, 4], "uv_size": [12, 10]}
+							}
+						},
+						{"origin": [-2, 12, -7], "size": [4, 6, 2], "uv": [52, 0]}
+					]
+				},
+				{
+					"name": "head",
+					"pivot": [0, 20, -8],
+					"cubes": [
+						{"origin": [-4, 16, -14], "size": [8, 8, 6], "uv": [0, 0]},
+						{"origin": [-5, 22, -12], "size": [1, 3, 1], "uv": [22, 0]},
+						{"origin": [4, 22, -12], "size": [1, 3, 1], "uv": [22, 0]}
+					],
+					"locators": {
+						"lead": [0, 20, -8]
+					}
+				},
+				{
+					"name": "leg0",
+					"pivot": [-4, 12, 7],
+					"cubes": [
+						{"origin": [-6, 0, 5], "size": [4, 12, 4], "uv": [0, 16]}
+					]
+				},
+				{
+					"name": "leg1",
+					"pivot": [4, 12, 7],
+					"mirror": true,
+					"cubes": [
+						{"origin": [2, 0, 5], "size": [4, 12, 4], "uv": [0, 16]}
+					]
+				},
+				{
+					"name": "leg2",
+					"pivot": [-4, 12, -6],
+					"cubes": [
+						{"origin": [-6, 0, -7], "size": [4, 12, 4], "uv": [0, 16]}
+					]
+				},
+				{
+					"name": "leg3",
+					"pivot": [4, 12, -6],
+					"mirror": true,
+					"cubes": [
+						{"origin": [2, 0, -7], "size": [4, 12, 4], "uv": [0, 16]}
+					]
+				}
+			]
+		}
+	]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/creeper/creeper.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/creeper/creeper.geo.json
new file mode 100644
index 000000000..be16fb9b0
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/creeper/creeper.geo.json
@@ -0,0 +1,120 @@
+{
+	"format_version": "1.8.0",
+	"geometry.creeper": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 4,
+		"visible_bounds_height": 3.25,
+		"visible_bounds_offset": [0, 1.375, 0],
+		"bones": [
+			{
+				"name": "body",
+				"pivot": [0, 0, 0],
+				"cubes": [
+					{"origin": [-4, 6, -2], "size": [8, 12, 4], "uv": [16, 16]}
+				]
+			},
+			{
+				"name": "head",
+				"parent": "body",
+				"pivot": [0, 18, 0],
+				"cubes": [
+					{"origin": [-4, 18, -4], "size": [8, 8, 8], "uv": [0, 0]}
+				]
+			},
+			{
+				"name": "leg0",
+				"parent": "body",
+				"pivot": [-2, 6, 4],
+				"cubes": [
+					{"origin": [-4, 0, 2], "size": [4, 6, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leg1",
+				"parent": "body",
+				"pivot": [2, 6, 4],
+				"cubes": [
+					{"origin": [0, 0, 2], "size": [4, 6, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leg2",
+				"parent": "body",
+				"pivot": [-2, 6, -4],
+				"cubes": [
+					{"origin": [-4, 0, -6], "size": [4, 6, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leg3",
+				"parent": "body",
+				"pivot": [2, 6, -4],
+				"cubes": [
+					{"origin": [0, 0, -6], "size": [4, 6, 4], "uv": [0, 16]}
+				]
+			}
+		]
+	},
+	"geometry.creeper.charged": {
+		"visible_bounds_width": 1,
+		"visible_bounds_height": 2,
+		"visible_bounds_offset": [0, 0.75, 0],
+		"texturewidth": 64,
+		"textureheight": 32,
+		"bones": [
+			{
+				"name": "body",
+				"cubes": [
+					{"origin": [-4, 6, -2], "size": [8, 12, 4], "uv": [16, 16]}
+				],
+				"inflate": 1
+			},
+			{
+				"name": "head",
+				"parent": "body",
+				"pivot": [0, 18, 0],
+				"cubes": [
+					{"origin": [-4, 18, -4], "size": [8, 8, 8], "uv": [0, 0]}
+				],
+				"inflate": 1
+			},
+			{
+				"name": "leg0",
+				"parent": "body",
+				"pivot": [-2, 6, 4],
+				"cubes": [
+					{"origin": [-4, 0, 2], "size": [4, 6, 4], "uv": [0, 16]}
+				],
+				"inflate": 1
+			},
+			{
+				"name": "leg1",
+				"parent": "body",
+				"pivot": [2, 6, 4],
+				"cubes": [
+					{"origin": [0, 0, 2], "size": [4, 6, 4], "uv": [0, 16]}
+				],
+				"inflate": 1
+			},
+			{
+				"name": "leg2",
+				"parent": "body",
+				"pivot": [-2, 6, -4],
+				"cubes": [
+					{"origin": [-4, 0, -6], "size": [4, 6, 4], "uv": [0, 16]}
+				],
+				"inflate": 1
+			},
+			{
+				"name": "leg3",
+				"parent": "body",
+				"pivot": [2, 6, -4],
+				"cubes": [
+					{"origin": [0, 0, -6], "size": [4, 6, 4], "uv": [0, 16]}
+				],
+				"inflate": 1
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/flag/flag.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/flag/flag.geo.json
new file mode 100644
index 000000000..385b59559
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/flag/flag.geo.json
@@ -0,0 +1,145 @@
+{
+	"format_version": "1.12.0",
+	"minecraft:geometry": [
+		{
+			"description": {
+				"identifier": "geometry.flag.pole.long",
+				"texture_width": 64,
+				"texture_height": 64,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 3.5,
+				"visible_bounds_offset": [0, 1.25, 0]
+			},
+			"bones": [
+				{
+					"name": "root",
+					"pivot": [0, 0, 0]
+				},
+				{
+					"name": "base",
+					"parent": "root",
+					"pivot": [0, 0, 0],
+					"cubes": [
+						{"origin": [-2, 0, -2], "size": [4, 1, 4], "uv": [0, 40]}
+					]
+				},
+				{
+					"name": "pole",
+					"parent": "root",
+					"pivot": [0, 0, 0],
+					"cubes": [
+						{"origin": [-1, 1, -1], "size": [2, 33, 2], "uv": [0, 0]}
+					]
+				},
+				{
+					"name": "flag",
+					"parent": "root",
+					"pivot": [0, 25, 0]
+				}
+			]
+		},
+		{
+			"description": {
+				"identifier": "geometry.flag.pole.short",
+				"texture_width": 64,
+				"texture_height": 64,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 3.5,
+				"visible_bounds_offset": [0, 1.25, 0]
+			},
+			"bones": [
+				{
+					"name": "root",
+					"pivot": [0, 0, 0]
+				},
+				{
+					"name": "pole",
+					"parent": "root",
+					"pivot": [0, 0, 0],
+					"cubes": [
+						{"origin": [-1, 0, -1], "size": [2, 16, 2], "uv": [0, 0]}
+					]
+				},
+				{
+					"name": "flag",
+					"parent": "root",
+					"pivot": [0, 7, 0]
+				}
+			]
+		},
+		{
+			"description": {
+				"identifier": "geometry.flag.cloth",
+				"texture_width": 24,
+				"texture_height": 16,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 3.5,
+				"visible_bounds_offset": [0, 1.25, 0]
+			},
+			"bones": [
+				{
+					"name": "root",
+					"pivot": [0, 0, 0]
+				},
+				{
+					"name": "flag",
+					"parent": "root",
+					"pivot": [0, 0, 0],
+					"cubes": [
+						{
+							"origin": [1, -8, 0],
+							"size": [24, 16, 0],
+							"uv": {
+								"north": {
+									"uv": [0, 0],
+									"uv_size": [24, 16]
+								},
+								"south": {
+									"uv": [0, 0],
+									"uv_size": [24, 16]
+								}
+							}
+						}
+					]
+				}
+			]
+		},
+		{
+			"description": {
+				"identifier": "geometry.flag.cloth.mirror",
+				"texture_width": 24,
+				"texture_height": 16,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 3.5,
+				"visible_bounds_offset": [0, 1.25, 0]
+			},
+			"bones": [
+				{
+					"name": "root",
+					"pivot": [0, 0, 0]
+				},
+				{
+					"name": "flag",
+					"parent": "root",
+					"pivot": [0, 0, 0],
+					"cubes": [
+						{
+							"origin": [1, -8, 0],
+							"size": [24, 16, 0],
+							"uv": {
+								"north": {
+									"uv": [0, 0],
+									"uv_size": [24, 16]
+								},
+								"south": {
+									"uv": [24, 0],
+									"uv_size": [-24, 16]
+								}
+							}
+						}
+					]
+				}
+			]
+		}
+	]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/ghast/ghast.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/ghast/ghast.geo.json
new file mode 100644
index 000000000..d05017227
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/ghast/ghast.geo.json
@@ -0,0 +1,131 @@
+{
+  "format_version": "1.8.0",
+  "geometry.ghast": {
+    "visible_bounds_width": 6,
+    "visible_bounds_height": 9,
+    "visible_bounds_offset": [ 0, 4.5, 0 ],
+    "texturewidth": 64,
+    "textureheight": 32,
+    "bones": [
+      {
+        "name": "tentacles_0",
+        "parent": "body",
+        "pivot": [ -3.8, 1.0, -5.0 ],
+        "cubes": [
+          {
+            "origin": [ -4.8, -8.0, -6.0 ],
+            "size": [ 2.0, 9.0, 2.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "tentacles_1",
+        "parent": "body",
+        "pivot": [ 1.3, 1.0, -5.0 ],
+        "cubes": [
+          {
+            "origin": [ 0.3, -10.0, -6.0 ],
+            "size": [ 2.0, 11.0, 2.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "tentacles_2",
+        "parent": "body",
+        "pivot": [ 6.3, 1.0, -5.0 ],
+        "cubes": [
+          {
+            "origin": [ 5.3, -7.0, -6.0 ],
+            "size": [ 2.0, 8.0, 2.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "tentacles_3",
+        "parent": "body",
+        "pivot": [ -6.3, 1.0, 0.0 ],
+        "cubes": [
+          {
+            "origin": [ -7.3, -8.0, -1.0 ],
+            "size": [ 2.0, 9.0, 2.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "tentacles_4",
+        "parent": "body",
+        "pivot": [ -1.3, 1.0, 0.0 ],
+        "cubes": [
+          {
+            "origin": [ -2.3, -12.0, -1.0 ],
+            "size": [ 2.0, 13.0, 2.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "tentacles_5",
+        "parent": "body",
+        "pivot": [ 3.8, 1.0, 0.0 ],
+        "cubes": [
+          {
+            "origin": [ 2.8, -10.0, -1.0 ],
+            "size": [ 2.0, 11.0, 2.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "tentacles_6",
+        "parent": "body",
+        "pivot": [ -3.8, 1.0, 5.0 ],
+        "cubes": [
+          {
+            "origin": [ -4.8, -11.0, 4.0 ],
+            "size": [ 2.0, 12.0, 2.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "tentacles_7",
+        "parent": "body",
+        "pivot": [ 1.3, 1.0, 5.0 ],
+        "cubes": [
+          {
+            "origin": [ 0.3, -11.0, 4.0 ],
+            "size": [ 2.0, 12.0, 2.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "tentacles_8",
+        "parent": "body",
+        "pivot": [ 6.3, 1.0, 5.0 ],
+        "cubes": [
+          {
+            "origin": [ 5.3, -12.0, 4.0 ],
+            "size": [ 2.0, 13.0, 2.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "body",
+        "pivot": [ 0.0, 1.5, 0.0 ],
+        "cubes": [
+          {
+            "origin": [ -8.0, 0.0, -8.0 ],
+            "size": [ 16.0, 16.0, 16.0 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/humanoid.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/humanoid.geo.json
new file mode 100644
index 000000000..0a8bd6167
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/humanoid.geo.json
@@ -0,0 +1,81 @@
+{
+	"format_version": "1.10.0",
+	"geometry.humanoid.armor": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 3,
+		"visible_bounds_height": 3,
+		"visible_bounds_offset": [0, 1.5, 0],
+		"bones": [
+			{
+				"name": "waist",
+				"pivot": [0, 12, 0]
+			},
+			{
+				"name": "body",
+				"parent": "waist",
+				"pivot": [0, 24, 0]
+			},
+			{
+				"name": "chest",
+				"parent": "body",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+				]
+			},
+			{
+				"name": "head",
+				"parent": "body",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}
+				]
+			},
+			{
+				"name": "rightArm",
+				"parent": "body",
+				"pivot": [-5, 22, 0],
+				"cubes": [
+					{"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "rightItem",
+				"parent": "rightArm",
+				"pivot": [-5.5, 12, -2],
+				"rotation": [90, 0, 0]
+			},
+			{
+				"name": "leftArm",
+				"parent": "body",
+				"pivot": [5, 22, 0],
+				"cubes": [
+					{"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16], "mirror": true}
+				]
+			},
+			{
+				"name": "leftItem",
+				"parent": "leftArm",
+				"pivot": [5.5, 12, -2],
+				"rotation": [-90, 180, 0]
+			},
+			{
+				"name": "rightLeg",
+				"parent": "body",
+				"pivot": [-1.9, 12, 0],
+				"cubes": [
+					{"origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leftLeg",
+				"parent": "body",
+				"pivot": [1.9, 12, 0],
+				"cubes": [
+					{"origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 16], "mirror": true}
+				]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/minecart/minecart.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/minecart/minecart.geo.json
new file mode 100644
index 000000000..83a7aea0a
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/minecart/minecart.geo.json
@@ -0,0 +1,65 @@
+{
+	"format_version": "1.12.0",
+	"minecraft:geometry": [
+		{
+			"description": {
+				"identifier": "geometry.minecart",
+				"texture_width": 64,
+				"texture_height": 32,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 4,
+				"visible_bounds_offset": [0, 0, 0]
+			},
+			"bones": [
+				{
+					"name": "root",
+					"pivot": [0, 0, 0]
+				},
+				{
+					"name": "bottom",
+					"parent": "root",
+					"pivot": [0, -4, 0],
+					"rotation": [90, 0, 0],
+					"cubes": [
+						{"origin": [-10, -12, -1], "size": [20, 16, 2], "uv": [0, 10]}
+					]
+				},
+				{
+					"name": "back",
+					"parent": "root",
+					"pivot": [-9, -4, 0],
+					"rotation": [0, 270, 0],
+					"cubes": [
+						{"origin": [-17, -3, -1], "size": [16, 8, 2], "uv": [0, 0]}
+					]
+				},
+				{
+					"name": "front",
+					"parent": "root",
+					"pivot": [9, -4, 0],
+					"rotation": [0, 90, 0],
+					"cubes": [
+						{"origin": [1, -3, -1], "size": [16, 8, 2], "uv": [0, 0]}
+					]
+				},
+				{
+					"name": "right",
+					"parent": "root",
+					"pivot": [0, -4, -7],
+					"rotation": [0, 180, 0],
+					"cubes": [
+						{"origin": [-8, -3, -8], "size": [16, 8, 2], "uv": [0, 0]}
+					]
+				},
+				{
+					"name": "left",
+					"parent": "root",
+					"pivot": [0, -4, 7],
+					"cubes": [
+						{"origin": [-8, -3, 6], "size": [16, 8, 2], "uv": [0, 0]}
+					]
+				}
+			]
+		}
+	]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/models.json b/game/client/src/main/resources/assets/minecraft/models/entity/models.json
new file mode 100644
index 000000000..a2ac6a30f
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/models.json
@@ -0,0 +1,147 @@
+{
+    "model_paths": [
+        "/assets/minecraft/models/entity/sheep/sheep.geo.json",
+        "/assets/minecraft/models/entity/creeper/creeper.geo.json",
+        "/assets/minecraft/models/entity/scorpion/scorpion.geo.json",
+        "/assets/minecraft/models/entity/pig/pig.geo.json",
+        "/assets/minecraft/models/entity/chicken/chicken.geo.json",
+        "/assets/minecraft/models/entity/cow/cow.geo.json",
+        "/assets/minecraft/models/entity/wolf/wolf.geo.json",
+        "/assets/minecraft/models/entity/skeleton/skeleton.geo.json",
+        "/assets/minecraft/models/entity/zombie/zombie.geo.json",
+        "/assets/minecraft/models/entity/pigman/pigman.geo.json",
+        "/assets/minecraft/models/entity/pigzombie/pigzombie.geo.json",
+        "/assets/minecraft/models/entity/spider/spider.geo.json",
+        "/assets/minecraft/models/entity/squid/squid.geo.json",
+        "/assets/minecraft/models/entity/ghast/ghast.geo.json",
+        "/assets/minecraft/models/entity/slime/slime.geo.json",
+        "/assets/minecraft/models/entity/minecart/minecart.geo.json",
+        "/assets/minecraft/models/entity/boat/boat.geo.json",
+        "/assets/minecraft/models/entity/cannonball/cannonball.geo.json",
+        "/assets/minecraft/models/entity/humanoid.geo.json",
+        "/assets/minecraft/models/entity/player/player.geo.json",
+        "/assets/minecraft/models/entity/sign/sign.geo.json",
+        "/assets/minecraft/models/entity/flag/flag.geo.json"
+    ],
+    "renderers": {
+        "minecraft:spider": {
+            "main":"geometry.spider"
+        },
+        "minecraft:scorpion": {
+            "main":"geometry.scorpion"
+        },
+        "minecraft:pig": {
+            "main":"geometry.pig",
+            "saddle":{"model":"geometry.pig", "inflation": 0.5}
+        },
+        "minecraft:sheep": {
+            "main":"geometry.sheep.sheared",
+            "wool":"geometry.sheep.wool"
+        },
+        "minecraft:cow": {
+            "main":"geometry.cow"
+        },
+        "minecraft:wolf": {
+            "main":"geometry.wolf",
+            "armor":{"model":"geometry.wolf", "inflation":0.5}
+        },
+        "minecraft:chicken": {
+            "main":"geometry.chicken"
+        },
+        "minecraft:creeper": {
+            "main":"geometry.creeper"
+        },
+        "minecraft:skeleton": {
+            "main":"geometry.skeleton",
+            "armor.boots":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.leggings":{"model":"geometry.humanoid.armor", "inflation": 0.5},
+            "armor.chestplate":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.helmet":{"model":"geometry.humanoid.armor", "inflation": 1}
+        },
+        "minecraft:zombie": {
+            "main":"geometry.zombie",
+            "armor.boots":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.leggings":{"model":"geometry.humanoid.armor", "inflation": 0.5},
+            "armor.chestplate":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.helmet":{"model":"geometry.humanoid.armor", "inflation": 1}
+        },
+        "minecraft:zombie_pigman": {
+            "main":"geometry.zombie.pig",
+            "armor.boots":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.leggings":{"model":"geometry.humanoid.armor", "inflation": 0.5},
+            "armor.chestplate":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.helmet":{"model":"geometry.humanoid.armor", "inflation": 1}
+        },
+        "minecraft:snowman": {
+            "main":"geometry.zombie"
+        },
+        "minecraft:zombie_armored": {
+            "main":"geometry.zombie",
+            "armor.boots":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.leggings":{"model":"geometry.humanoid.armor", "inflation": 0.5},
+            "armor.chestplate":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.helmet":{"model":"geometry.humanoid.armor", "inflation": 1}
+        },
+        "minecraft:slime": {
+            "main":"geometry.slime"
+        },
+        "minecraft:player": {
+            "main":"geometry.player.base.steve",
+            "main.slim":"geometry.player.base.alex",
+            "arms":"geometry.player.base.steve.arms",
+            "arms.slim":"geometry.player.base.alex.arms",
+            "cape":"geometry.player.cape",
+            "armor.boots":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.leggings":{"model":"geometry.humanoid.armor", "inflation": 0.5},
+            "armor.chestplate":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.helmet":{"model":"geometry.humanoid.armor", "inflation": 1}
+        },
+        "minecraft:human": {
+            "main":"geometry.player.base.steve",
+            "main.slim":"geometry.player.base.alex",
+            "arms":"geometry.player.base.steve.arms",
+            "arms.slim":"geometry.player.base.alex.arms",
+            "cape":"geometry.player.cape"
+        },
+        "minecraft:giant": {
+            "main":"geometry.zombie",
+            "armor.boots":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.leggings":{"model":"geometry.humanoid.armor", "inflation": 0.5},
+            "armor.chestplate":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.helmet":{"model":"geometry.humanoid.armor", "inflation": 1}
+        },
+        "minecraft:ghast": {
+            "main":"geometry.ghast"
+        },
+        "minecraft:squid": {
+            "main":"geometry.squid"
+        },
+        "minecraft:boat": {
+            "main":"geometry.boat"
+        },
+        "minecraft:minecart": {
+            "main":"geometry.minecart"
+        },
+        "minecraft:cannonball": {
+            "main":"geometry.cannonball"
+        },
+        "minecraft:sign": {
+            "post":"geometry.sign.post",
+            "wall":"geometry.sign.wall"
+        },
+        "minecraft:flag": {
+            "pole.long":"geometry.flag.pole.long",
+            "pole.short":"geometry.flag.pole.short",
+            "cloth":"geometry.flag.cloth",
+            "cloth.mirror":"geometry.flag.cloth.mirror"
+        },
+        "minecraft:statue_stone": {
+            "main":"geometry.player.base.steve",
+            "main.pigman":"geometry.pigman",
+            "armor.boots":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.leggings":{"model":"geometry.humanoid.armor", "inflation": 0.5},
+            "armor.chestplate":{"model":"geometry.humanoid.armor", "inflation": 1},
+            "armor.helmet":{"model":"geometry.humanoid.armor", "inflation": 1}
+        }
+    }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/pig/pig.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/pig/pig.geo.json
new file mode 100644
index 000000000..243a20160
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/pig/pig.geo.json
@@ -0,0 +1,61 @@
+{
+	"format_version": "1.8.0",
+	"geometry.pig": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 3,
+		"visible_bounds_height": 2.25,
+		"visible_bounds_offset": [0, 0.875, 0],
+		"bones": [
+			{
+				"name": "body",
+				"pivot": [0, 13, 2],
+				"rotation": [90, 0, 0],
+				"cubes": [
+					{"origin": [-5, 7, -5], "size": [10, 16, 8], "uv": [28, 8]}
+				]
+			},
+			{
+				"name": "head",
+				"pivot": [0, 12, -6],
+				"cubes": [
+					{"origin": [-4, 8, -14], "size": [8, 8, 8], "uv": [0, 0]},
+					{"origin": [-2, 9, -15], "size": [4, 3, 1], "uv": [16, 16]}
+				],
+				"locators": {
+					"lead": [0, 14, -6]
+				}
+			},
+			{
+				"name": "leg0",
+				"pivot": [-3, 6, 7],
+				"cubes": [
+					{"origin": [-5, 0, 5], "size": [4, 6, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leg1",
+				"pivot": [3, 6, 7],
+				"mirror": true,
+				"cubes": [
+					{"origin": [1, 0, 5], "size": [4, 6, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leg2",
+				"pivot": [-3, 6, -5],
+				"cubes": [
+					{"origin": [-5, 0, -7], "size": [4, 6, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leg3",
+				"pivot": [3, 6, -5],
+				"mirror": true,
+				"cubes": [
+					{"origin": [1, 0, -7], "size": [4, 6, 4], "uv": [0, 16]}
+				]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/pigman/pigman.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/pigman/pigman.geo.json
new file mode 100644
index 000000000..a18ec5f35
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/pigman/pigman.geo.json
@@ -0,0 +1,139 @@
+{
+	"format_version": "1.10.0",
+	"geometry.pigman": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 2,
+		"visible_bounds_height": 3,
+		"visible_bounds_offset": [0, 1.5, 0],
+		"bones": [
+			{
+				"name": "waist",
+				"pivot": [0, 12, 0]
+			},
+			{
+				"name": "body",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+				]
+			},
+			{
+				"name": "bodyArmor",
+				"parent": "body",
+				"pivot": [0, 24, 0]
+			},
+			{
+				"name": "belt",
+				"parent": "body",
+				"pivot": [0, 24, 0]
+			},
+			{
+				"name": "head",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]},
+					{"origin": [-2, 25, -5], "size": [4, 3, 1], "uv": [24, 0]},
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5}
+				]
+			},
+			{
+				"name": "rightArm",
+				"parent": "waist",
+				"pivot": [-5, 22, 0],
+				"cubes": [
+					{"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "rightItem",
+				"parent": "rightArm",
+				"pivot": [-6, 12, -2],
+				"rotation": [90, 0, 0]
+			},
+			{
+				"name": "rightArmArmor",
+				"parent": "rightArm",
+				"pivot": [-5, 22, 0]
+			},
+			{
+				"name": "leftArm",
+				"parent": "waist",
+				"pivot": [5, 22, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "leftArmArmor",
+				"parent": "leftArm",
+				"pivot": [5, 22, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftItem",
+				"parent": "leftArm",
+				"pivot": [6, 12, -2],
+				"rotation": [-90, 180, 0]
+			},
+			{
+				"name": "rightLeg",
+				"parent": "waist",
+				"pivot": [-1.9, 12, 0],
+				"cubes": [
+					{"origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "rightLegging",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "rightBoot",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "rightSock",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "leftLeg",
+				"parent": "waist",
+				"pivot": [1.9, 12, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leftLegging",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftBoot",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftSock",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "helmet",
+				"parent": "waist",
+				"pivot": [0, 24, 0]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/pigzombie/pigzombie.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/pigzombie/pigzombie.geo.json
new file mode 100644
index 000000000..5ad4f03a7
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/pigzombie/pigzombie.geo.json
@@ -0,0 +1,139 @@
+{
+	"format_version": "1.10.0",
+	"geometry.zombie.pig": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 2,
+		"visible_bounds_height": 3,
+		"visible_bounds_offset": [0, 1.5, 0],
+		"bones": [
+			{
+				"name": "waist",
+				"pivot": [0, 12, 0]
+			},
+			{
+				"name": "body",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+				]
+			},
+			{
+				"name": "bodyArmor",
+				"parent": "body",
+				"pivot": [0, 24, 0]
+			},
+			{
+				"name": "belt",
+				"parent": "body",
+				"pivot": [0, 24, 0]
+			},
+			{
+				"name": "head",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]},
+					{"origin": [-2, 25, -5], "size": [4, 3, 1], "uv": [24, 0]},
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5}
+				]
+			},
+			{
+				"name": "rightArm",
+				"parent": "waist",
+				"pivot": [-5, 22, 0],
+				"cubes": [
+					{"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "rightItem",
+				"parent": "rightArm",
+				"pivot": [-6, 12, -2],
+				"rotation": [90, 0, 0]
+			},
+			{
+				"name": "rightArmArmor",
+				"parent": "rightArm",
+				"pivot": [-5, 22, 0]
+			},
+			{
+				"name": "leftArm",
+				"parent": "waist",
+				"pivot": [5, 22, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "leftArmArmor",
+				"parent": "leftArm",
+				"pivot": [5, 22, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftItem",
+				"parent": "leftArm",
+				"pivot": [6, 12, -2],
+				"rotation": [-90, 180, 0]
+			},
+			{
+				"name": "rightLeg",
+				"parent": "waist",
+				"pivot": [-1.9, 12, 0],
+				"cubes": [
+					{"origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "rightLegging",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "rightBoot",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "rightSock",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "leftLeg",
+				"parent": "waist",
+				"pivot": [1.9, 12, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leftLegging",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftBoot",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftSock",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "helmet",
+				"parent": "waist",
+				"pivot": [0, 24, 0]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/player/player.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/player/player.geo.json
new file mode 100644
index 000000000..436285126
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/player/player.geo.json
@@ -0,0 +1,391 @@
+{
+	"format_version": "1.12.0",
+	"minecraft:geometry": [
+		{
+			"description": {
+				"identifier": "geometry.player.base.alex.arms",
+				"texture_width": 64,
+				"texture_height": 64,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 3,
+				"visible_bounds_offset": [0, 1.5, 0]
+			},
+			"bones": [
+				{
+					"name": "rightArm",
+					"pivot": [-5, 22, 0],
+					"cubes": [
+						{"origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 16]}
+					]
+				},
+				{
+					"name": "rightSleeve",
+					"parent": "rightArm",
+					"pivot": [-6, 18, 0],
+					"cubes": [
+						{"origin": [-7, 12, -2], "size": [3, 12, 4], "inflate": 0.25, "uv": [40, 32]}
+					]
+				},
+				{
+					"name": "rightItem",
+					"parent": "rightArm",
+					"pivot": [-5.5, 12, -2],
+					"rotation": [90, 0, 0]
+				},
+				{
+					"name": "leftArm",
+					"pivot": [5, 22, 0],
+					"cubes": [
+						{"origin": [4, 12, -2], "size": [3, 12, 4], "uv": [32, 48]}
+					]
+				},
+				{
+					"name": "leftSleeve",
+					"parent": "leftArm",
+					"pivot": [5, 18, 0],
+					"cubes": [
+						{"origin": [4, 12, -2], "size": [3, 12, 4], "inflate": 0.25, "uv": [48, 48]}
+					]
+				},
+				{
+					"name": "leftItem",
+					"parent": "leftArm",
+					"pivot": [5.5, 12, -2],
+					"rotation": [-90, 180, 0]
+				}
+			]
+		},
+		{
+			"description": {
+				"identifier": "geometry.player.base.alex",
+				"texture_width": 64,
+				"texture_height": 64,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 3,
+				"visible_bounds_offset": [0, 1.5, 0]
+			},
+			"bones": [
+				{
+					"name": "waist",
+					"pivot": [0, 12, 0]
+				},
+				{
+					"name": "body",
+					"parent": "waist",
+					"pivot": [0, 24, 0],
+					"cubes": [
+						{"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+					]
+				},
+				{
+					"name": "jacket",
+					"parent": "body",
+					"pivot": [0, 18, 0],
+					"cubes": [
+						{"origin": [-4, 12, -2], "size": [8, 12, 4], "inflate": 0.25, "uv": [16, 32]}
+					]
+				},
+				{
+					"name": "head",
+					"parent": "body",
+					"pivot": [0, 24, 0],
+					"cubes": [
+						{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}
+					]
+				},
+				{
+					"name": "hat",
+					"parent": "head",
+					"pivot": [0, 28, 0],
+					"cubes": [
+						{"origin": [-4, 24, -4], "size": [8, 8, 8], "inflate": 0.25, "uv": [32, 0]}
+					]
+				},
+				{
+					"name": "rightArm",
+					"parent": "body",
+					"pivot": [-5, 22, 0],
+					"cubes": [
+						{"origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 16]}
+					]
+				},
+				{
+					"name": "rightSleeve",
+					"parent": "rightArm",
+					"pivot": [-6, 18, 0],
+					"cubes": [
+						{"origin": [-7, 12, -2], "size": [3, 12, 4], "inflate": 0.25, "uv": [40, 32]}
+					]
+				},
+				{
+					"name": "rightItem",
+					"parent": "rightArm",
+					"pivot": [-5.5, 12, -2],
+					"rotation": [90, 0, 0]
+				},
+				{
+					"name": "leftArm",
+					"parent": "body",
+					"pivot": [5, 22, 0],
+					"cubes": [
+						{"origin": [4, 12, -2], "size": [3, 12, 4], "uv": [32, 48]}
+					]
+				},
+				{
+					"name": "leftSleeve",
+					"parent": "leftArm",
+					"pivot": [5, 18, 0],
+					"cubes": [
+						{"origin": [4, 12, -2], "size": [3, 12, 4], "inflate": 0.25, "uv": [48, 48]}
+					]
+				},
+				{
+					"name": "leftItem",
+					"parent": "leftArm",
+					"pivot": [5.5, 12, -2],
+					"rotation": [-90, 180, 0]
+				},
+				{
+					"name": "rightLeg",
+					"parent": "body",
+					"pivot": [-1.9, 12, 0],
+					"cubes": [
+						{"origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+					]
+				},
+				{
+					"name": "rightPant",
+					"parent": "rightLeg",
+					"pivot": [-2, 6, 0],
+					"cubes": [
+						{"origin": [-4, 0, -2], "size": [4, 12, 4], "inflate": 0.25, "uv": [0, 32]}
+					]
+				},
+				{
+					"name": "leftLeg",
+					"parent": "body",
+					"pivot": [1.9, 12, 0],
+					"cubes": [
+						{"origin": [0, 0, -2], "size": [4, 12, 4], "uv": [16, 48]}
+					]
+				},
+				{
+					"name": "leftPant",
+					"parent": "leftLeg",
+					"pivot": [2, 6, 0],
+					"cubes": [
+						{"origin": [0, 0, -2], "size": [4, 12, 4], "inflate": 0.25, "uv": [0, 48]}
+					]
+				},
+				{
+					"name": "cape",
+					"parent": "body",
+					"pivot": [0, 24, 2.5]
+				}
+			]
+		},
+		{
+			"description": {
+				"identifier": "geometry.player.base.steve.arms",
+				"texture_width": 64,
+				"texture_height": 64,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 3,
+				"visible_bounds_offset": [0, 1.5, 0]
+			},
+			"bones": [
+				{
+					"name": "rightArm",
+					"pivot": [-5, 22, 0],
+					"cubes": [
+						{"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+					]
+				},
+				{
+					"name": "rightSleeve",
+					"parent": "rightArm",
+					"pivot": [-6, 18, 0],
+					"cubes": [
+						{"origin": [-8, 12, -2], "size": [4, 12, 4], "inflate": 0.25, "uv": [40, 32]}
+					]
+				},
+				{
+					"name": "rightItem",
+					"parent": "rightArm",
+					"pivot": [-6, 12, -2],
+					"rotation": [90, 0, 0]
+				},
+				{
+					"name": "leftArm",
+					"pivot": [5, 22, 0],
+					"cubes": [
+						{"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [32, 48]}
+					]
+				},
+				{
+					"name": "leftSleeve",
+					"parent": "leftArm",
+					"pivot": [6, 18, 0],
+					"cubes": [
+						{"origin": [4, 12, -2], "size": [4, 12, 4], "inflate": 0.25, "uv": [48, 48]}
+					]
+				},
+				{
+					"name": "leftItem",
+					"parent": "leftArm",
+					"pivot": [6, 12, -2],
+					"rotation": [-90, 180, 0]
+				}
+			]
+		},
+		{
+			"description": {
+				"identifier": "geometry.player.base.steve",
+				"texture_width": 64,
+				"texture_height": 64,
+				"visible_bounds_width": 3,
+				"visible_bounds_height": 3,
+				"visible_bounds_offset": [0, 1.5, 0]
+			},
+			"bones": [
+				{
+					"name": "waist",
+					"pivot": [0, 12, 0]
+				},
+				{
+					"name": "body",
+					"parent": "waist",
+					"pivot": [0, 24, 0],
+					"cubes": [
+						{"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+					]
+				},
+				{
+					"name": "jacket",
+					"parent": "body",
+					"pivot": [0, 18, 0],
+					"cubes": [
+						{"origin": [-4, 12, -2], "size": [8, 12, 4], "inflate": 0.25, "uv": [16, 32]}
+					]
+				},
+				{
+					"name": "head",
+					"parent": "body",
+					"pivot": [0, 24, 0],
+					"cubes": [
+						{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}
+					]
+				},
+				{
+					"name": "hat",
+					"parent": "head",
+					"pivot": [0, 28, 0],
+					"cubes": [
+						{"origin": [-4, 24, -4], "size": [8, 8, 8], "inflate": 0.25, "uv": [32, 0]}
+					]
+				},
+				{
+					"name": "rightArm",
+					"parent": "body",
+					"pivot": [-5, 22, 0],
+					"cubes": [
+						{"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+					]
+				},
+				{
+					"name": "rightSleeve",
+					"parent": "rightArm",
+					"pivot": [-6, 18, 0],
+					"cubes": [
+						{"origin": [-8, 12, -2], "size": [4, 12, 4], "inflate": 0.25, "uv": [40, 32]}
+					]
+				},
+				{
+					"name": "rightItem",
+					"parent": "rightArm",
+					"pivot": [-6, 12, -2],
+					"rotation": [90, 0, 0]
+				},
+				{
+					"name": "leftArm",
+					"parent": "body",
+					"pivot": [5, 22, 0],
+					"cubes": [
+						{"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [32, 48]}
+					]
+				},
+				{
+					"name": "leftSleeve",
+					"parent": "leftArm",
+					"pivot": [6, 18, 0],
+					"cubes": [
+						{"origin": [4, 12, -2], "size": [4, 12, 4], "inflate": 0.25, "uv": [48, 48]}
+					]
+				},
+				{
+					"name": "leftItem",
+					"parent": "leftArm",
+					"pivot": [6, 12, -2],
+					"rotation": [-90, 180, 0]
+				},
+				{
+					"name": "rightLeg",
+					"parent": "body",
+					"pivot": [-1.9, 12, 0],
+					"cubes": [
+						{"origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+					]
+				},
+				{
+					"name": "rightPant",
+					"parent": "rightLeg",
+					"pivot": [-2, 6, 0],
+					"cubes": [
+						{"origin": [-4, 0, -2], "size": [4, 12, 4], "inflate": 0.25, "uv": [0, 32]}
+					]
+				},
+				{
+					"name": "leftLeg",
+					"parent": "body",
+					"pivot": [1.9, 12, 0],
+					"cubes": [
+						{"origin": [0, 0, -2], "size": [4, 12, 4], "uv": [16, 48]}
+					]
+				},
+				{
+					"name": "leftPant",
+					"parent": "leftLeg",
+					"pivot": [2, 6, 0],
+					"cubes": [
+						{"origin": [0, 0, -2], "size": [4, 12, 4], "inflate": 0.25, "uv": [0, 48]}
+					]
+				},
+				{
+					"name": "cape",
+					"parent": "body",
+					"pivot": [0, 24, 2.5]
+				}
+			]
+		},
+		{
+			"description": {
+				"identifier": "geometry.player.cape",
+				"texture_width": 64,
+				"texture_height": 32,
+				"visible_bounds_width": 2,
+				"visible_bounds_height": 2,
+				"visible_bounds_offset": [0, 0, 0]
+			},
+			"bones": [
+				{
+					"name": "cape",
+					"pivot": [0, 0, 0],
+					"rotation": [0, 180, 0],
+					"cubes": [
+						{"origin": [-5, -16, -0.5], "size": [10, 16, 1], "uv": [0, 0]}
+					]
+				}
+			]
+		}
+	]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/scorpion/scorpion.bbmodel b/game/client/src/main/resources/assets/minecraft/models/entity/scorpion/scorpion.bbmodel
new file mode 100644
index 000000000..3aa9d5389
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/scorpion/scorpion.bbmodel
@@ -0,0 +1 @@
+{"meta":{"format_version":"4.10","model_format":"bedrock","box_uv":true},"name":"scorpion.geo","model_identifier":"scorpion","visible_box":[4,2.5,0.75],"variable_placeholders":"","variable_placeholder_buttons":[],"bedrock_animation_mode":"entity","timeline_setups":[],"unhandled_root_fields":{},"resolution":{"width":64,"height":32},"elements":[{"name":"body","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-2.5,1,-5],"to":[2.5,4,5],"autouv":1,"color":6,"origin":[0,0,0],"faces":{"north":{"uv":[10,10,15,13],"texture":0},"east":{"uv":[0,10,10,13],"texture":0},"south":{"uv":[25,10,30,13],"texture":0},"west":{"uv":[15,10,25,13],"texture":0},"up":{"uv":[15,10,10,0],"texture":0},"down":{"uv":[20,0,15,10],"texture":0}},"type":"cube","uuid":"75c25cd0-33d2-0761-de1f-d59ca02cdee3"},{"name":"tail0","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-1.5,0.5,5],"to":[1.5,2.5,13],"autouv":0,"color":6,"origin":[0,1.25,5],"uv_offset":[0,13],"faces":{"north":{"uv":[8,21,11,23],"texture":0},"east":{"uv":[0,21,8,23],"texture":0},"south":{"uv":[19,21,22,23],"texture":0},"west":{"uv":[11,21,19,23],"texture":0},"up":{"uv":[11,21,8,13],"texture":0},"down":{"uv":[14,13,11,21],"texture":0}},"type":"cube","uuid":"74d23680-7988-7d9f-7336-a22408a1cf9e"},{"name":"tail1","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-1,1.5,12],"to":[1,7.5,14],"autouv":1,"color":2,"origin":[0,1.5,13],"faces":{"north":{"uv":[2,2,4,8],"texture":0},"east":{"uv":[0,2,2,8],"texture":0},"south":{"uv":[6,2,8,8],"texture":0},"west":{"uv":[4,2,6,8],"texture":0},"up":{"uv":[4,2,2,0],"texture":0},"down":{"uv":[6,0,4,2],"texture":0}},"type":"cube","uuid":"1f9ec86b-8296-d1e9-e98e-b0bf6578d66b"},{"name":"tail2","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-1,7.5,12.5],"to":[1,11.5,13.5],"autouv":0,"color":2,"origin":[0,7.5,13],"uv_offset":[0,13],"faces":{"north":{"uv":[1,14,3,18],"texture":0},"east":{"uv":[0,14,1,18],"texture":0},"south":{"uv":[4,14,6,18],"texture":0},"west":{"uv":[3,14,4,18],"texture":0},"up":{"uv":[3,14,1,13],"texture":0},"down":{"uv":[5,13,3,14],"texture":0}},"type":"cube","uuid":"a965b927-b816-84e6-ea75-b2742d1c04e6"},{"name":"leg2","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[0,3,-0.5],"to":[9,4,0.5],"autouv":0,"color":0,"origin":[0,0,0],"uv_offset":[0,23],"faces":{"north":{"uv":[1,24,10,25],"texture":0},"east":{"uv":[0,24,1,25],"texture":0},"south":{"uv":[11,24,20,25],"texture":0},"west":{"uv":[10,24,11,25],"texture":0},"up":{"uv":[10,24,1,23],"texture":0},"down":{"uv":[19,23,10,24],"texture":0}},"type":"cube","uuid":"ead5639c-9277-a391-95f8-74e346cc0cd7"},{"name":"leg0","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[0,3,-0.5],"to":[9,4,0.5],"autouv":0,"color":0,"origin":[0,0,0],"uv_offset":[0,25],"faces":{"north":{"uv":[1,26,10,27],"texture":0},"east":{"uv":[0,26,1,27],"texture":0},"south":{"uv":[11,26,20,27],"texture":0},"west":{"uv":[10,26,11,27],"texture":0},"up":{"uv":[10,26,1,25],"texture":0},"down":{"uv":[19,25,10,26],"texture":0}},"type":"cube","uuid":"301f0dbf-1323-ddf3-a703-67d0821794ca"},{"name":"leg4","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[0,3,-0.5],"to":[9,4,0.5],"autouv":0,"color":0,"origin":[0,0,0],"uv_offset":[21,22],"faces":{"north":{"uv":[22,23,31,24],"texture":0},"east":{"uv":[21,23,22,24],"texture":0},"south":{"uv":[32,23,41,24],"texture":0},"west":{"uv":[31,23,32,24],"texture":0},"up":{"uv":[31,23,22,22],"texture":0},"down":{"uv":[40,22,31,23],"texture":0}},"type":"cube","uuid":"6c7c6593-0141-9e31-bef3-573ee9e81a24"},{"name":"leg1","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[0,3,-0.5],"to":[9,4,0.5],"autouv":0,"color":0,"origin":[0,0,0],"uv_offset":[0,25],"faces":{"north":{"uv":[1,26,10,27],"texture":0},"east":{"uv":[0,26,1,27],"texture":0},"south":{"uv":[11,26,20,27],"texture":0},"west":{"uv":[10,26,11,27],"texture":0},"up":{"uv":[10,26,1,25],"texture":0},"down":{"uv":[19,25,10,26],"texture":0}},"type":"cube","uuid":"c9e7a019-df53-fca6-f85a-235df7b19a31"},{"name":"leg3","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[0,3,-0.5],"to":[9,4,0.5],"autouv":0,"color":0,"origin":[0,0,0],"uv_offset":[0,23],"faces":{"north":{"uv":[1,24,10,25],"texture":0},"east":{"uv":[0,24,1,25],"texture":0},"south":{"uv":[11,24,20,25],"texture":0},"west":{"uv":[10,24,11,25],"texture":0},"up":{"uv":[10,24,1,23],"texture":0},"down":{"uv":[19,23,10,24],"texture":0}},"type":"cube","uuid":"a2c1d456-b378-a96c-90db-c3d5439e3910"},{"name":"leg5","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[0,3,-0.5],"to":[9,4,0.5],"autouv":0,"color":0,"origin":[0,0,0],"uv_offset":[21,22],"faces":{"north":{"uv":[22,23,31,24],"texture":0},"east":{"uv":[21,23,22,24],"texture":0},"south":{"uv":[32,23,41,24],"texture":0},"west":{"uv":[31,23,32,24],"texture":0},"up":{"uv":[31,23,22,22],"texture":0},"down":{"uv":[40,22,31,23],"texture":0}},"type":"cube","uuid":"8bc64815-f0ee-ebe6-a4b2-923b166cc3c9"},{"name":"rightClaw","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[1.5,1,-10],"to":[4.5,3,-4],"autouv":0,"color":6,"origin":[2,0,-4.5],"uv_offset":[14,13],"faces":{"north":{"uv":[20,19,23,21],"texture":0},"east":{"uv":[14,19,20,21],"texture":0},"south":{"uv":[29,19,32,21],"texture":0},"west":{"uv":[23,19,29,21],"texture":0},"up":{"uv":[23,19,20,13],"texture":0},"down":{"uv":[26,13,23,19],"texture":0}},"type":"cube","uuid":"c0a72c7f-733d-1227-c5c0-701e28cdc32a"},{"name":"leftClaw","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-4.5,1,-10],"to":[-1.5,3,-4],"autouv":0,"color":6,"origin":[0,0,0],"uv_offset":[20,0],"faces":{"north":{"uv":[26,6,29,8],"texture":0},"east":{"uv":[20,6,26,8],"texture":0},"south":{"uv":[35,6,38,8],"texture":0},"west":{"uv":[29,6,35,8],"texture":0},"up":{"uv":[29,6,26,0],"texture":0},"down":{"uv":[32,0,29,6],"texture":0}},"type":"cube","uuid":"c44ce376-5dba-12a4-3ff4-a8587751d16e"}],"outliner":[{"name":"body","origin":[0,0,0],"color":0,"uuid":"5a638a54-254e-38c6-22a9-7707ecc678d0","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["75c25cd0-33d2-0761-de1f-d59ca02cdee3",{"name":"leg0","origin":[0,2.5,0],"color":0,"uuid":"13d96cb4-d28a-4673-9e3c-e5abe5fe32f8","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["301f0dbf-1323-ddf3-a703-67d0821794ca"]},{"name":"leg1","origin":[0,2.5,0],"rotation":[0,-180,0],"color":0,"uuid":"c72d0ebb-b888-702a-b635-4f3e7b580abc","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["c9e7a019-df53-fca6-f85a-235df7b19a31"]},{"name":"leg2","origin":[0,2.5,0],"color":0,"uuid":"fe7d9ced-1944-901b-889a-c3fae48e0dba","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["ead5639c-9277-a391-95f8-74e346cc0cd7"]},{"name":"leg3","origin":[0,2.5,0],"rotation":[0,-180,0],"color":0,"uuid":"1b5ec03c-18b7-e93c-98b3-a15d36572b62","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["a2c1d456-b378-a96c-90db-c3d5439e3910"]},{"name":"leg4","origin":[0,2.5,0],"color":0,"uuid":"e44e6657-1d0e-229d-c9ac-e089b4a411e8","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["6c7c6593-0141-9e31-bef3-573ee9e81a24"]},{"name":"leg5","origin":[0,2.5,0],"rotation":[0,-180,0],"color":0,"uuid":"aa85fb4b-6226-3f8b-32f5-e0cf80ea9a78","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["8bc64815-f0ee-ebe6-a4b2-923b166cc3c9"]},{"name":"rightClaw","origin":[2,2.5,-4.5],"color":0,"uuid":"b714168d-4e63-8c82-d83e-c276755fcac7","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["c0a72c7f-733d-1227-c5c0-701e28cdc32a"]},{"name":"leftClaw","origin":[-2,2.25,-4.5],"color":0,"uuid":"f5b4c698-6664-5505-93cc-da5ee3b55b70","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["c44ce376-5dba-12a4-3ff4-a8587751d16e"]},{"name":"tail0","origin":[0,1,4.5],"rotation":[-60.00000000000001,0,0],"color":0,"uuid":"b6870b30-0a77-3a50-03fe-ebdd28f1c287","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["74d23680-7988-7d9f-7336-a22408a1cf9e",{"name":"tail1","origin":[0,1.5,13],"rotation":[15.000000000000433,0,0],"color":0,"uuid":"f8a5be4c-017e-50b6-5384-d30a695778b8","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["1f9ec86b-8296-d1e9-e98e-b0bf6578d66b",{"name":"tail2","origin":[0,7.5,13],"rotation":[-75.00000000000001,0,0],"color":0,"uuid":"02fdc195-3aa4-cecb-4503-06cddaf00edb","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["a965b927-b816-84e6-ea75-b2742d1c04e6"]}]}]}]}],"textures":[{"path":"C:\\Users\\matth\\Documents\\GitHub\\bta-src-useless\\game\\client\\src\\main\\resources\\assets\\minecraft\\textures\\entity\\scorpion\\0.png","name":"0.png","folder":"","namespace":"","id":"0","group":"","width":64,"height":32,"uv_width":16,"uv_height":16,"particle":false,"use_as_default":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"bdcfc59b-3273-dbe8-91e9-c98c5fe57d7a","relative_path":"../../../textures/entity/scorpion/0.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAAAAXNSR0IArs4c6QAAAz5JREFUaEPtWL9v00AUPqNWtE1KCJLTKghBAAmGSN06MnTo2A6M7Gz8B4z9D7plZ2SAkYGBsQtUKhKRCimqWmgjEfoj/BBVXX0XPuvi+OxzajdnqV7uYj9f3n33ve+9Z0f8v969XfU4x/ho4Zmj/n71csUrl0v+rU7nQH3sz5cfP+97jw92W6+94tSEOP71R/zuHsnbO/s/Bv4ndNEMb/rOxgHweeOFN1mYFtgELmxks/V1wLUgcDQ43HvjtdttcfKvK/Y6f8XNyg07AMDJ4ERwGrjgGDaKexirtSUJUhoMOPr5XW6e/2MFA3QAkK4EgBTm6augRYUOn4FBOP1PX/YFQsl6BpDq12YWU2EAQmymfNUHAHOwQRcyGYZ939JOFAPGJ6pislSXAJxXAwAAhVMVU2sBwKbBgqQMqD+oSe3g+xghfrgQAmPjBTl3XdcXU0wQUhvNVmw2SZsZDk6WKYnihJFCeK/+RDKATOlpQFe47mxoFgC1eYHiunQJGzCB9kFbXTpNHQDTBZnGaI8T/PCxOfA6KL2+1vAAEE6VYA0zJ/imPg5jF1q0hC0EAK6M9ah9eoKNhdcBpWKPASYAmNhlDYIDcWJKCo73a7flZnh6xamCjF21mmO8oyjSrYM1CAzmB8ejV38esoMC586tinQKToaNBKJaWxLraw0xN/8UWUHqBDauew/3t7Z7eV/VAvwetfr3AUBBwghH6TBHKDsVmikMdrwftFdtuLa1AMDBqD5AbWJQyuKKKmCimh4bxVGmwWAfgE2yBKb6I/a/7W75tXzSpsdWcRwAgAUKCyACgHgHA1jL6wAAA2xsenQpMhQAqLzKAJz89PVZIwBsbXqMAWBaU7tAKD2bF4qkjgG2Nj1aAOKqJ2pEEgBsbHqGBqD5vuHxI4aayvLW9AwNgJoiVQAe3q34a+ah6YnUAMY9jVD68ttdsIBBKKClDXtnFO1sXAjHPZe9gGoU1b4GF1M/bLCKpA3Ka5OGKM4m82YIDqddoWE9k04PrbKJXZYgyN7dxAlTZ8/T/6vvZrlplcnye0BaDEgCkgnoFwFC6gy4CKfjhC3Jc+MvQkkWzZPtJQB5Oq0sfL1kQBao5mnNM5ifM10RIS/UAAAAAElFTkSuQmCC"}],"animations":[{"uuid":"ebc5466a-8967-349c-dd8d-3ebf7580533b","name":"animation","loop":"once","override":false,"length":0,"snapping":24,"selected":true,"anim_time_update":"","blend_weight":"","start_delay":"","loop_delay":"","animators":{"13d96cb4-d28a-4673-9e3c-e5abe5fe32f8":{"name":"leg0","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":"\n","y":30,"z":-22.5}],"uuid":"34e3a261-9240-32d9-8c39-70106c2feba5","time":0,"color":-1,"interpolation":"linear"},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"ebd985d3-694e-99b6-990f-6d9ecc6fe892","time":0,"color":-1,"interpolation":"linear"}]},"c72d0ebb-b888-702a-b635-4f3e7b580abc":{"name":"leg1","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":-167.54108980830915,"y":-152.48765192554947,"z":-154.4385541632023}],"uuid":"612d40f5-5aa1-4c6d-6394-186b693d30b2","time":0,"color":-1,"interpolation":"linear"}]},"fe7d9ced-1944-901b-889a-c3fae48e0dba":{"name":"leg2","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":"0","y":"0","z":-22.5}],"uuid":"03aa7861-9c71-09bc-c88c-72a74a748e63","time":0,"color":-1,"interpolation":"linear"}]},"1b5ec03c-18b7-e93c-98b3-a15d36572b62":{"name":"leg3","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":-180,"y":-180,"z":-157.5}],"uuid":"b1abacc2-b5d5-f1c5-d7b4-8eaa70b2befc","time":0,"color":-1,"interpolation":"linear"}]},"e44e6657-1d0e-229d-c9ac-e089b4a411e8":{"name":"leg4","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":"0","y":-30,"z":-22.5}],"uuid":"af6d9b0d-fd87-e6d7-c8c4-372871636e7d","time":0,"color":-1,"interpolation":"linear"}]},"aa85fb4b-6226-3f8b-32f5-e0cf80ea9a78":{"name":"leg5","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":-192.4589101916904,"y":-207.51234807445053,"z":-154.4385541632023}],"uuid":"7fa8127d-47a9-7f9b-cf2b-c2df07d45176","time":0,"color":-1,"interpolation":"linear"}]},"b6870b30-0a77-3a50-03fe-ebdd28f1c287":{"name":"tail0","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":55,"y":0,"z":0}],"uuid":"1d6f4dc7-e1a1-7aba-1be2-2e5f0e463838","time":0,"color":-1,"interpolation":"linear"}]},"f8a5be4c-017e-50b6-5384-d30a695778b8":{"name":"tail1","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":72.5,"y":0,"z":0}],"uuid":"d355724d-d594-52cb-edbc-a692e12a8cfe","time":0,"color":-1,"interpolation":"linear"}]},"02fdc195-3aa4-cecb-4503-06cddaf00edb":{"name":"tail2","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":72.5,"y":0,"z":0}],"uuid":"51eebfc1-ba05-66d7-ee17-1276ad338e8d","time":0,"color":-1,"interpolation":"linear"}]}}}]}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/scorpion/scorpion.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/scorpion/scorpion.geo.json
new file mode 100644
index 000000000..732b1ff00
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/scorpion/scorpion.geo.json
@@ -0,0 +1,118 @@
+{
+	"format_version": "1.12.0",
+	"minecraft:geometry": [
+		{
+			"description": {
+				"identifier": "geometry.scorpion",
+				"texture_width": 64,
+				"texture_height": 32,
+				"visible_bounds_width": 4,
+				"visible_bounds_height": 2.5,
+				"visible_bounds_offset": [0, 0.75, 0]
+			},
+			"bones": [
+				{
+					"name": "body",
+					"pivot": [0, 0, 0],
+					"cubes": [
+						{"origin": [-2.5, 1, -5], "size": [5, 3, 10], "uv": [0, 0]}
+					]
+				},
+				{
+					"name": "leg0",
+					"parent": "body",
+					"pivot": [0, 2.5, 0],
+					"cubes": [
+						{"origin": [-9, 3, -0.5], "size": [9, 1, 1], "uv": [0, 25]}
+					]
+				},
+				{
+					"name": "leg1",
+					"parent": "body",
+					"pivot": [0, 2.5, 0],
+					"rotation": [0, 180, 0],
+					"cubes": [
+						{"origin": [-9, 3, -0.5], "size": [9, 1, 1], "uv": [0, 25]}
+					]
+				},
+				{
+					"name": "leg2",
+					"parent": "body",
+					"pivot": [0, 2.5, 0],
+					"cubes": [
+						{"origin": [-9, 3, -0.5], "size": [9, 1, 1], "uv": [0, 23]}
+					]
+				},
+				{
+					"name": "leg3",
+					"parent": "body",
+					"pivot": [0, 2.5, 0],
+					"rotation": [0, 180, 0],
+					"cubes": [
+						{"origin": [-9, 3, -0.5], "size": [9, 1, 1], "uv": [0, 23]}
+					]
+				},
+				{
+					"name": "leg4",
+					"parent": "body",
+					"pivot": [0, 2.5, 0],
+					"cubes": [
+						{"origin": [-9, 3, -0.5], "size": [9, 1, 1], "uv": [21, 22]}
+					]
+				},
+				{
+					"name": "leg5",
+					"parent": "body",
+					"pivot": [0, 2.5, 0],
+					"rotation": [0, 180, 0],
+					"cubes": [
+						{"origin": [-9, 3, -0.5], "size": [9, 1, 1], "uv": [21, 22]}
+					]
+				},
+				{
+					"name": "rightClaw",
+					"parent": "body",
+					"pivot": [-2, 2.5, -4.5],
+					"cubes": [
+						{"origin": [-4.5, 1, -10], "size": [3, 2, 6], "uv": [14, 13]}
+					]
+				},
+				{
+					"name": "leftClaw",
+					"parent": "body",
+					"pivot": [2, 2.25, -4.5],
+					"cubes": [
+						{"origin": [1.5, 1, -10], "size": [3, 2, 6], "uv": [20, 0]}
+					]
+				},
+				{
+					"name": "tail0",
+					"parent": "body",
+					"pivot": [0, 1, 4.5],
+					"rotation": [60, 0, 0],
+					"cubes": [
+						{"origin": [-1.5, 0.5, 5], "size": [3, 2, 8], "uv": [0, 13]}
+					]
+				},
+				{
+					"name": "tail1",
+					"parent": "tail0",
+					"pivot": [0, 1.5, 13],
+					"rotation": [-15, 0, 0],
+					"cubes": [
+						{"origin": [-1, 1.5, 12], "size": [2, 6, 2], "uv": [0, 0]}
+					]
+				},
+				{
+					"name": "tail2",
+					"parent": "tail1",
+					"pivot": [0, 7.5, 13],
+					"rotation": [75, 0, 0],
+					"cubes": [
+						{"origin": [-1, 7.5, 12.5], "size": [2, 4, 1], "uv": [0, 13]}
+					]
+				}
+			]
+		}
+	]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/sheep/sheep.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/sheep/sheep.geo.json
new file mode 100644
index 000000000..4767afebc
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/sheep/sheep.geo.json
@@ -0,0 +1,169 @@
+{
+  "format_version": "1.8.0",
+  "geometry.sheep.sheared": {
+    "texturewidth": 64,
+    "textureheight": 64,
+    "visible_bounds_width": 2,
+    "visible_bounds_height": 1.75,
+    "visible_bounds_offset": [ 0, 0.5, 0 ],
+    "bones": [
+      {
+        "name": "body",
+        "pivot": [ 0.0, 19.0, 2.0 ],
+        "rotation": [90, 0, 0],
+        "bind_pose_rotation": [ 90.0, 0.0, 0.0 ],
+        "cubes": [
+          {
+            "origin": [ -4.0, 13.0, -5.0 ],
+            "size": [ 8, 16, 6 ],
+            "uv": [ 28, 8 ]
+          }
+        ]
+      },
+      {
+        "name": "head",
+        "pivot": [ 0.0, 18.0, -8.0 ],
+        "locators": {
+          "lead": [ 0.0, 18.0, -8.0 ]
+        },
+        "cubes": [
+          {
+            "origin": [ -3.0, 16.0, -14.0 ],
+            "size": [ 6, 6, 8 ],
+            "uv": [ 0, 0 ]
+          }
+        ]
+      },
+      {
+        "name": "leg0",
+        "pivot": [ -3.0, 12.0, 7.0 ],
+        "cubes": [
+          {
+            "origin": [ -5.0, 0.0, 5.0 ],
+            "size": [ 4, 12, 4 ],
+            "uv": [ 0, 16 ]
+          }
+        ]
+      },
+      {
+        "name": "leg1",
+        "pivot": [ 3.0, 12.0, 7.0 ],
+        "cubes": [
+          {
+            "origin": [ 1.0, 0.0, 5.0 ],
+            "size": [ 4, 12, 4 ],
+            "uv": [ 0, 16 ]
+          }
+        ]
+      },
+      {
+        "name": "leg2",
+        "pivot": [ -3.0, 12.0, -5.0 ],
+        "cubes": [
+          {
+            "origin": [ -5.0, 0.0, -7.0 ],
+            "size": [ 4, 12, 4 ],
+            "uv": [ 0, 16 ]
+          }
+        ]
+      },
+      {
+        "name": "leg3",
+        "pivot": [ 3.0, 12.0, -5.0 ],
+        "cubes": [
+          {
+            "origin": [ 1.0, 0.0, -7.0 ],
+            "size": [ 4, 12, 4 ],
+            "uv": [ 0, 16 ]
+          }
+        ]
+      }
+    ]
+  },
+  "geometry.sheep.wool": {
+    "texturewidth": 64,
+    "textureheight": 64,
+    "visible_bounds_width": 2,
+    "visible_bounds_height": 1.75,
+    "visible_bounds_offset": [ 0, 0.5, 0 ],
+    "bones": [
+      {
+        "name": "head",
+        "pivot": [ 0.0, 18.0, -8.0 ],
+        "cubes": [
+          {
+            "origin": [ -3.0, 16.0, -12.0 ],
+            "size": [ 6, 6, 6 ],
+            "uv": [ 0, 32 ],
+            "inflate": 0.6
+          }
+        ]
+      },
+      {
+        "name": "body",
+        "pivot": [ 0.0, 19.0, 2.0 ],
+        "rotation": [90, 0, 0],
+        "bind_pose_rotation": [ 90.0, 0.0, 0.0 ],
+        "cubes": [
+          {
+            "origin": [ -4.0, 13.0, -5.0 ],
+            "size": [ 8, 16, 6 ],
+            "uv": [ 28, 40 ],
+            "inflate": 1.75
+          }
+        ]
+      },
+      {
+        "name": "leg0",
+        "pivot": [ -3.0, 12.0, 7.0 ],
+        "cubes": [
+          {
+            "origin": [ -5.0, 6.0, 5.0 ],
+            "size": [ 4, 6, 4 ],
+            "uv": [ 0, 48 ],
+            "inflate": 0.5
+          }
+        ]
+      },
+
+      {
+        "name": "leg1",
+        "pivot": [ 3.0, 12.0, 7.0 ],
+        "cubes": [
+          {
+            "origin": [ 1.0, 6.0, 5.0 ],
+            "size": [ 4, 6, 4 ],
+            "uv": [ 0, 48 ],
+            "inflate": 0.5
+          }
+        ]
+      },
+
+      {
+        "name": "leg2",
+        "pivot": [ -3.0, 12.0, -5.0 ],
+        "cubes": [
+          {
+            "origin": [ -5.0, 6.0, -7.0 ],
+            "size": [ 4, 6, 4 ],
+            "uv": [ 0, 48 ],
+            "inflate": 0.5
+          }
+        ]
+      },
+
+      {
+        "name": "leg3",
+        "pivot": [ 3.0, 12.0, -5.0 ],
+        "cubes": [
+          {
+            "origin": [ 1.0, 6.0, -7.0 ],
+            "size": [ 4, 6, 4 ],
+            "uv": [ 0, 48 ],
+            "inflate": 0.5
+          }
+        ]
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/sign/sign.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/sign/sign.geo.json
new file mode 100644
index 000000000..2de02d96f
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/sign/sign.geo.json
@@ -0,0 +1,44 @@
+{
+	"format_version": "1.12.0",
+	"minecraft:geometry": [
+		{
+			"description": {
+				"identifier": "geometry.sign.post",
+				"texture_width": 64,
+				"texture_height": 32,
+				"visible_bounds_width": 4,
+				"visible_bounds_height": 3.5,
+				"visible_bounds_offset": [0, 1.25, 0]
+			},
+			"bones": [
+				{
+					"name": "sign",
+					"pivot": [0, 0, 0],
+					"cubes": [
+						{"origin": [-1, 0, -1], "size": [2, 14, 2], "uv": [0, 14]},
+						{"origin": [-12, 14, -1], "size": [24, 12, 2], "uv": [0, 0]}
+					]
+				}
+			]
+		},
+		{
+			"description": {
+				"identifier": "geometry.sign.wall",
+				"texture_width": 64,
+				"texture_height": 32,
+				"visible_bounds_width": 4,
+				"visible_bounds_height": 3.5,
+				"visible_bounds_offset": [0, 1.25, 0]
+			},
+			"bones": [
+				{
+					"name": "sign",
+					"pivot": [0, 8, 0],
+					"cubes": [
+						{"origin": [-12, 7, -1], "size": [24, 12, 2], "uv": [0, 0]}
+					]
+				}
+			]
+		}
+	]
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/skeleton/skeleton.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/skeleton/skeleton.geo.json
new file mode 100644
index 000000000..96b8bc0df
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/skeleton/skeleton.geo.json
@@ -0,0 +1,79 @@
+{
+	"format_version": "1.10.0",
+	"geometry.skeleton": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 2,
+		"visible_bounds_height": 3,
+		"visible_bounds_offset": [0, 1.5, 0],
+		"bones": [
+			{
+				"name": "waist",
+				"pivot": [0, 12, 0]
+			},
+			{
+				"name": "body",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+				]
+			},
+			{
+				"name": "head",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]},
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5}
+				]
+			},
+			{
+				"name": "rightArm",
+				"parent": "waist",
+				"pivot": [-5, 22, 0],
+				"cubes": [
+					{"origin": [-6, 12, -1], "size": [2, 12, 2], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "rightItem",
+				"parent": "rightArm",
+				"pivot": [-5, 12, -1],
+				"rotation": [90, 0, 0]
+			},
+			{
+				"name": "leftArm",
+				"parent": "waist",
+				"pivot": [5, 22, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [4, 12, -1], "size": [2, 12, 2], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "leftItem",
+				"parent": "leftArm",
+				"pivot": [5, 12, -1],
+				"rotation": [-90, 180, 0]
+			},
+			{
+				"name": "rightLeg",
+				"parent": "waist",
+				"pivot": [-2, 12, 0],
+				"cubes": [
+					{"origin": [-3, 0, -1], "size": [2, 12, 2], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leftLeg",
+				"parent": "waist",
+				"pivot": [2, 12, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [1, 0, -1], "size": [2, 12, 2], "uv": [0, 16]}
+				]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/slime/slime.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/slime/slime.geo.json
new file mode 100644
index 000000000..ac0a9ee2f
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/slime/slime.geo.json
@@ -0,0 +1,44 @@
+{
+	"format_version": "1.8.0",
+	"geometry.slime": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 5,
+		"visible_bounds_height": 2,
+		"visible_bounds_offset": [0, 1, 0],
+		"bones": [
+			{
+				"name": "cube",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-3, 1, -3], "size": [6, 6, 6], "uv": [0, 16]},
+					{"origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0]}
+				]
+			},
+			{
+				"name": "eye0",
+				"parent": "cube",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-3.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 0]}
+				]
+			},
+			{
+				"name": "eye1",
+				"parent": "cube",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4]}
+				]
+			},
+			{
+				"name": "mouth",
+				"parent": "cube",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8]}
+				]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/spider/spider.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/spider/spider.geo.json
new file mode 100644
index 000000000..a9d9a80e0
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/spider/spider.geo.json
@@ -0,0 +1,99 @@
+{
+	"format_version": "1.10.0",
+	"geometry.spider": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 4,
+		"visible_bounds_height": 2,
+		"visible_bounds_offset": [0, 1, 0],
+		"bones": [
+			{
+				"name": "body0",
+				"pivot": [0, 9, 0],
+				"cubes": [
+					{"origin": [-3, 6, -3], "size": [6, 6, 6], "uv": [0, 0]}
+				]
+			},
+			{
+				"name": "head",
+				"parent": "body0",
+				"pivot": [0, 9, -3],
+				"cubes": [
+					{"origin": [-4, 5, -11], "size": [8, 8, 8], "uv": [32, 4]}
+				]
+			},
+			{
+				"name": "body1",
+				"parent": "body0",
+				"pivot": [0, 9, 9],
+				"cubes": [
+					{"origin": [-5, 5, 3], "size": [10, 8, 12], "uv": [0, 12]}
+				]
+			},
+			{
+				"name": "leg0",
+				"parent": "body0",
+				"pivot": [-4, 9, 2],
+				"cubes": [
+					{"origin": [-19, 8, 1], "size": [16, 2, 2], "uv": [18, 0]}
+				]
+			},
+			{
+				"name": "leg1",
+				"parent": "body0",
+				"pivot": [4, 9, 2],
+				"cubes": [
+					{"origin": [3, 8, 1], "size": [16, 2, 2], "uv": [18, 0], "mirror": true}
+				]
+			},
+			{
+				"name": "leg2",
+				"parent": "body0",
+				"pivot": [-4, 9, 1],
+				"cubes": [
+					{"origin": [-19, 8, 0], "size": [16, 2, 2], "uv": [18, 0]}
+				]
+			},
+			{
+				"name": "leg3",
+				"parent": "body0",
+				"pivot": [4, 9, 1],
+				"cubes": [
+					{"origin": [3, 8, 0], "size": [16, 2, 2], "uv": [18, 0], "mirror": true}
+				]
+			},
+			{
+				"name": "leg4",
+				"parent": "body0",
+				"pivot": [-4, 9, 0],
+				"cubes": [
+					{"origin": [-19, 8, -1], "size": [16, 2, 2], "uv": [18, 0]}
+				]
+			},
+			{
+				"name": "leg5",
+				"parent": "body0",
+				"pivot": [4, 9, 0],
+				"cubes": [
+					{"origin": [3, 8, -1], "size": [16, 2, 2], "uv": [18, 0], "mirror": true}
+				]
+			},
+			{
+				"name": "leg6",
+				"parent": "body0",
+				"pivot": [-4, 9, -1],
+				"cubes": [
+					{"origin": [-19, 8, -2], "size": [16, 2, 2], "uv": [18, 0]}
+				]
+			},
+			{
+				"name": "leg7",
+				"parent": "body0",
+				"pivot": [4, 9, -1],
+				"cubes": [
+					{"origin": [3, 8, -2], "size": [16, 2, 2], "uv": [18, 0], "mirror": true}
+				]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/squid/squid.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/squid/squid.geo.json
new file mode 100644
index 000000000..6af31a39a
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/squid/squid.geo.json
@@ -0,0 +1,93 @@
+{
+	"format_version": "1.10.0",
+	"geometry.squid": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 3,
+		"visible_bounds_height": 4,
+		"visible_bounds_offset": [0, 0, 0],
+		"bones": [
+			{
+				"name": "body",
+				"pivot": [0, 0, 0],
+				"cubes": [
+					{"origin": [-6, -8, -6], "size": [12, 16, 12], "uv": [0, 0]}
+				],
+				"locators": {
+					"lead": [0, 0, -5]
+				}
+			},
+			{
+				"name": "tentacle1",
+				"parent": "body",
+				"pivot": [5, -7, 0],
+				"rotation": [0, 90, 0],
+				"cubes": [
+					{"origin": [4, -25, -1], "size": [2, 18, 2], "uv": [48, 0]}
+				]
+			},
+			{
+				"name": "tentacle2",
+				"parent": "body",
+				"pivot": [3.5, -7, 3.5],
+				"rotation": [0, 45, 0],
+				"cubes": [
+					{"origin": [2.5, -25, 2.5], "size": [2, 18, 2], "uv": [48, 0]}
+				]
+			},
+			{
+				"name": "tentacle3",
+				"parent": "body",
+				"pivot": [0, -7, 5],
+				"cubes": [
+					{"origin": [-1, -25, 4], "size": [2, 18, 2], "uv": [48, 0]}
+				]
+			},
+			{
+				"name": "tentacle4",
+				"parent": "body",
+				"pivot": [-3.5, -7, 3.5],
+				"rotation": [0, -45, 0],
+				"cubes": [
+					{"origin": [-4.5, -25, 2.5], "size": [2, 18, 2], "uv": [48, 0]}
+				]
+			},
+			{
+				"name": "tentacle5",
+				"parent": "body",
+				"pivot": [-5, -7, 0],
+				"rotation": [0, -90, 0],
+				"cubes": [
+					{"origin": [-6, -25, -1], "size": [2, 18, 2], "uv": [48, 0]}
+				]
+			},
+			{
+				"name": "tentacle6",
+				"parent": "body",
+				"pivot": [-3.5, -7, -3.5],
+				"rotation": [0, -135, 0],
+				"cubes": [
+					{"origin": [-4.5, -25, -4.5], "size": [2, 18, 2], "uv": [48, 0]}
+				]
+			},
+			{
+				"name": "tentacle7",
+				"parent": "body",
+				"pivot": [0, -7, -5],
+				"rotation": [0, -180, 0],
+				"cubes": [
+					{"origin": [-1, -25, -6], "size": [2, 18, 2], "uv": [48, 0]}
+				]
+			},
+			{
+				"name": "tentacle8",
+				"parent": "body",
+				"pivot": [3.5, -7, -3.5],
+				"rotation": [0, -225, 0],
+				"cubes": [
+					{"origin": [2.5, -25, -4.5], "size": [2, 18, 2], "uv": [48, 0]}
+				]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/wolf/wolf.animation.json b/game/client/src/main/resources/assets/minecraft/models/entity/wolf/wolf.animation.json
new file mode 100644
index 000000000..8c727577f
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/wolf/wolf.animation.json
@@ -0,0 +1,49 @@
+{
+	"format_version": "1.8.0",
+	"animations": {
+		"animation.wolfidle": {
+			"loop": true,
+			"bones": {
+				"tail": {
+					"rotation": [88.5, 0, 0]
+				}
+			}
+		},
+		"animation.wolfsitting": {
+			"loop": true,
+			"bones": {
+				"head": {
+					"position": [0, 0, 0]
+				},
+				"body": {
+					"rotation": [-33.5, 0, 0],
+					"position": [0, -4.5, -2]
+				},
+				"upperBody": {
+					"rotation": [-18, 0, 0],
+					"position": [0, -3, 0]
+				},
+				"leg0": {
+					"rotation": [-90, 0, 0],
+					"position": [0, -7, -3]
+				},
+				"leg1": {
+					"rotation": [-90, 0, 0],
+					"position": [0, -7, -3]
+				},
+				"leg2": {
+					"rotation": [-22.5, 0, 0],
+					"position": [0, -1, 0]
+				},
+				"leg3": {
+					"rotation": [-22.5, 0, 0],
+					"position": [0, -1, 0]
+				},
+				"tail": {
+					"rotation": [85, 0, 0],
+					"position": [0, -9, -3]
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/wolf/wolf.geo.bbmodel b/game/client/src/main/resources/assets/minecraft/models/entity/wolf/wolf.geo.bbmodel
new file mode 100644
index 000000000..dc1ad048f
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/wolf/wolf.geo.bbmodel
@@ -0,0 +1 @@
+{"meta":{"format_version":"4.10","model_format":"bedrock_old","box_uv":true},"name":"wolf.geo","model_identifier":"wolf","visible_box":[3,2,1],"variable_placeholders":"","variable_placeholder_buttons":[],"timeline_setups":[],"unhandled_root_fields":{},"resolution":{"width":64,"height":32},"elements":[{"name":"head","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-2,7.5,-9],"to":[4,13.5,-5],"autouv":0,"color":0,"origin":[0,0,0],"faces":{"north":{"uv":[4,4,10,10],"texture":0},"east":{"uv":[0,4,4,10],"texture":0},"south":{"uv":[14,4,20,10],"texture":0},"west":{"uv":[10,4,14,10],"texture":0},"up":{"uv":[10,4,4,0],"texture":0},"down":{"uv":[16,0,10,4],"texture":0}},"type":"cube","uuid":"b29951cb-88c4-4e06-5194-15c1c9018d78"},{"name":"head","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[2,13.5,-7],"to":[4,15.5,-6],"autouv":0,"color":0,"origin":[0,0,0],"uv_offset":[16,14],"faces":{"north":{"uv":[17,15,19,17],"texture":0},"east":{"uv":[16,15,17,17],"texture":0},"south":{"uv":[20,15,22,17],"texture":0},"west":{"uv":[19,15,20,17],"texture":0},"up":{"uv":[19,15,17,14],"texture":0},"down":{"uv":[21,14,19,15],"texture":0}},"type":"cube","uuid":"3d68207e-0529-2828-564b-0a0a71affb33"},{"name":"head","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-2,13.5,-7],"to":[0,15.5,-6],"autouv":0,"color":0,"origin":[0,0,0],"uv_offset":[16,14],"faces":{"north":{"uv":[17,15,19,17],"texture":0},"east":{"uv":[16,15,17,17],"texture":0},"south":{"uv":[20,15,22,17],"texture":0},"west":{"uv":[19,15,20,17],"texture":0},"up":{"uv":[19,15,17,14],"texture":0},"down":{"uv":[21,14,19,15],"texture":0}},"type":"cube","uuid":"0980c778-719c-6dd4-d948-0c77345b16c1"},{"name":"head","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-0.5,7.51563,-12],"to":[2.5,10.51563,-8],"autouv":0,"color":0,"origin":[0,0,0],"uv_offset":[0,10],"faces":{"north":{"uv":[4,14,7,17],"texture":0},"east":{"uv":[0,14,4,17],"texture":0},"south":{"uv":[11,14,14,17],"texture":0},"west":{"uv":[7,14,11,17],"texture":0},"up":{"uv":[7,14,4,10],"texture":0},"down":{"uv":[10,10,7,14],"texture":0}},"type":"cube","uuid":"70cd917f-e0de-6cd8-e2d8-a2e9a0a8417b"},{"name":"lead","position":[1,10.5,-7],"rotation":[0,0,0],"ignore_inherited_scale":false,"visibility":true,"locked":false,"uuid":"3f6875fc-3b2c-6868-bbb3-4f319dd507e9","type":"locator"},{"name":"body","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-2,3,-1],"to":[4,12,5],"autouv":0,"color":1,"origin":[0,0,0],"uv_offset":[18,14],"faces":{"north":{"uv":[24,20,30,29],"texture":0},"east":{"uv":[18,20,24,29],"texture":0},"south":{"uv":[36,20,42,29],"texture":0},"west":{"uv":[30,20,36,29],"texture":0},"up":{"uv":[30,20,24,14],"texture":0},"down":{"uv":[36,14,30,20],"texture":0}},"type":"cube","uuid":"44eaff25-9b56-807d-d658-e5a41ae16856"},{"name":"upperBody","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-3,7,-6],"to":[5,13,1],"autouv":0,"color":2,"origin":[0,-1,0],"uv_offset":[21,0],"faces":{"north":{"uv":[28,7,36,13],"texture":0},"east":{"uv":[21,7,28,13],"texture":0},"south":{"uv":[43,7,51,13],"texture":0},"west":{"uv":[36,7,43,13],"texture":0},"up":{"uv":[36,7,28,0],"texture":0},"down":{"uv":[44,0,36,7],"texture":0}},"type":"cube","uuid":"3cc8b70e-01ad-ef33-5068-60ed3fdd4514"},{"name":"leg0","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[1.5,0,6],"to":[3.5,8,8],"autouv":0,"color":3,"origin":[0,0,0],"uv_offset":[0,18],"faces":{"north":{"uv":[2,20,4,28],"texture":0},"east":{"uv":[0,20,2,28],"texture":0},"south":{"uv":[6,20,8,28],"texture":0},"west":{"uv":[4,20,6,28],"texture":0},"up":{"uv":[4,20,2,18],"texture":0},"down":{"uv":[6,18,4,20],"texture":0}},"type":"cube","uuid":"7a5a8088-3920-b228-8e94-42e30516821d"},{"name":"leg1","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-1.5,0,6],"to":[0.5,8,8],"autouv":0,"color":4,"origin":[0,0,0],"uv_offset":[0,18],"faces":{"north":{"uv":[2,20,4,28],"texture":0},"east":{"uv":[0,20,2,28],"texture":0},"south":{"uv":[6,20,8,28],"texture":0},"west":{"uv":[4,20,6,28],"texture":0},"up":{"uv":[4,20,2,18],"texture":0},"down":{"uv":[6,18,4,20],"texture":0}},"type":"cube","uuid":"a071198f-06dc-4ff1-0a51-b6c9be4862b7"},{"name":"leg2","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[1.5,0,-5],"to":[3.5,8,-3],"autouv":0,"color":5,"origin":[0,0,0],"uv_offset":[0,18],"faces":{"north":{"uv":[2,20,4,28],"texture":0},"east":{"uv":[0,20,2,28],"texture":0},"south":{"uv":[6,20,8,28],"texture":0},"west":{"uv":[4,20,6,28],"texture":0},"up":{"uv":[4,20,2,18],"texture":0},"down":{"uv":[6,18,4,20],"texture":0}},"type":"cube","uuid":"d44cad68-8b6b-d3b4-3945-368ef2445dfb"},{"name":"leg3","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[-1.5,0,-5],"to":[0.5,8,-3],"autouv":0,"color":6,"origin":[0,0,0],"uv_offset":[0,18],"faces":{"north":{"uv":[2,20,4,28],"texture":0},"east":{"uv":[0,20,2,28],"texture":0},"south":{"uv":[6,20,8,28],"texture":0},"west":{"uv":[4,20,6,28],"texture":0},"up":{"uv":[4,20,2,18],"texture":0},"down":{"uv":[6,18,4,20],"texture":0}},"type":"cube","uuid":"c09777a6-378c-c22d-cd95-c494245ce640"},{"name":"tail","box_uv":true,"rescale":false,"locked":false,"light_emission":0,"render_order":"default","allow_mirror_modeling":true,"from":[0,2.9999999999999964,6.999999999999993],"to":[2,10.999999999999996,8.999999999999993],"autouv":0,"color":7,"origin":[0,-1.0000000000000036,-5.329070518200751e-15],"uv_offset":[9,18],"faces":{"north":{"uv":[11,20,13,28],"texture":0},"east":{"uv":[9,20,11,28],"texture":0},"south":{"uv":[15,20,17,28],"texture":0},"west":{"uv":[13,20,15,28],"texture":0},"up":{"uv":[13,20,11,18],"texture":0},"down":{"uv":[15,18,13,20],"texture":0}},"type":"cube","uuid":"8886af11-13e2-e131-8a08-457220ef2595"}],"outliner":[{"name":"head","origin":[1,10.5,-7],"color":0,"uuid":"11bc0886-0c2c-6c8c-967b-d1e54b977627","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["b29951cb-88c4-4e06-5194-15c1c9018d78","3d68207e-0529-2828-564b-0a0a71affb33","0980c778-719c-6dd4-d948-0c77345b16c1","70cd917f-e0de-6cd8-e2d8-a2e9a0a8417b","3f6875fc-3b2c-6868-bbb3-4f319dd507e9",{"name":"mouthItem","origin":[1,8.5,-9.500000000000004],"rotation":[90,-40,2.5],"color":0,"uuid":"4424d211-6a49-d38d-12a1-e69883e94191","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":[]}]},{"name":"body","origin":[0,10,2],"rotation":[-90,0,0],"color":1,"uuid":"c97c8a0a-0372-dc9e-58cc-01cc38fcb3d9","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["44eaff25-9b56-807d-d658-e5a41ae16856"]},{"name":"upperBody","origin":[1,10,-3],"rotation":[90,-180,-180],"color":2,"uuid":"6e44e31c-2778-32bd-03eb-c517ffbe310f","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["3cc8b70e-01ad-ef33-5068-60ed3fdd4514"]},{"name":"leg0","origin":[2.5,8,7],"color":3,"uuid":"a67cd76f-1c41-88fb-2d41-d9778462dd3b","export":true,"mirror_uv":false,"isOpen":false,"locked":false,"visibility":true,"autouv":0,"children":["7a5a8088-3920-b228-8e94-42e30516821d"]},{"name":"leg1","origin":[-0.5,8,7],"color":4,"uuid":"d018cf05-c955-c9f2-e7bb-f96fc92dc7cf","export":true,"mirror_uv":false,"isOpen":false,"locked":false,"visibility":true,"autouv":0,"children":["a071198f-06dc-4ff1-0a51-b6c9be4862b7"]},{"name":"leg2","origin":[2.5,8,-4],"color":5,"uuid":"cbe083a0-55fd-7e98-7f7c-a4d43c31a1c3","export":true,"mirror_uv":false,"isOpen":false,"locked":false,"visibility":true,"autouv":0,"children":["d44cad68-8b6b-d3b4-3945-368ef2445dfb"]},{"name":"leg3","origin":[-0.5,8,-4],"color":6,"uuid":"b9cd192d-cf7c-a7f0-cc87-f4f46b220c57","export":true,"mirror_uv":false,"isOpen":false,"locked":false,"visibility":true,"autouv":0,"children":["c09777a6-378c-c22d-cd95-c494245ce640"]},{"name":"tail","origin":[1,11,8],"color":7,"uuid":"6ae10187-2725-34a9-eca5-8a37c86daf20","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["8886af11-13e2-e131-8a08-457220ef2595"]}],"textures":[{"path":"C:\\Users\\matth\\Documents\\GitHub\\bta-src-useless\\game\\client\\src\\main\\resources\\assets\\minecraft\\textures\\entity\\wolf\\0.png","name":"0.png","folder":"","namespace":"","id":"0","group":"","width":64,"height":32,"uv_width":64,"uv_height":32,"particle":false,"use_as_default":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"24ea25a1-4f7e-13b7-4087-73fb508004ef","relative_path":"../../../textures/entity/wolf/0.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAAAAXNSR0IArs4c6QAACxpJREFUaEPlWWlsXNUV/t4sb8ZvNi+Jw2LHy4w9Hu+OndiOl5RWVQO0aqEFFSSgUIEQ/dEWqkptf9BfXWihaYISGhAIibZSo5amNAipSiB1bCd2FhLH29jjsYkDjsfL7PvMrc4xHkLSxtiy6fak0bPfu+++e757znfO+Z6Ea47hgYsiEAjAaDTC5/MBQsBsMSMYDPG1YDCAdFrAYrFAkiQ4aqqla+e40f/79/xSGI0GxOJJxGJRZJtN8PoDUAwGKHo9br61CG73GGw2B7/j3Nk+1Nc3wmA0ARCw2u2ret9Ka7tuMgJACMHGeb2LiIb80BssMJlMiETCUBQD/H4/VCqJgWjtaF/VgvY994yYmn4ft2zJx4xnDjflb4JnfhGd7Z3weD6AzVbBhs/NzeHSe244Kmug0Wj4FwwG0dzWtqr3rRqAk93dgt5gNJr4hYqSxbtPBptMZp6PPMRgMPB5tQAc3L9XBAJBeOYX0NLSiv7T/Whu2oE5zwxUKhWaW9rg9frgGhvB1uJSBn54eAAORw3i8fjGAzA0MCD8/gC7m9FgRCgcRjqdZsPNJhOCoRCMZHwwCPKU1vbV7ciBfXuEyz2JjvYO9Padwo7G7eg/04/One2YmZnGzrZdUKnUSKdTSCSSCIVCMJtNINBycnJQ5qhYXw8glyfj/H4fzGYLG04GEwgUBiaTkWgAAXZ7FSB95B3kBeFQiHcJkgSf14uWFULi+ed+IVxT78FWUoLR8XHQy8miijIbcnOyUdewnT2OPE+rleHzeWGxZPM5Nzd3/TngVE+voB0lpInkPB4PwuEwG77k7kHo9XqIVAxbbi7guI9EI8jS6xEORzgU6FkCIRDwr+iir738G+EPhmAtLYfTOQzX5BSKCwug1WogyzKqaxqQm5uHRCKOSCTKu0+bQYBkZSkoLS9bXw8YPH9BkJuTAbJORqnNhrzNW/Drpx5iAL797KuY91zB6b4+BiidSvOOEVH4fX4eo5KQ4YfK2pobLvClA/tEPBaDRquFotfBHwjyvLSGHIsFVbXb2GA6Nm3Kw8LCIrKzLR96nwR7ZeX6AnCyu0cQ6xL6iXgU5/52CIGUkiFP/6U+3FpcjfrPfRWyXkE8EYfP6+P7qXSKF2YirggF2Z1b2tqk/XufFWajEf5gEEgDWYqCVDKJWDwGlSRxuFjMZkSjMchaNQKhMEQ6zXMpRhOi4TBUajVqahtwceAcc0IqmYBaI/O5ubWdQRoevIBEMs7PpZIpPPGdp1YNjkQhkJuXi1QizsZfnrwIc+EOJOJLRmplC5ZBaPj8PVBrZSwuLHJYRCKRpdogQLVBmt21qq5O2r/nWSHrdIjHY1CyFFRW1+Ldc6eRSqVgIi+ChMLCIow5h/kaHRqNFjqdDrYyO5wjQww0kU+S7ksSdLKOw4KIOJ5IorZuG4fe7JXL2FpUCvf4CO594JHVAzA+6hQincLpt36PqfdnkbulGHd88a6Ppc83//o6Fq5MouiWfDTtvg+SSs3MFYtEeHH01kAwxNeaW1ulVw4eEHqdjEAoxIVOVc029J3qZpCyLRaU2uy8a2OjQ7yTsqyFgAoFhUVwT4zBYjKi2FqOs2f6mGuSyRQKi0pxeXoKRUWlmJ+b4YJpqTALQqeTMeEaxdfue3D1AFxbKJw49JJwj4+ixGaHoomj5/QF7Gyqxba7nvjEk3e9/bYgA9MijfnZGVRW1/FuTbnHYXdUc/pcPoYG3kUkFsW2xmYkEgkMDQ2guroW5989y96RpZc5HG66eStmZ6ZRVdPA48gDKTRCoQCm3C7k5Oaj/bbPfOI1Lr//ugfWA4DeEyc4szAI6TQURUEsFuPcTkxOBQ25PF1bXFzA3OwHsJVVIByJIJVKIz8/H+FwiIGiukOtVjNnkMcQgMlkkjMQ1QUUFnSffmspkzcEgCOHXxdbtxZz2UwHxbOslTN/k/HexUU2hOoOAshgNCIWjfIYAolJNpXEhGsMxSVWTscGkxEBnx8GgwKdTs+eoJW1fCaOWEuKvA6Ai0deE4/+9EW8+INHEY/71xQC14bVf/L/Erk8LbC4poPXqVOnYW/dhdHe44ilVHxtcqCLz32X3vmYLU8++RoD2Nqy/aOgBtB7sn/FWCSemHA5YbWWczwPDQ+grq4RdY2NKz67noBKZ1/fn1l8YfVtH5ubAJgdPpq59o675zoAyPhDv/sDX7/n/nvxq2eeQ0FBAQpKS25oyKnuHm6LueubcsNRtdT1feoAPP+jx8VPXnkT5eX2fwms0zmKHz58B+J5wX8KABlNx3e//yQIjOnpabR0dtwQgLHhEUHGX931UdHzwCOPfboesJ7utJq53M4xQUXO1V0fVaQV1VX/HgBqaio4FL53ZyPb8dDPfnvdQm7/bCuPaWlqwu4770Hzrs41L5Y8wOv1Xtf1lVc61jznajZgeWzmZasB4MdP/xxvHTmEp5/Zt+bF9vf0Ckt2NudxyunUfU66x7H7S19Z85xrAoB2Yn5uDolkgvWAcDCAVDrNhUrepk0sQJx457jQajTcstIRiUbhcg6ivmE7DEYzrBV2aSn3F0FRjKwjkN63JK2pcOrUCRQUFGFq0oWm7S2sNkWjUS6UZFkHIdLcV1yevoSSUit8fj/XBESKVPvrFQOs69wGZzyA2Jj+oaqKtD7aCZKkqAyVVCpWfF4+sFfYK+u4GiPjqDqjIoZAou3a0bZT6unqEmq1BkaDAr0+i+ePRiMIhsIIBvyglEddA7F9dnY2z0PFzNXj0qkUNDK1yXqcPNkNq7UMer3Ca6Imay07vNIzkmt0VJDIsSxykhBqNpszIOzs7MgAoFGpuWoLRyM8LzUjZIStwi71dnUJ2m21RgODksXXSUQlZZna1mQqibIyBxSDkft8KocJKPKUUDjC7fLyRszOXsHhNw6jtGgr6huasDk/H2UV6yuFZTzANerkdET9OO3MwuIC3yNVZn5+Dm27dkl/P3pUaGUdJO74ScNSQRICeZs3Q61WoaSsTDp/5owgcOgg7yA5i+p80hn6+3oRj0WhVxSUl1exwEEun5OTyxxArk4HcYFWq4XHM4s//vlP0Kg1ePihb0CjVsNRW7sxHjBycVDMeTzwLlwBKTW0g/OLXhSX2Lg1/ebj35JePbhflNmrQYULyWUCEtKpJLJzcjIylXN4WHgXvdQdZwwjIEjfC4eCmJhworS0nPV9quXpIMOXgaIGkdIgeSC1uIeP/AVqlRp3f/luBqymoWFjAHhx/15hMlLnpoasUSMWTzAhhiNRGJUs3P/wY1L38eNCJalYzREQTJJu1wgIFCJKm90uEZeQbkdurdGouYdfWFhgUWR0+OKSOGIwYvuOnfxxhcQDEjmXxxJfkAfQuMHB8xifcMFaYkVn520b8j0gEwIv7NsjiN1LreV4b9IFi9mEufmlMKAY//qDj0gnjh0TWp0Ohg9dnPS7ZCKBTZvzkUwmmKCOvvmGMJhzlrRFWYY/EABlDtINR4YHWNmpcFRBp8tiAiSwEsnkksITj/M3hnDAB40uC0NDFzA+MYXbv7A701Gu9vvDSuSXAaDr2DFBC8ozmUEs7I1GmA9y8/Kw6PWirbNTevmFvaLCUQ+LZenDCGUBcllmBPo20NHOWYAAovRGZEh8QgRIrSoRHZW81MuT23PrG4/DYiKy9XIapIaIw0sI1gmco0NwVNZy6qWN2LAQ+KRIrTSul74oCXB8E6DLYgjtLHHB6Mgg7BVVnDoprdEY+pFgQkaHSBiVAJFKsw5w9XgzpcH6+o3hgJUM+1+/vyGo/jeB9n8PwD8AIzh8bOgUNREAAAAASUVORK5CYII="},{"path":"C:\\Users\\matth\\Documents\\GitHub\\bta-src-useless\\game\\client\\src\\main\\resources\\assets\\minecraft\\textures\\entity\\wolf_tame\\0.png","name":"0.png","folder":"","namespace":"","id":"1","group":"","width":64,"height":32,"uv_width":64,"uv_height":32,"particle":false,"use_as_default":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"8de62916-3cb9-62f2-5c12-7a16c77d85a5","relative_path":"../../../textures/entity/wolf_tame/0.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAAAAXNSR0IArs4c6QAACy1JREFUaEPlWWlsXNUV/t682Tyrl8QhiR3bM2OPx7tjJ7HjJdCqatjUAg0qSEBJBaLhRwtUSG1/0F+0RaKhoQqroKikCynQAEmpqgRSx3ZiZyFxvO8kaRNvs+8z71bnGA8haWNs2XS70ujZ79137z3fOec7y5NwxejtOiv8fj9MJhO8Xi8gBCxWCwKBIN8LBPxQFAGr1QpJkuAqL5OuXONa/+8pXCMssgpRIRBVBNLVKngSCkyyCmkqCbpnf4XR0UE4HC7e49TJDlRV1cBoMgMQsDudC9pvvrNdtRgBIIRg4TweNyJBH/RGK8xmM8LhEAwGI3w+H1QqiYGob2pc0IF+XbhGnL71TqxZlY2Lk1O4LnsFJqfdaG5shnh8B9Jf2MOCT01N4dzHo3CVlEOtVvMvEAhgU0PDgvZbMABHW1sF7WAymXlDgyGNtU8Cm80WXo8sxGg08nWhAPzBuVaMb38Yk9MzqKurR+fxTmyq3YipyYtYufNJOPb+CR6PF8ODfViXb2Pge3u74HKVIxaLLT8APV1dwufzs7mZjCYEQyEoisKCW8xmBIJBmEj4QABkKfWNC9PIG0VrRcct29DU2IT2jmPYWLMBnSc60by5EbHHd6D4zT9DpZKhKEnE4wkEg0FYLGb4/QFkZGSg0FW8tBZAJk/C+XxeWCxWTExMIBQKIT09nd3A7XZDr9dDr9NBpVIB0qfWQVYQCgZZS5AkeD0e1M3jEuQCJ2+6A46CAvQPDYE2J4mKCx1wvLATub8/wBZHlqfRaOH1emC1pvM1MzNz6TngWFu7II0S0kRy4+Pj2HrLzWg9fJi13rBlC95/bz90GgmrVuew34cjYaTp9QiFwuwK9C6B4Pf75jXRA65cMfadR2C3FWFgoBfDY+PIz82BRqPGqud2Yu3Lv0NmZhbi8RjC4QhrnyySAElLM8BWVLi0FtB9+owgMycBtDotbA4Hslauwi8eu48B+O7Tr2F68hKOd3QwQEpSYY0RUfi8Pp6jkpDih5KK8mse8C3nWhFWBDSSBKMscQSgqBBSFGSoZaze8w4LTGPFiizMzLiRnm79xPokOEtKlhaAo61tglhXq9UiHovg1F/2wp80pMjTd64Da/PLUPXlO6DVGxCLx+D1ePl5UknywczEFcEAm3NdQ4O0e9fTwmIywRcIAAqQZjAgmUggGotCJUnsLlaLBZFIFFqNDH8wBKEovJbBZEYkFIJKllFeUY2zXaeYE5KJOGS1lq+b6hsZpN7uM4gnYvxeMpHEju89tmBwJHKBzKxMJOMxFv7C2FlYcjciHpsVUqO1Yg6E6q9sg6zRwj0zywvhcHg2N/BTbqCwuZZWVkq7n3laaHU6xGJRGNIMKCmrwEenjiOZTMJMVgQJubl5GBzo5Xs01GoNdDodHIVODPT1MNCUgyTouSRBp9WxWxARx+IJVFSuZ9ebuHQB6/JsGB3qw533bF84AEP9A0IoSRx//7cY/9sEMlfl46ZbbvtM+Dzw3tuYuTSGvDXZqN16FySVzMwVDYf5cLSrPxDke5vq66VXX3xO6HVa+INBpBMo5evRcayVQUq3WmFzOFlrg/09rEmtVgMBFXJy8zA6Mgir2YR8exFOnuhgrkkkksjNs+HC+XHk5dkwPXURq9fmfZKYBaDTaTEy3I9v3HXvwgG4MlE4svdlMTrUjwKHEwZ1DG3Hz2BzbQXW37bjcy/e8sEHggRUhILpiYsoKatkbY2PDsHpKuPwOTd6uj5COBrB+ppNiMfj6OnpQllZBU5/dJKtI02vZXe4bvU6TFw8j9Lyap5HFkiuEQz6MT46jIzMbDTecP3nPuPc/le9sBQAtB85wpGFQVAUGAwGRKNRju3E5JTQkMnTPbd7BlMTf4ejsBihcBjJpILs7GyEQkEGivIOWZaZM8hiCMBEIsERiPICcgt6Tr/FpMnLAsD+fW+LdevyOW2mQf6s1WhTf5PwHrebBaGEiwAymkyIRiI8h0Bikk0mMDI8iPwCOydCRrMJfq8PRqMBOp2eLUGj1fCVOGIxIfIqAM7uf1088JOX8NIPHkAs5luUC1zpVv/J/0tk8nTA/PImPqdOVuCs34L+9sOIJlV8b6yrha8d5z78jCyPPvo6A1hft+FTpwbQfrRzXl8knhgZHoDdXsT+3NPbhcrKGlTW1Mz77lICKp18e3fq8LllN3xmbQJgovdg6t6Ho21XAUDC7/3NG3x/2913YudTP0dOTg5ybAXXFORYa5swmYyzVd/4KFyls1XfFw7AL3/0kHjy1QMoKnL+S2AHBvrxw/tvQiwr8E8BIKFpPPL4oyAwzp8/j7rmpmsCMNjbJ0j4y6s+Snru2f7gF2sBS2lOC1lrdGBQUJJzedVHGWlxWem/B4Dy8mJ2he/fXMNy3PfTPVcd5MYv1fOcutpabL15GzZtaV70YckCPB7PVVVfUYlr0WsuRAFzc1ObLQSAHz/xM7y/fy+eeOrZRR+2s61dWNPTOY5TTDebTRgbHcLWW7++6DUXBQBpYnpqCvFEnPsBoYAfSUXhRCVrxQpuQBz58LDQqNVcstIIRyIYHuhGVfUGGE0W2Iud0mzsz4PBYOI+QjQa4URGklQ4duwIcnLyMD42jNoNddxtikQinChptToIoXBdceH8ORTY7PD6fJwTEClS7q83GGFf4jI4ZQHExvQPZVXU6yNNUEuK0lBJpeKOzyvP7RLOkkrOxkg4ys4oiSGQSF0bGzZLbS0tQpbVMBkN0OvTeP1IJIxAMISA3wcKeVQ1ENvPNVsombl8npJMQq3VwKDX4+jRVtjthdDrDXwmKrIWo+H53pGG+/sFNTnmmpzUCLVYLCkQNjc3pQBQq2TO2kKRMK9LlSAJ4Sh2Su0tLYK0LavVMBrS+D41UamzTGVrIplAYaELBqOJ63xKhwkospRgKMzl8pwiJiYuYd+7+2DLW4eq6lqszM5GYfHStsJSFjDcP8DhiOpx0syMe4afUVdmenqKOkLSXw8eFBqtDhJX/NTDUkESAlkrV0KWVSgoLJROnzghCBwaZB3UzqI8n/oMnR3tiEUj0BsMKCoq5QYHmXxGRiZzAJk6DeICjUaDyckJvPnHt6CW1bj/vm9BLctwVVQsjwX0ne0WU5OT8MxcQiwaZQ1Ouz3IL3Bwafrthx6WXntxtyh0loESF+oXCkhQkgmkZ2Sk2lQDvb3C4/ZQdZwSjICg/l4oGMDIyABstiLu71MuT4MEnwOKCkQKg2SB1I3et/8dyCoZt3/tdgasvLp6eQB4afcuYTZR5SZDq5YRjcWZEEPhCEyGNNx9/4NS6+HDQiWpuJsjIJgkR4f7QKAQUTqcTom4hPp2ZNZqtcw1/MzMDDdF+nvPzjZHjCZs2LiZP65Q84CanHNziS/IAmhed/dpDI0Mw15gR3PzDcvyPSDlAs8/+4wgdrfZi/Dx2DCsFjOmpmfdgHz8m/dul44cOiQ0Oh2Mn5g49RAT8ThWrMxGIhFngjp44F1htGTM9ha1Wvj8flDkoL5hX28Xd3aKXaXQ6dKYSAmseCIx2+GJxfgbQ8jvhVqXhp6eMxgaGceNX92aqigX+v1hPvJLAdBy6JCgA2WZLSAW9kTCzAeZWVlwezxoaG6WXnl+lyh2VcFqnf0wQlGATJYZgb4NNDVyFCCAKLwRGRKfEAFSqUpERykv1fJk9lz6xmKwmolsPRwGqSBi96JPZtEoBvp74Cqp4NBLilg2F/i8SM03r52+KAmwfxOgc80Q0ixxQX9fN5zFpRw6KazRHPpRw4SEDlJjVAJEUuE+wOXzLRQGq6qWhwPmE+x//fmyoPrfBNr/PQD/AN2Rcmy1yng0AAAAAElFTkSuQmCC"},{"path":"C:\\Users\\matth\\Documents\\GitHub\\bta-src-useless\\game\\client\\src\\main\\resources\\assets\\minecraft\\textures\\armor\\wolf\\diamond.png","name":"diamond.png","folder":"","namespace":"","id":"2","group":"","width":64,"height":32,"uv_width":64,"uv_height":32,"particle":false,"use_as_default":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"4b0169bf-fe49-4adc-a47d-51070d7cbeeb","relative_path":"../../../textures/armor/wolf/diamond.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAAAAXNSR0IArs4c6QAABSFJREFUaEPtWF1TG1UYfnaz2XxAQwX5no7ToVBBPkorLdJaL9Spdrzwygtn/HU6XjuOU3VqnVFbBFJoAxRsgRZkELBDbAIkm02yx3nfeGKSSZZtuikwujOdpee8e3LOc573eT8UlDwDt78W3qYmiEwGiqYhm0hAOxHCdM8lpdS2mv8Phb8XmVgMens76O3xB+Cpr0dmNw5YFi9pNx8ZuebKPuTeKy4mhBCj0WVMNnW7+oMXHk2KSmCem7klCAy7+fvn33V1PxUXG37wi1C9ums3LxG3A2Bo+qawYxvNRy68/3IAqIbeTr6xA6D3xucieKanIug0v3j9M3cB6PvuS6EGAvA2NuLewDu2iw/P/STS0SisZBK+zk4+r+LVIdImoKpIra9j4YNPbdcY2ZgX4c7+sjakD3pHJ+zmXdcAupFAdzf25+ccAVDXP4Dk0hKslIGZ/qu4knmau3jLgrG2dqDL2DFgZD0irKRRcQ2aD58acpcBA+PfiLrePiQe/obZ0eu2iw9O3BDBs69jf3EBqteL+sGhHAt0naPFXuQ+5sY+sl2DhE5kMznQVBXm9ha0UANUnw/ZZBJa/QnYzc9f/dhdAEhYPMEgZnovO1r4/OIdQYcV6XTuDLoP+j/ukFxZZgAKD2k+/bPogJ5AwDbMSWBIDLN7e1B8OszNTWgNDTUJkY4O7UTcCm2I5v7Tp2EZBoRlcT6h6jrMrU3YUZyBExb0tnZooRDG60/ll31zaYr/vtt9MT92xdyGZZpQvF4kFhZQTYisCQDkKnUDg6wLlpmCZaRALEsuL0FrOGmr8nS60MhFCEvwN3S4O742FAJwObUFkc3y+sRGRVUQD0+hmghREwCIAXRTvNF0umiT3sYmKB4P32I596DxwJlu/kb1+9jFSCv252b5m8ilDzG2t87MEpl0EbjVRIiaAiC5ShvOxOPsAkRvX0cHhGlCCJETUUVhId29G4be1sY2RG1Ox1UVqt8P48kTqHV1tt8eGQAK832RMotyfcWj2ao8AUJCaaVSyMRj0JtbciB5NH67HSFqwoDnFc3DtD80ACRL1GDw34ow9gzV0PhFADw0AEgoOX+wLA6R5POUYVYTyo4tAOnoDkcEigbyqSaUHUsAKFegkChrf3IJDnMuNzwOAufQXICqwvT2dp7y/T9/JUj9/zMAyHpBHphacZTcuF3sHMgA6vxQsUE9unLvB+994ogllVSdNkA9vlK1f97xWjFDGY2tCmNlBf6uLpR7O1VlUnVva2suWTFTuQbJ2u+cBHFhZJpQNS2v9jRO9r+GXstf0vC9H9m+sOChSRp3uo+Dbrx0XqGNa6+cROavZyj3nmw+64gB3Fjp6uL01aJ/RhLG6ip3lL3NzZzb6y0tXCEmHj3k8UL78WAnzs38wOMEgGy0SHu3e4ESCEXW91R50SZL305/uBwD4pMToB4fASurO/qN3ekwjxcyZuLVHvR9+wWPEwBjiY18tUf2tQqPjm7XCa1kBfi2tcMsoCd66yYfiIoYqu/pKQSAXIOKHbK/rbcebwAorlOp+lZ8La8BxuPHXLdTZ6dUBGk82NtXpBnSnnoJBIosd80/NmoWHl1jAMX1qY43UMiAvdkIynV5ZfeXNEEygJCQ9lQuUzXIVaCi8HjNooATejuxkS4gbYkJ2XisbAtMdn/JBXIdHZUbHNJejjMAmoZMdAdud4PzIujkcE5s8o3Qgk4vHSrf5X3B8VolSK65gBOQjqLN/wAcxVt5mXv6G+Ejgk5YVW3eAAAAAElFTkSuQmCC"}],"animations":[{"uuid":"e4cb9216-eedf-a7f4-78e2-2f2fd9368789","name":"animation.wolfidle","loop":"once","override":false,"length":0,"snapping":24,"selected":false,"saved":true,"path":"C:\\Users\\matth\\Documents\\GitHub\\bta-src-useless\\game\\client\\src\\main\\resources\\assets\\minecraft\\models\\entity\\wolf\\wolf.animation.json","anim_time_update":"","blend_weight":"","start_delay":"","loop_delay":"","animators":{"6ae10187-2725-34a9-eca5-8a37c86daf20":{"name":"tail","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":88.5,"y":0,"z":0}],"uuid":"67c0d137-70d6-a9a1-4a93-482448679556","time":0,"color":-1,"interpolation":"linear"}]}}},{"uuid":"11a0c765-983f-e1ae-87e3-3cc25c689eec","name":"animation.wolfsitting","loop":"once","override":false,"length":0,"snapping":24,"selected":false,"saved":true,"path":"C:\\Users\\matth\\Documents\\GitHub\\bta-src-useless\\game\\client\\src\\main\\resources\\assets\\minecraft\\models\\entity\\wolf\\wolf.animation.json","anim_time_update":"","blend_weight":"","start_delay":"","loop_delay":"","animators":{"11bc0886-0c2c-6c8c-967b-d1e54b977627":{"name":"head","type":"bone","keyframes":[{"channel":"position","data_points":[{"x":"0","y":0,"z":"0"}],"uuid":"e9fe22c4-11c0-d898-434b-7f8dda879afb","time":0,"color":-1,"interpolation":"linear"}]},"c97c8a0a-0372-dc9e-58cc-01cc38fcb3d9":{"name":"body","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":"-33.5\n","y":"0","z":"0"}],"uuid":"0c89aabe-a6e3-1fc9-902f-9c73ae141ec6","time":0,"color":-1,"interpolation":"linear"},{"channel":"position","data_points":[{"x":"0","y":-4.5,"z":-2}],"uuid":"51b198d8-465e-1f3d-7597-d1cc171c0ce6","time":0,"color":-1,"interpolation":"linear"}]},"6e44e31c-2778-32bd-03eb-c517ffbe310f":{"name":"upperBody","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":"-18","y":"0","z":"0"}],"uuid":"d163ba04-1966-66ae-d5d4-84659cf7ae87","time":0,"color":-1,"interpolation":"linear"},{"channel":"position","data_points":[{"x":"0","y":-3,"z":"0"}],"uuid":"2b1b0a11-a790-03fa-f06e-962c6b02e823","time":0,"color":-1,"interpolation":"linear"}]},"a67cd76f-1c41-88fb-2d41-d9778462dd3b":{"name":"leg0","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":-90,"y":"0","z":"0"}],"uuid":"a501a17e-2ef9-81ea-a8c5-daa7a5085dfe","time":0,"color":-1,"interpolation":"linear"},{"channel":"position","data_points":[{"x":"0","y":-7,"z":-3}],"uuid":"ee99662f-fa87-e811-5dbd-eceda8f92a03","time":0,"color":-1,"interpolation":"linear"}]},"d018cf05-c955-c9f2-e7bb-f96fc92dc7cf":{"name":"leg1","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":-90,"y":"0","z":"0"}],"uuid":"a0ac7c73-d21d-2aea-65fd-a6a05efc889c","time":0,"color":-1,"interpolation":"linear"},{"channel":"position","data_points":[{"x":"0","y":-7,"z":-3}],"uuid":"e85ec11c-71cd-6496-e0bb-26dea7788e55","time":0,"color":-1,"interpolation":"linear"}]},"cbe083a0-55fd-7e98-7f7c-a4d43c31a1c3":{"name":"leg2","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":-22.5,"y":"0","z":"0"}],"uuid":"abe9c049-0a6e-ad65-5555-bc12c6e4afe1","time":0,"color":-1,"interpolation":"linear"},{"channel":"position","data_points":[{"x":"0","y":-1,"z":"0"}],"uuid":"e9f7d660-ac3b-679e-1a53-4368a2ee4420","time":0,"color":-1,"interpolation":"linear"}]},"b9cd192d-cf7c-a7f0-cc87-f4f46b220c57":{"name":"leg3","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":-22.5,"y":"0","z":"0"}],"uuid":"306ca87c-17b2-5b4c-3da0-62e3efbae86f","time":0,"color":-1,"interpolation":"linear"},{"channel":"position","data_points":[{"x":"0","y":-1,"z":"0"}],"uuid":"d5b5a407-8ea0-e21d-a4f6-ab0aa6ecd81b","time":0,"color":-1,"interpolation":"linear"}]},"6ae10187-2725-34a9-eca5-8a37c86daf20":{"name":"tail","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":85,"y":0,"z":0}],"uuid":"2bd6b682-f8e8-68ad-4ffe-2200c7e5ebdb","time":0,"color":-1,"interpolation":"linear"},{"channel":"position","data_points":[{"x":"0","y":-9,"z":-3}],"uuid":"2e376303-fe23-e247-1a8b-e380280138fb","time":0,"color":-1,"interpolation":"linear"}]}}}]}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/wolf/wolf.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/wolf/wolf.geo.json
new file mode 100644
index 000000000..f5def56af
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/wolf/wolf.geo.json
@@ -0,0 +1,82 @@
+{
+	"format_version": "1.10.0",
+	"geometry.wolf": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 3,
+		"visible_bounds_height": 2,
+		"visible_bounds_offset": [0, 1, 0],
+		"bones": [
+			{
+				"name": "head",
+				"pivot": [-1, 10.5, -7],
+				"cubes": [
+					{"origin": [-4, 7.5, -9], "size": [6, 6, 4], "uv": [0, 0]},
+					{"origin": [-4, 13.5, -7], "size": [2, 2, 1], "uv": [16, 14]},
+					{"origin": [0, 13.5, -7], "size": [2, 2, 1], "uv": [16, 14]},
+					{"origin": [-2.5, 7.51563, -12], "size": [3, 3, 4], "uv": [0, 10]}
+				],
+				"locators": {
+					"lead": [-1, 10.5, -7]
+				}
+			},
+			{
+				"name": "mouthItem",
+				"parent": "head",
+				"pivot": [-1, 8.5, -9.5],
+				"rotation": [-90, 40, 2.5]
+			},
+			{
+				"name": "body",
+				"pivot": [0, 10, 2],
+				"rotation": [90, 0, 0],
+				"cubes": [
+					{"origin": [-4, 3, -1], "size": [6, 9, 6], "uv": [18, 14]}
+				]
+			},
+			{
+				"name": "upperBody",
+				"pivot": [-1, 10, -3],
+				"rotation": [-90, 180, -180],
+				"cubes": [
+					{"origin": [-5, 7, -6], "size": [8, 6, 7], "uv": [21, 0]}
+				]
+			},
+			{
+				"name": "leg0",
+				"pivot": [-2.5, 8, 7],
+				"cubes": [
+					{"origin": [-3.5, 0, 6], "size": [2, 8, 2], "uv": [0, 18]}
+				]
+			},
+			{
+				"name": "leg1",
+				"pivot": [0.5, 8, 7],
+				"cubes": [
+					{"origin": [-0.5, 0, 6], "size": [2, 8, 2], "uv": [0, 18]}
+				]
+			},
+			{
+				"name": "leg2",
+				"pivot": [-2.5, 8, -4],
+				"cubes": [
+					{"origin": [-3.5, 0, -5], "size": [2, 8, 2], "uv": [0, 18]}
+				]
+			},
+			{
+				"name": "leg3",
+				"pivot": [0.5, 8, -4],
+				"cubes": [
+					{"origin": [-0.5, 0, -5], "size": [2, 8, 2], "uv": [0, 18]}
+				]
+			},
+			{
+				"name": "tail",
+				"pivot": [-1, 11, 8],
+				"cubes": [
+					{"origin": [-2, 3, 7], "size": [2, 8, 2], "uv": [9, 18]}
+				]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/models/entity/zombie/zombie.geo.json b/game/client/src/main/resources/assets/minecraft/models/entity/zombie/zombie.geo.json
new file mode 100644
index 000000000..b5f75a4a1
--- /dev/null
+++ b/game/client/src/main/resources/assets/minecraft/models/entity/zombie/zombie.geo.json
@@ -0,0 +1,273 @@
+{
+	"format_version": "1.10.0",
+	"geometry.zombie": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 2,
+		"visible_bounds_height": 3,
+		"visible_bounds_offset": [0, 1.5, 0],
+		"bones": [
+			{
+				"name": "waist",
+				"pivot": [0, 12, 0]
+			},
+			{
+				"name": "body",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+				]
+			},
+			{
+				"name": "bodyArmor",
+				"parent": "body",
+				"pivot": [0, 24, 0]
+			},
+			{
+				"name": "belt",
+				"parent": "body",
+				"pivot": [0, 24, 0]
+			},
+			{
+				"name": "head",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}
+				]
+			},
+			{
+				"name": "hat",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5}
+				]
+			},
+			{
+				"name": "rightArm",
+				"parent": "waist",
+				"pivot": [-5, 22, 0],
+				"cubes": [
+					{"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "rightItem",
+				"parent": "rightArm",
+				"pivot": [-6, 12, -2],
+				"rotation": [90, 0, 0]
+			},
+			{
+				"name": "rightArmArmor",
+				"parent": "rightArm",
+				"pivot": [-5, 22, 0]
+			},
+			{
+				"name": "leftArm",
+				"parent": "waist",
+				"pivot": [5, 22, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "leftItem",
+				"parent": "leftArm",
+				"pivot": [6, 12, -2],
+				"rotation": [-90, 180, 0]
+			},
+			{
+				"name": "leftArmArmor",
+				"parent": "leftArm",
+				"pivot": [5, 22, 0],
+				"mirror": true
+			},
+			{
+				"name": "rightLeg",
+				"parent": "waist",
+				"pivot": [-1.9, 12, 0],
+				"cubes": [
+					{"origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "rightLegging",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "rightBoot",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "rightSock",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "leftLeg",
+				"parent": "waist",
+				"pivot": [1.9, 12, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leftLegging",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftBoot",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftSock",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "helmet",
+				"parent": "waist",
+				"pivot": [0, 24, 0]
+			}
+		]
+	},
+	"geometry.humanoid": {
+		"texturewidth": 64,
+		"textureheight": 32,
+		"visible_bounds_width": 2,
+		"visible_bounds_height": 3,
+		"visible_bounds_offset": [0, 1.5, 0],
+		"bones": [
+			{
+				"name": "waist",
+				"pivot": [0, 12, 0]
+			},
+			{
+				"name": "body",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+				]
+			},
+			{
+				"name": "bodyArmor",
+				"parent": "body",
+				"pivot": [0, 24, 0]
+			},
+			{
+				"name": "belt",
+				"parent": "body",
+				"pivot": [0, 24, 0]
+			},
+			{
+				"name": "head",
+				"parent": "waist",
+				"pivot": [0, 24, 0],
+				"cubes": [
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]},
+					{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5}
+				]
+			},
+			{
+				"name": "rightArm",
+				"parent": "waist",
+				"pivot": [-5, 22, 0],
+				"cubes": [
+					{"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "rightItem",
+				"parent": "rightArm",
+				"pivot": [-6, 15, 1]
+			},
+			{
+				"name": "rightArmArmor",
+				"parent": "rightArm",
+				"pivot": [-5, 22, 0]
+			},
+			{
+				"name": "leftArm",
+				"parent": "waist",
+				"pivot": [5, 22, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+				]
+			},
+			{
+				"name": "leftArmArmor",
+				"parent": "leftArm",
+				"pivot": [5, 22, 0],
+				"mirror": true
+			},
+			{
+				"name": "rightLeg",
+				"parent": "waist",
+				"pivot": [-1.9, 12, 0],
+				"cubes": [
+					{"origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "rightLegging",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "rightBoot",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "rightSock",
+				"parent": "rightLeg",
+				"pivot": [-1.9, 12, 0]
+			},
+			{
+				"name": "leftLeg",
+				"parent": "waist",
+				"pivot": [1.9, 12, 0],
+				"mirror": true,
+				"cubes": [
+					{"origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+				]
+			},
+			{
+				"name": "leftLegging",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftBoot",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "leftSock",
+				"parent": "leftLeg",
+				"pivot": [1.9, 12, 0],
+				"mirror": true
+			},
+			{
+				"name": "helmet",
+				"parent": "waist",
+				"pivot": [0, 24, 0]
+			}
+		]
+	}
+}
\ No newline at end of file
diff --git a/game/client/src/main/resources/assets/minecraft/textures/entity/creeper/debug.png b/game/client/src/main/resources/assets/minecraft/textures/entity/creeper/debug.png
new file mode 100644
index 000000000..f8e9e4b94
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/entity/creeper/debug.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/entity/flag.png b/game/client/src/main/resources/assets/minecraft/textures/entity/flag.png
index fa513e45d..f8c587a7f 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/entity/flag.png and b/game/client/src/main/resources/assets/minecraft/textures/entity/flag.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/entity/pig/debug.png b/game/client/src/main/resources/assets/minecraft/textures/entity/pig/debug.png
new file mode 100644
index 000000000..e6b2a9b9c
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/entity/pig/debug.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/entity/sheep/0.png b/game/client/src/main/resources/assets/minecraft/textures/entity/sheep/0.png
index a4a843c45..59c00e5af 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/entity/sheep/0.png and b/game/client/src/main/resources/assets/minecraft/textures/entity/sheep/0.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/entity/sheep/wool_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/entity/sheep/wool_overlay.png
new file mode 100644
index 000000000..fedd749ba
Binary files /dev/null and b/game/client/src/main/resources/assets/minecraft/textures/entity/sheep/wool_overlay.png differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/entity/sheep_fur.png b/game/client/src/main/resources/assets/minecraft/textures/entity/sheep_fur.png
deleted file mode 100644
index f1291a5fa..000000000
Binary files a/game/client/src/main/resources/assets/minecraft/textures/entity/sheep_fur.png and /dev/null differ
diff --git a/game/client/src/main/resources/assets/minecraft/textures/entity/sheep_overlay.png b/game/client/src/main/resources/assets/minecraft/textures/entity/sheep_overlay.png
index 8aa9be1fc..cc369abc2 100644
Binary files a/game/client/src/main/resources/assets/minecraft/textures/entity/sheep_overlay.png and b/game/client/src/main/resources/assets/minecraft/textures/entity/sheep_overlay.png differ
diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java
index 80597d2b7..c2fe2d02c 100644
--- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java
+++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java
@@ -74,15 +74,16 @@ public class BlockLogicActivator extends BlockLogicVeryRotatable
     }
 
     @Override
-    public void onNeighborBlockChange(World world, int x, int y, int z, int blockId)
+    public void onNeighborBlockChange(final World world, final int x, final int y, final int z, final int blockId)
     {
-        int meta = world.getBlockMetadata(x, y, z);
-        boolean flag = getNeighborSignal(world, x, y, z, BlockLogicRotatable.getDirectionFromMeta(meta));
-        if(flag && (meta & MASK_POWERED) == 0)
+        final int meta = world.getBlockMetadata(x, y, z);
+        final boolean hasSignal = getNeighborSignal(world, x, y, z, BlockLogicRotatable.getDirectionFromMeta(meta));
+        final boolean isPowered = (meta & MASK_POWERED) != 0;
+        if(hasSignal && !isPowered)
         {
-            world.scheduleBlockUpdate(x, y, z, block.id(), tickDelay());
+            world.scheduleBlockUpdate(x, y, z, this.block.id(), tickDelay());
             world.setBlockMetadataWithNotify(x, y, z, meta | MASK_POWERED);
-        } else if (!flag){
+        } else if (!hasSignal && isPowered){
             world.setBlockMetadataWithNotify(x, y, z, meta & ~MASK_POWERED);
         }
     }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/Entity.java b/game/core/src/main/java/net/minecraft/core/entity/Entity.java
index fa2f5ad7f..d04a9eb6d 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/Entity.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/Entity.java
@@ -49,7 +49,7 @@ public abstract class Entity
     public boolean blocksBuilding = false;
     public @Nullable Entity passenger;
     public @Nullable IVehicle vehicle;
-    public @Nullable World world;
+    public @NotNull World world;
     public double xo;
     public double yo;
     public double zo;
@@ -117,7 +117,8 @@ public abstract class Entity
     public boolean sendAdditionalData = false;
     public boolean turnWithVehicle = true;
 
-    public Entity(final @Nullable World world) {
+    public Entity(final @NotNull World world) {
+        assert world != null : "Entity world must not be null! If no world ref available try using WorldClient.EMPTY_WORLD as a stub!";
         this.world = world;
         setPos(0.0D, 0.0D, 0.0D);
         entityData.define(DATA_SHARED_FLAGS_ID, (byte) 0, Byte.class);
@@ -381,7 +382,7 @@ public abstract class Entity
     }
 
     public void waterHurt() {
-        if (world != null && world.dimension == Dimension.NETHER && !(vehicle instanceof EntityBoat)) {
+        if (world.dimension == Dimension.NETHER && !(vehicle instanceof EntityBoat)) {
             hurt(null, 1, DamageType.FIRE);
         }
     }
@@ -867,7 +868,7 @@ public abstract class Entity
         double d = (bb.maxY - bb.minY) * 0.66D;
         int j = MathHelper.floor((y - (double) heightOffset) + d);
         int k = MathHelper.floor(z);
-        if(world != null && world.areBlocksLoaded(MathHelper.floor(bb.minX), MathHelper.floor(bb.minY), MathHelper.floor(bb.minZ), MathHelper.floor(bb.maxX), MathHelper.floor(bb.maxY), MathHelper.floor(bb.maxZ)))
+        if(world.areBlocksLoaded(MathHelper.floor(bb.minX), MathHelper.floor(bb.minY), MathHelper.floor(bb.minZ), MathHelper.floor(bb.maxX), MathHelper.floor(bb.maxY), MathHelper.floor(bb.maxZ)))
         {
             float f1 = world.getLightBrightness(i, j, k);
             if(f1 < entityBrightness)
@@ -899,7 +900,7 @@ public abstract class Entity
     	return world.getLightmapCoord(skylight, blocklight);
     }
 
-    public void setWorld(@Nullable World world)
+    public void setWorld(@NotNull final World world)
     {
         this.world = world;
     }
@@ -1049,19 +1050,19 @@ public abstract class Entity
     {
     }
 
-    public boolean shouldRender(Vec3 vec3)
+    public boolean shouldRender(final Vec3 vec3, final double viewDistanceModifier)
     {
-        double d = x - vec3.x;
-        double d1 = y - vec3.y;
-        double d2 = z - vec3.z;
-        double d3 = d * d + d1 * d1 + d2 * d2;
-        return shouldRenderAtSqrDistance(d3);
+        final double dx = this.x - vec3.x;
+        final double dy = this.y - vec3.y;
+        final double dz = this.z - vec3.z;
+        final double distance = dx * dx + dy * dy + dz * dz;
+        return shouldRenderAtSqrDistance(distance, viewDistanceModifier);
     }
 
-    public boolean shouldRenderAtSqrDistance(double distance)
+    public boolean shouldRenderAtSqrDistance(final double distance, final double viewDistanceModifier)
     {
-        double d1 = bb.getSize();
-        d1 *= 64D * viewScale;
+        double d1 = this.bb.getSize();
+        d1 *= 64D * this.viewScale * viewDistanceModifier;
         return distance < d1 * d1;
     }
 
@@ -1182,11 +1183,9 @@ public abstract class Entity
 
     public @NotNull EntityItem dropItem(@NotNull ItemStack itemStack, float verticalOffset)
     {
-        EntityItem entityitem = new EntityItem(world, x, y + verticalOffset, z, itemStack);
+        final EntityItem entityitem = new EntityItem(world, x, y + verticalOffset, z, itemStack);
         entityitem.pickupDelay = 10;
-        if (world != null) {
-            world.entityJoinedWorld(entityitem);
-        }
+        this.world.entityJoinedWorld(entityitem);
         return entityitem;
     }
 
@@ -1322,22 +1321,20 @@ public abstract class Entity
     {
         setPos(x, y, z);
         setRot(yRot, xRot);
-        if (world != null) {
-            List<AABB> cubes = world.getCubes(this, bb.getInsetBoundingBox(0.03125D, 0.0D, 0.03125D));
-            if(!cubes.isEmpty())
+        List<AABB> cubes = world.getCubes(this, bb.getInsetBoundingBox(0.03125D, 0.0D, 0.03125D));
+        if(!cubes.isEmpty())
+        {
+            double d3 = 0.0D;
+            for (AABB cube : cubes)
             {
-                double d3 = 0.0D;
-                for (AABB cube : cubes)
+                if (cube.maxY > d3)
                 {
-                    if (cube.maxY > d3)
-                    {
-                        d3 = cube.maxY;
-                    }
+                    d3 = cube.maxY;
                 }
-
-                y += d3 - bb.minY;
-                setPos(x, y, z);
             }
+
+            y += d3 - bb.minY;
+            setPos(x, y, z);
         }
     }
 
@@ -1384,6 +1381,10 @@ public abstract class Entity
 
     }
 
+    public @Nullable ICarriable getHeldObject() {
+        return null;
+    }
+
     public boolean isOnFire()
     {
         return !fireImmune && remainingFireTicks > 0 || getSharedFlag(FLAG_ONFIRE);
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java b/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
index 5c6051b24..803f01fe1 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
@@ -3,6 +3,7 @@ package net.minecraft.core.entity;
 import com.mojang.logging.LogUtils;
 import net.minecraft.core.entity.animal.*;
 import net.minecraft.core.entity.monster.*;
+import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.entity.projectile.*;
 import net.minecraft.core.entity.vehicle.EntityBoat;
 import net.minecraft.core.entity.vehicle.EntityMinecart;
@@ -106,7 +107,7 @@ public final class EntityDispatcher
         return numericIdToStringIdMap;
     }
 
-    public static @Nullable Entity createEntityInWorld(@Nullable String id, World world)
+    public static @Nullable Entity createEntityInWorld(@Nullable final String id, @NotNull final World world)
     {
         if (id == null) return null;
         if (Legacy.isLegacyKey(id)) { // Handle entity creation via legacy id
@@ -121,11 +122,11 @@ public final class EntityDispatcher
         }
     }
 
-    public static @Nullable Entity createEntityInWorld(NamespaceID id, World world) {
+    public static @Nullable Entity createEntityInWorld(@NotNull final NamespaceID id, @NotNull final World world) {
         return createEntityInWorld(classForId(id), world);
     }
 
-    public static @Nullable Entity createEntityInWorld(Class<? extends Entity> clazz, World world) {
+    public static @Nullable Entity createEntityInWorld(@Nullable final Class<? extends Entity> clazz, @NotNull final World world) {
         Entity entity = null;
         try {
             if(clazz != null) {
@@ -195,8 +196,9 @@ public final class EntityDispatcher
         addMapping(ProjectileFireball.class, new NamespaceID("minecraft", "fireball"));
         addMapping(ProjectileCannonball.class, new NamespaceID("minecraft", "cannonball"));
 
-//        addMapping(Mob.class, new NamespaceID("minecraft", "mob")); // Abstract class, shouldn't ever be instantiated
+        addMapping(Mob.class, new NamespaceID("minecraft", "mob")); // Abstract class, shouldn't ever be instantiated
         addMapping(MobHuman.class, new NamespaceID("minecraft", "human"));
+        addMapping(Player.class, new NamespaceID("minecraft", "player"));
 
         // Hostile
         addMapping(MobZombie.class, new NamespaceID("minecraft", "zombie"), "guidebook.section.mob.zombie.name");
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java b/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java
index bf284fd56..5e37c36ed 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityFishingBobber.java
@@ -92,10 +92,10 @@ public class EntityFishingBobber extends Entity
     }
 
     @Override
-	public boolean shouldRenderAtSqrDistance(double distance)
+	public boolean shouldRenderAtSqrDistance(double distance, double viewDistanceModifier)
     {
         double d1 = bb.getSize() * 4D;
-        d1 *= 64D;
+        d1 *= 64D * viewDistanceModifier;
         return distance < d1 * d1;
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java b/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java
index cd2cc068a..b08216347 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java
@@ -117,7 +117,7 @@ public class EntityLightning extends Entity
     }
 
     @Override
-	public boolean shouldRender(Vec3 vec3)
+	public boolean shouldRender(Vec3 vec3, double viewDistanceModifier)
     {
         return life >= 0;
     }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/Mob.java b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
index f7d6a20ad..a67b4fb3e 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/Mob.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/Mob.java
@@ -35,6 +35,7 @@ import java.util.Map;
 
 public abstract class Mob extends Entity
 {
+    public static boolean SPAWN_NO_AI = false;
     public static final int DATA_VARIANT = 1;
     public static final int DATA_HEALTH = 2;
     protected @NotNull Map<ItemFood, ConsumedFood> consumedFood = new HashMap<>();
@@ -68,6 +69,7 @@ public abstract class Mob extends Entity
     public float prevCameraPitch;
     public float cameraPitch;
     protected boolean dead;
+    public boolean noAI = false;
     //    public int modelNum;
 //    public float animSpeed;
     public float walkAnimSpeedO;
@@ -94,8 +96,11 @@ public abstract class Mob extends Entity
     protected int numTicksToChaseTarget;
     public @NotNull String nickname = "";
     public byte chatColor = 0;
-    protected @NotNull NamespaceID textureIdentifier = new NamespaceID("minecraft", "char");
     protected float lastStrafe = 0.0f;
+    protected @NotNull String basePath = "/assets/minecraft/textures/entity/char/";
+    protected @NotNull String defaultTexture = "/assets/minecraft/textures/entity/char/0.png";
+    protected @NotNull String variantJsonPath = "/assets/minecraft/textures/entity/char/variant.json";
+    protected @NotNull NamespaceID textureIdentifier = new NamespaceID("minecraft", "char");
 
     public boolean isSkating = false;
 
@@ -105,7 +110,7 @@ public abstract class Mob extends Entity
     public @NotNull PlacementMode placementModeOverride = PlacementMode.FACING;
     public final @NotNull List<WeightedRandomLootObject> mobDrops = new ArrayList<>();
 
-    public Mob(@Nullable World world)
+    public Mob(@NotNull final World world)
     {
         super(world);
         heartsHalvesLife = 20;
@@ -145,7 +150,16 @@ public abstract class Mob extends Entity
 
         speed = 0.1f;
         flySpeed = 0.02f;
+        this.noAI = SPAWN_NO_AI;
     }
+
+    protected void setTextureIdentifier(final  @NotNull String namespace, final @NotNull String id) {
+        this.textureIdentifier = new NamespaceID(namespace, id);
+        this.basePath = String.format("/assets/%s/textures/entity/%s/", this.textureIdentifier.namespace, this.textureIdentifier.value);
+        this.defaultTexture = this.basePath + "0.png";
+        this.variantJsonPath = this.basePath + "variants.json";
+    }
+
     @Override
 	protected void defineSynchedData()
     {
@@ -157,34 +171,31 @@ public abstract class Mob extends Entity
     }
 
     @Override
-	public String getEntityTexture() {
-        String basePath = String.format("/assets/%s/textures/entity/%s/", textureIdentifier.namespace, textureIdentifier.value);
-        return basePath + getTextureReference() + ".png";
+	public @NotNull String getEntityTexture() {
+        return this.basePath + getTextureReference() + ".png";
     }
 
     public String getTextureReference() {
-        SkinVariantList variantList = Global.accessor.getSkinVariantList();
-        String basePath = String.format("/assets/%s/textures/entity/%s/", textureIdentifier.namespace, textureIdentifier.value);
-        return variantList.getSkinReference(basePath + "variants.json", "0", getSkinVariant());
+        final SkinVariantList variantList = Global.accessor.getSkinVariantList();
+        return variantList.getSkinReference(this.variantJsonPath, "0", getSkinVariant());
     }
 
     public boolean cycleVariant() {
-        String basePath = String.format("/assets/%s/textures/entity/%s/", textureIdentifier.namespace, textureIdentifier.value);
-        int skinVar = getSkinVariant();
-        setSkinVariant(Global.accessor.getSkinVariantList().nextSkinVariant(basePath + "variants.json", skinVar));
+        final int skinVar = getSkinVariant();
+        setSkinVariant(Global.accessor.getSkinVariantList().nextSkinVariant(this.variantJsonPath, skinVar));
         return skinVar != getSkinVariant();
     }
 
     public int getSkinVariant() {
-        return Byte.toUnsignedInt(entityData.getByte(DATA_VARIANT));
+        return Byte.toUnsignedInt(this.entityData.getByte(DATA_VARIANT));
     }
 
-    public void setSkinVariant(int skinVariant) {
-        entityData.set(DATA_VARIANT, (byte) (skinVariant));
+    public void setSkinVariant(final int skinVariant) {
+        this.entityData.set(DATA_VARIANT, (byte) (skinVariant));
     }
 
     public @NotNull String getDefaultEntityTexture() {
-        return String.format("/assets/%s/textures/entity/%s/0.png", textureIdentifier.namespace, textureIdentifier.value);
+        return this.defaultTexture;
     }
 
     @Override
@@ -405,6 +416,7 @@ public abstract class Mob extends Entity
 	public void tick()
     {
         super.tick();
+        if (this.noAI) return;
         onLivingUpdate();
         double d = x - xo;
         double d1 = z - zo;
@@ -925,31 +937,33 @@ public abstract class Mob extends Entity
     }
 
     @Override
-	public void addAdditionalSaveData(@NotNull CompoundTag tag)
+	public void addAdditionalSaveData(@NotNull final CompoundTag tag)
     {
         tag.putShort("Health", (short)getHealth());
-        tag.putShort("HurtTime", (short)hurtTime);
-        tag.putShort("DeathTime", (short)deathTime);
-        tag.putShort("AttackTime", (short)attackTime);
-        tag.putString("Nickname", nickname);
-        tag.putByte("ChatColor", chatColor);
-        tag.putByte("SkinVariant", entityData.getByte(1));
+        tag.putShort("HurtTime", (short) this.hurtTime);
+        tag.putShort("DeathTime", (short) this.deathTime);
+        tag.putShort("AttackTime", (short) this.attackTime);
+        tag.putString("Nickname", this.nickname);
+        tag.putByte("ChatColor", this.chatColor);
+        tag.putByte("SkinVariant", this.entityData.getByte(1));
+        tag.putBoolean("noAI", this.noAI);
     }
 
     @Override
-	public void readAdditionalSaveData(@NotNull CompoundTag tag)
+	public void readAdditionalSaveData(@NotNull final CompoundTag tag)
     {
         setHealthRaw(tag.getShort("Health"));
         if(!tag.containsKey("Health"))
         {
             setHealthRaw(getMaxHealth());
         }
-        hurtTime = tag.getShort("HurtTime");
-        deathTime = tag.getShort("DeathTime");
-        attackTime = tag.getShort("AttackTime");
-        nickname = StringUtils.substring(tag.getString("Nickname"), 0, 32);
-        chatColor = tag.getByte("ChatColor");
+        this.hurtTime = tag.getShort("HurtTime");
+        this.deathTime = tag.getShort("DeathTime");
+        this.attackTime = tag.getShort("AttackTime");
+        this.nickname = StringUtils.substring(tag.getString("Nickname"), 0, 32);
+        this.chatColor = tag.getByte("ChatColor");
         setSkinVariant(tag.getByte("SkinVariant"));
+        this.noAI = tag.getBoolean("noAI");
     }
 
     @Override
diff --git a/game/core/src/main/java/net/minecraft/core/entity/MobFlying.java b/game/core/src/main/java/net/minecraft/core/entity/MobFlying.java
index 9691b3cfb..011d9d5e3 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/MobFlying.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/MobFlying.java
@@ -7,7 +7,7 @@ import net.minecraft.core.world.World;
 public class MobFlying extends Mob
 {
 
-    public MobFlying(World world)
+    public MobFlying(final World world)
     {
         super(world);
     }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java b/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java
index ec5ed1e64..e041b0552 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/MobPathfinder.java
@@ -19,7 +19,7 @@ public abstract class MobPathfinder extends Mob
     protected @Nullable Entity closestFireflyEntity;
     protected boolean hasAttacked;
 
-    public MobPathfinder(@Nullable World world)
+    public MobPathfinder(@NotNull final World world)
     {
         super(world);
         hasAttacked = false;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobButterfly.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobButterfly.java
index dea7bdc18..3fb849bf9 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobButterfly.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobButterfly.java
@@ -16,6 +16,7 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.Biome;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Arrays;
@@ -56,7 +57,7 @@ public class MobButterfly extends MobFlying implements Creature {
 
     public MobButterfly(World world) {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "butterfly");
+        setTextureIdentifier("minecraft", "butterfly");
         setSize(0.5f, 0.5f);
     }
 
@@ -251,33 +252,26 @@ public class MobButterfly extends MobFlying implements Creature {
     }
 
     @Override
-    public void addAdditionalSaveData(CompoundTag tag) {
+    public void addAdditionalSaveData(@NotNull CompoundTag tag) {
         super.addAdditionalSaveData(tag);
         tag.putByte("Color", (byte) getColor());
     }
 
     @Override
-    public void readAdditionalSaveData(CompoundTag tag) {
+    public void readAdditionalSaveData(@NotNull CompoundTag tag) {
         super.readAdditionalSaveData(tag);
         setColor(tag.getByte("Color") & 0xFF);
     }
 
     @Override
-    public String getEntityTexture() {
-        String basePath = String.format("/assets/%s/textures/entity/%s/", textureIdentifier.namespace, textureIdentifier.value);
-        return basePath + getTextureReference() + "_0.png";
-//        if ((tickCount / 10) % 2 == 0) {
-//            return basePath + getTextureReference() + "_0.png";
-//        } else {
-//            return basePath + getTextureReference() + "_1.png";
-//        }
+    public @NotNull String getEntityTexture() {
+        return this.basePath + getTextureReference() + "_0.png";
     }
 
     @Override
     public String getTextureReference() {
-        SkinVariantList variantList = Global.accessor.getSkinVariantList();
-        String basePath = String.format("/assets/%s/textures/entity/%s/", textureIdentifier.namespace, textureIdentifier.value);
-        return colorEntries.get(getColor()).name + "/" + variantList.getSkinReference(basePath + "variants.json", "0", getSkinVariant());
+        final SkinVariantList variantList = Global.accessor.getSkinVariantList();
+        return colorEntries.get(getColor()).name + "/" + variantList.getSkinReference(variantJsonPath, "0", getSkinVariant());
     }
 
     public static class ButterflyEntry {
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobChicken.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobChicken.java
index ade3fc055..d42023c55 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobChicken.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobChicken.java
@@ -24,7 +24,7 @@ public class MobChicken extends MobAnimal
         flap = 0.0F;
         flapSpeed = 0.0F;
         flapping = 1.0F;
-        textureIdentifier = new NamespaceID("minecraft", "chicken");
+        setTextureIdentifier("minecraft", "chicken");
         setSize(0.4F, 0.8F);
         eggTimer = random.nextInt(6000) + 6000;
         mobDrops.add(new WeightedRandomLootObject(Items.FEATHER_CHICKEN.getDefaultStack(), 0, 2));
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobCow.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobCow.java
index 6be859029..fc904f58d 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobCow.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobCow.java
@@ -17,7 +17,7 @@ public class MobCow extends MobAnimal
     public MobCow(World world)
     {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "cow");
+        setTextureIdentifier("minecraft", "cow");
         setSize(0.9F, 1.3F);
         mobDrops.add(new WeightedRandomLootObject(Items.LEATHER.getDefaultStack(), 1, 5));
     }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java
index fd68f598f..6ccccf7c2 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobFireflyCluster.java
@@ -40,10 +40,10 @@ public class MobFireflyCluster extends MobFlying
     private int slowUpdateCooldown;
     
     
-    public MobFireflyCluster(World world)
+    public MobFireflyCluster(@NotNull final World world)
     {
         super(world);
-        if(world == null || world.isClientSide) {
+        if(world.isClientSide) {
         	setClusterSize(0);
         	setFireflyCount(0);
         }else {
@@ -57,9 +57,7 @@ public class MobFireflyCluster extends MobFlying
         fireImmune = true;
         
         // Give it a random cooldown so that not every check happens at the same time
-		if (world != null) {
-			slowUpdateCooldown = world.rand.nextInt(slowUpdateCooldownMax);
-		}
+        slowUpdateCooldown = world.rand.nextInt(slowUpdateCooldownMax);
     }
 
 	@Override
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java
index 5f37a5ba2..800b23e3a 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java
@@ -24,7 +24,7 @@ public class MobPig extends MobAnimal
     public MobPig(World world)
     {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "pig");
+        setTextureIdentifier("minecraft", "pig");
         setSize(0.9F, 0.9F);
         mobDrops.add(new WeightedRandomLootObject(Items.FOOD_PORKCHOP_RAW.getDefaultStack(), 1, 2));
         burningMobDrops.add(new WeightedRandomLootObject(Items.FOOD_PORKCHOP_COOKED.getDefaultStack(), 1, 2));
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java
index 12eed6b10..a45ebe472 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSheep.java
@@ -28,7 +28,7 @@ public class MobSheep extends MobAnimal
     public MobSheep(World world)
     {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "sheep");
+        setTextureIdentifier("minecraft", "sheep");
         setSize(0.9F, 1.3F);
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSquid.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSquid.java
index 42dbead8a..1754fe698 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobSquid.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobSquid.java
@@ -44,7 +44,7 @@ public class MobSquid extends MobWaterAnimal
         tx = 0.0F;
         ty = 0.0F;
         tz = 0.0F;
-        textureIdentifier = new NamespaceID("minecraft", "squid");
+        setTextureIdentifier("minecraft", "squid");
         setSize(0.95F, 0.95F);
         tentacleSpeed = (1.0F / (random.nextFloat() + 1.0F)) * 0.2F;
         mobDrops.add(new WeightedRandomLootObject(Items.DYE.getDefaultStack(), 1, 3));
diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
index e1018d96b..39dd8a85e 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobWolf.java
@@ -58,7 +58,7 @@ public class MobWolf extends MobAnimal implements IItemHolding
     {
         super(world);
         looksWithInterest = false;
-        textureIdentifier = new NamespaceID("minecraft", "wolf");
+        setTextureIdentifier("minecraft", "wolf");
         setSize(0.8F, 0.8F);
         moveSpeed = 1.1F;
         scoreValue = 500;
@@ -87,8 +87,9 @@ public class MobWolf extends MobAnimal implements IItemHolding
 
     public @Nullable ArmorMaterial getArmorMaterial() {
         ArmorMaterial material = null;
-        String name = entityData.getString(DATA_ARMOR_MATERIAL);
-        for (ArmorMaterial mat : ArmorMaterial.getArmorMaterials()) {
+        final String name = this.entityData.getString(DATA_ARMOR_MATERIAL);
+        if (name == null) return null;
+        for (final ArmorMaterial mat : ArmorMaterial.getArmorMaterials()) {
             if (mat.identifier.toString().equalsIgnoreCase(name)) {
                 material = mat;
                 break;
@@ -98,16 +99,16 @@ public class MobWolf extends MobAnimal implements IItemHolding
         return material;
     }
 
-    public void setArmor(ItemStack stack) {
+    public void setArmor(final ItemStack stack) {
         ArmorMaterial material = null;
-        armor = stack;
+        this.armor = stack;
         if (stack != null && stack.getItem() instanceof IArmorItem && ARMOR_MATERIALS.containsValue(stack.getItem())){
-            material = ((IArmorItem) stack.getItem()).getArmorMaterial();
+            material = ((IArmorItem<?>) stack.getItem()).getArmorMaterial();
         }
         if (material == null) {
-            entityData.set(DATA_ARMOR_MATERIAL, "");
+            this.entityData.set(DATA_ARMOR_MATERIAL, null);
         } else {
-            entityData.set(DATA_ARMOR_MATERIAL, material.identifier.toString());
+            this.entityData.set(DATA_ARMOR_MATERIAL, material.identifier.toString());
         }
     }
 
@@ -118,7 +119,7 @@ public class MobWolf extends MobAnimal implements IItemHolding
     }
 
     @Override
-	public String getEntityTexture()
+	public @NotNull String getEntityTexture()
     {
         if(isWolfTamed())
         {
@@ -488,23 +489,15 @@ public class MobWolf extends MobAnimal implements IItemHolding
         return isWolfShaking;
     }
 
-    public float getShadingWhileShaking(float f)
+    public float getShadingWhileShaking(final float partialTick)
     {
-        return 0.75F + ((prevTimeWolfIsShaking + (timeWolfIsShaking - prevTimeWolfIsShaking) * f) / 2.0F) * 0.25F;
+        return 0.75F + MathHelper.lerp(this.prevTimeWolfIsShaking, this.timeWolfIsShaking, partialTick) / 8.0F;
     }
 
-    public float getShakeAngle(float f, float f1)
+    public float getShakeAngle(final float partialTick, final float offset)
     {
-        float f2 = (prevTimeWolfIsShaking + (timeWolfIsShaking - prevTimeWolfIsShaking) * f + f1) / 1.8F;
-        if(f2 < 0.0F)
-        {
-            f2 = 0.0F;
-        } else
-        if(f2 > 1.0F)
-        {
-            f2 = 1.0F;
-        }
-        return MathHelper.sin(f2 * MathHelper.PI) * MathHelper.sin(f2 * MathHelper.PI * 11F) * 0.15F * MathHelper.PI;
+        final float shakeTime = MathHelper.clamp((MathHelper.lerp(this.prevTimeWolfIsShaking, this.timeWolfIsShaking, partialTick) + offset) / 1.8F, 0, 1);
+        return MathHelper.sin(shakeTime * MathHelper.PI) * MathHelper.sin(shakeTime * MathHelper.PI * 11F) * 0.15F * MathHelper.PI;
     }
 
     public float getInterestedAngle(float f)
@@ -523,7 +516,7 @@ public class MobWolf extends MobAnimal implements IItemHolding
     {
         if(isWolfSitting())
         {
-            return 20;
+            return 40;
         } else
         {
             return super.getLookingTilt();
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobCreeper.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobCreeper.java
index 0e69f3d75..6d4881887 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobCreeper.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobCreeper.java
@@ -14,10 +14,10 @@ public class MobCreeper extends MobMonster
 {
     public static final int DATA_CREEPER_STATE = 16;
     public static final int DATA_POWERED = 17;
-    public MobCreeper(@Nullable World world)
+    public MobCreeper(@NotNull final World world)
     {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "creeper");
+        setTextureIdentifier("minecraft", "creeper");
         scoreValue = 800;
         setSize(0.6F, 1.6F);
         mobDrops.add(new WeightedRandomLootObject(Items.SULPHUR.getDefaultStack(), 0, 2));
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
index da5eb2dac..ce3b5801e 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGhast.java
@@ -37,7 +37,7 @@ public class MobGhast extends MobFlying
         aggroCooldown = 0;
         attackChargeO = 0;
         attackCharge = 0;
-        textureIdentifier = new NamespaceID("minecraft", "ghast");
+        setTextureIdentifier("minecraft", "ghast");
         setSize(4F, 7F);
         fireImmune = true;
         scoreValue = 1000;
@@ -53,9 +53,9 @@ public class MobGhast extends MobFlying
     }
 
     @Override
-    public String getEntityTexture()
+    public @NotNull String getEntityTexture()
     {
-        if (entityData.getByte(DATA_CHARGING) != 1)
+        if (this.entityData.getByte(DATA_CHARGING) != 1)
         {
             return super.getEntityTexture();
         }
@@ -68,7 +68,7 @@ public class MobGhast extends MobFlying
     @Override
     public @NotNull String getDefaultEntityTexture()
     {
-        if (entityData.getByte(DATA_CHARGING) != 1)
+        if (this.entityData.getByte(DATA_CHARGING) != 1)
         {
             return super.getEntityTexture();
         }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGiant.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGiant.java
index 51decd3b9..badeaf224 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobGiant.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobGiant.java
@@ -3,25 +3,26 @@ package net.minecraft.core.entity.monster;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.world.World;
 
-public class MobGiant extends MobMonster
+public class MobGiant extends MobZombie
 {
+    public static final int GIANT_SCALE = 6;
 
-    public MobGiant(World world)
+    public MobGiant(final World world)
     {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "zombie");
-        moveSpeed = 0.5F;
-        attackStrength = 50;
-        heightOffset *= 6F;
-        setSize(bbWidth * 6F, bbHeight * 6F);
+        setTextureIdentifier("minecraft", "zombie");
+        this.moveSpeed = 0.5F;
+        this.attackStrength = 50;
+        this.heightOffset *= 6F;
+        setSize(this.bbWidth * GIANT_SCALE, this.bbHeight * GIANT_SCALE);
     }
     @Override
     public int getMaxHealth(){
         return super.getMaxHealth() * 10;
     }
     @Override
-	protected float getBlockPathWeight(int x, int y, int z)
+	protected float getBlockPathWeight(final int x, final int y, final int z)
     {
-        return world.getLightBrightness(x, y, z) - 0.5F;
+        return this.world.getLightBrightness(x, y, z) - 0.5F;
     }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonster.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonster.java
index f9e78d9d0..0bd600f44 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonster.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonster.java
@@ -17,7 +17,7 @@ public abstract class MobMonster extends MobPathfinder
     implements Enemy
 {
 
-    public MobMonster(@Nullable World world)
+    public MobMonster(@NotNull final World world)
     {
         super(world);
         attackStrength = 2;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonsterArmored.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonsterArmored.java
index 13a350c64..c5c1f6400 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonsterArmored.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobMonsterArmored.java
@@ -21,7 +21,7 @@ public abstract class MobMonsterArmored<T extends IArmorShape>
     protected static final int DATA_ARMOR_START = 25;
     protected static final int FLAG_LEFT_HANDED = 4;
 
-    public MobMonsterArmored(final @Nullable World world) {
+    public MobMonsterArmored(final @NotNull World world) {
         super(world);
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobScorpion.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobScorpion.java
index 6275738ac..839af5900 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobScorpion.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobScorpion.java
@@ -17,7 +17,7 @@ public class MobScorpion extends MobMonster
     public MobScorpion(World world)
     {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "scorpion");
+        setTextureIdentifier("minecraft", "scorpion");
         setSize(1F, 0.2F);
         moveSpeed = 0.8F;
         scoreValue = 200;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java
index 14b1ec861..a3500037f 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSkeleton.java
@@ -26,7 +26,7 @@ public class MobSkeleton extends MobMonsterArmored<HumanArmorShape>
 
     public MobSkeleton(World world) {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "skeleton");
+        setTextureIdentifier("minecraft", "skeleton");
         scoreValue = 500;
         mobDrops.add(new WeightedRandomLootObject(Items.AMMO_ARROW.getDefaultStack(), 0, 2));
         mobDrops.add(new WeightedRandomLootObject(Items.BONE.getDefaultStack(), 0, 2));
@@ -122,4 +122,9 @@ public class MobSkeleton extends MobMonsterArmored<HumanArmorShape>
 
         return HumanArmorShape.values()[index];
     }
+
+    @Override
+    public @Nullable ItemStack getHeldItem() {
+        return DEFAULT_HELD_ITEM;
+    }
 }
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSlime.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSlime.java
index a02eb8c4f..85f03b35a 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSlime.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSlime.java
@@ -23,7 +23,7 @@ public class MobSlime extends Mob
     {
         super(world);
         jumpDelay = 0;
-        textureIdentifier = new NamespaceID("minecraft", "slime");
+        setTextureIdentifier("minecraft", "slime");
         heightOffset = 0.0F;
         jumpDelay = 20;
         scoreValue = 100;
@@ -34,7 +34,7 @@ public class MobSlime extends Mob
     {
         super(world);
         jumpDelay = 0;
-        textureIdentifier = new NamespaceID("minecraft", "slime");
+        setTextureIdentifier("minecraft", "slime");
         heightOffset = 0.0F;
         jumpDelay = 20;
         scoreValue = 100;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSnowman.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSnowman.java
index 5b01ff77d..1fadbd2df 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSnowman.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSnowman.java
@@ -20,7 +20,7 @@ public class MobSnowman extends MobMonster
     public MobSnowman(World world)
     {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "snowman");
+        setTextureIdentifier("minecraft", "snowman");
         moveSpeed = 0.5F;
         attackStrength = 5;
         scoreValue = 300;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSpider.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSpider.java
index f1072a45c..79e4e10f0 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobSpider.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobSpider.java
@@ -17,7 +17,7 @@ public class MobSpider extends MobMonster
     public MobSpider(World world)
     {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "spider");
+        setTextureIdentifier("minecraft", "spider");
         setSize(1.4F, 0.9F);
         moveSpeed = 0.8F;
         scoreValue = 200;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombie.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombie.java
index 22d3f052b..5c27418a9 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombie.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombie.java
@@ -1,14 +1,8 @@
 package net.minecraft.core.entity.monster;
 
-import com.mojang.nbt.tags.CompoundTag;
-import com.mojang.nbt.tags.ListTag;
 import net.minecraft.core.WeightedRandomLootObject;
 import net.minecraft.core.enums.HumanArmorShape;
-import net.minecraft.core.item.Item;
-import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.Items;
-import net.minecraft.core.item.material.ArmorMaterial;
-import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.weather.Weather;
@@ -16,15 +10,11 @@ import net.minecraft.core.world.weather.Weathers;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
-
 public class MobZombie extends MobMonsterArmored<HumanArmorShape>
 {
-    public MobZombie(final World world) {
+    public MobZombie(final @NotNull World world) {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "zombie");
+        setTextureIdentifier("minecraft", "zombie");
         moveSpeed = 0.5F;
         attackStrength = 5;
         scoreValue = 300;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombieArmored.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombieArmored.java
index a161e2c91..2a3423f1e 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombieArmored.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombieArmored.java
@@ -29,10 +29,10 @@ public class MobZombieArmored extends MobZombie implements IItemHolding
         DEFAULT_HELD_ITEM = new ItemStack(Items.TOOL_SWORD_IRON, 1);
     }
 
-    public MobZombieArmored(World world)
+    public MobZombieArmored(@NotNull final World world)
     {
         super(world);
-        textureIdentifier = new NamespaceID("minecraft", "zombie_armored");
+        setTextureIdentifier("minecraft", "zombie_armored");
         scoreValue = 1000;
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java
index 1fa3117c4..ab6066da0 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/monster/MobZombiePig.java
@@ -36,7 +36,7 @@ public class MobZombiePig extends MobZombie
         super(world);
         angerLevel = 0;
         randomSoundDelay = 0;
-        textureIdentifier = new NamespaceID("minecraft", "pigzombie");
+        setTextureIdentifier("minecraft", "pigzombie");
         moveSpeed = 0.5F;
         attackStrength = 5;
         fireImmune = false;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
index 4a1e29987..4bbd1bd99 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java
@@ -144,8 +144,9 @@ public abstract class Player
         moveTo((double)chunkcoordinates.x + 0.5D, chunkcoordinates.y + 1, (double)chunkcoordinates.z + 0.5D, 0.0F, 0.0F);
 //        rotOffs = 180F;
         fireImmuneTicks = 20;
-        textureIdentifier = new NamespaceID("minecraft", "char");
+        setTextureIdentifier("minecraft", "char");
         damageRemainder = 0;
+        this.noAI = false;
     }
     @Override
     public int getMaxHealth(){
@@ -636,8 +637,9 @@ public abstract class Player
         this.heldObject = heldObject;
     }
 
+    @Override
     public @Nullable ICarriable getHeldObject() {
-        return heldObject;
+        return this.heldObject;
     }
 
     @Override
@@ -1620,7 +1622,7 @@ public abstract class Player
 		if(itemSlot == -1) {
 			if(getGamemode() == Gamemode.creative) {
 				int emptySlot = -1;
-				for(int i = 0; i < inventory.getContainerSize(); i++) {
+				for(int i = 0; i < 36; i++) {
 					if(inventory.getItem(i) == null) {
 						emptySlot = i;
 						break;
diff --git a/game/core/src/main/java/net/minecraft/core/entity/projectile/Projectile.java b/game/core/src/main/java/net/minecraft/core/entity/projectile/Projectile.java
index 23fcf5efa..d84b04c5a 100644
--- a/game/core/src/main/java/net/minecraft/core/entity/projectile/Projectile.java
+++ b/game/core/src/main/java/net/minecraft/core/entity/projectile/Projectile.java
@@ -85,10 +85,10 @@ public class Projectile extends Entity {
     }
 
     @Override
-    public boolean shouldRenderAtSqrDistance(double distance)
+    public boolean shouldRenderAtSqrDistance(final double distance, final double viewDistanceModifier)
     {
-        double d1 = bb.getSize() * 4D;
-        d1 *= 64D;
+        double d1 = this.bb.getSize() * 4D;
+        d1 *= 64D * viewDistanceModifier;
         return distance < d1 * d1;
     }
 
diff --git a/game/core/src/main/java/net/minecraft/core/util/collection/NamespaceID.java b/game/core/src/main/java/net/minecraft/core/util/collection/NamespaceID.java
index 89af7b7d0..2f85fc7db 100644
--- a/game/core/src/main/java/net/minecraft/core/util/collection/NamespaceID.java
+++ b/game/core/src/main/java/net/minecraft/core/util/collection/NamespaceID.java
@@ -17,8 +17,10 @@ public final class NamespaceID implements Comparator<NamespaceID>, Comparable<Na
     }
     public NamespaceID(String formattedString) throws HardIllegalArgumentException {
         if (!formattedString.contains(":")) throw new HardIllegalArgumentException("Formatted String '" + formattedString + "' missing ':' character all namespace ids must follow the format <namespace>:<value>!");
-        String[] split = formattedString.split(":");
-        if (split.length != 2) throw new HardIllegalArgumentException("Formatted String '" + formattedString + "' has more then 1 ':' character! all namespace ids must follow the format <namespace>:<value>!");
+        String[] split = formattedString.split(":", 2);
+        if (split.length != 2 || split[0].isEmpty()) throw new HardIllegalArgumentException("Formatted String '" + formattedString + "' is missing namespace! all namespace ids must follow the format <namespace>:<value>!");
+        if (split[1].isEmpty()) throw new HardIllegalArgumentException("Formatted String '" + formattedString + "' is missing value! all namespace ids must follow the format <namespace>:<value>!");
+        if (split[1].contains(":")) throw new HardIllegalArgumentException("Formatted String '" + formattedString + "' has more then 1 ':' character! all namespace ids must follow the format <namespace>:<value>!");
         namespace = split[0];
         value = split[1];
     }
diff --git a/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java b/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java
index f2d9785f7..54aa221c8 100644
--- a/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java
+++ b/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java
@@ -154,7 +154,7 @@ public class PlayerServer extends Player implements ContainerListener {
     }
 
     @Override
-	public void setWorld(World world)
+	public void setWorld(@NotNull final World world)
     {
         super.setWorld(world);
         playerController = new ServerPlayerController((WorldServer) world);
diff --git a/util/seed-viewer/src/main/java/org/useless/seedviewer/TestChunkProvider.java b/util/seed-viewer/src/main/java/org/useless/seedviewer/TestChunkProvider.java
index 964ddb241..0f597f9cd 100644
--- a/util/seed-viewer/src/main/java/org/useless/seedviewer/TestChunkProvider.java
+++ b/util/seed-viewer/src/main/java/org/useless/seedviewer/TestChunkProvider.java
@@ -1,9 +1,9 @@
 package org.useless.seedviewer;
 
+import net.minecraft.core.util.collection.NamespaceID;
 import org.useless.seedviewer.collections.ChunkLocation;
 import org.useless.seedviewer.collections.ChunkPos2D;
 import org.useless.seedviewer.collections.ChunkPos3D;
-import org.useless.seedviewer.collections.NamespaceID;
 import org.useless.seedviewer.data.Biome;
 import org.useless.seedviewer.data.Chunk;
 import org.useless.seedviewer.gui.ChunkProvider;
@@ -22,7 +22,7 @@ public class TestChunkProvider implements ChunkProvider {
 
                     @Override
                     public NamespaceID getID() {
-                        return new NamespaceID("viewer:test");
+                        return new NamespaceID("viewer", "test");
                     }
 
                     @Override
diff --git a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/BTABiome.java b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/BTABiome.java
index 0088af62d..e3f61e1d5 100644
--- a/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/BTABiome.java
+++ b/util/seed-viewer/src/main/java/org/useless/seedviewer/bta/BTABiome.java
@@ -2,7 +2,8 @@ package org.useless.seedviewer.bta;
 
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.lang.I18n;
-import org.useless.seedviewer.collections.NamespaceID;
+import net.minecraft.core.util.HardIllegalArgumentException;
+import net.minecraft.core.util.collection.NamespaceID;
 import org.useless.seedviewer.data.Biome;
 
 public class BTABiome implements Biome {
@@ -18,7 +19,11 @@ public class BTABiome implements Biome {
 
     @Override
     public NamespaceID getID() {
-        return new NamespaceID(Registries.BIOMES.getKey(biome));
+        try {
+            return new NamespaceID(Registries.BIOMES.getKey(biome));
+        } catch (HardIllegalArgumentException e) {
+            throw new IllegalArgumentException(e);
+        }
     }
 
     @Override
diff --git a/util/seed-viewer/src/main/java/org/useless/seedviewer/collections/NamespaceID.java b/util/seed-viewer/src/main/java/org/useless/seedviewer/collections/NamespaceID.java
deleted file mode 100644
index e83a58a17..000000000
--- a/util/seed-viewer/src/main/java/org/useless/seedviewer/collections/NamespaceID.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.useless.seedviewer.collections;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Objects;
-
-public final class NamespaceID {
-    private final @NotNull String combined;
-    public final @NotNull String namespace;
-    public final @NotNull String value;
-
-    public NamespaceID(@NotNull String namespace, @NotNull String value) {
-        validateNamespace(namespace);
-        validateValue(value);
-
-        this.combined = namespace + ":" + value;
-        this.namespace = namespace;
-        this.value = value;
-    }
-
-    public NamespaceID(@NotNull String formattedString) {
-        validateFormattedString(formattedString);
-
-        int colonIndex = formattedString.indexOf(":");
-        String _namespace = formattedString.substring(0, colonIndex);
-        String _value = formattedString.substring(colonIndex + 1);
-
-        validateNamespace(_namespace);
-        validateValue(_value);
-
-        this.combined = formattedString;
-        this.namespace = _namespace;
-        this.value = _value;
-    }
-
-    private void validateNamespace(String namespace) {
-        Objects.requireNonNull(namespace, "Namespace cannot be null!");
-        if (namespace.isEmpty()) throw new IllegalArgumentException("Namespace cannot be empty!");
-        if (namespace.contains(":")) throw new IllegalArgumentException("Namespace cannot contain ':'!");
-    }
-
-    private void validateValue(String value) {
-        Objects.requireNonNull(value, "Value cannot be null!");
-        if (value.isEmpty()) throw new IllegalArgumentException("Value cannot be empty!");
-        if (value.contains(":")) throw new IllegalArgumentException("Value cannot contain ':'!");
-    }
-
-    private void validateFormattedString(String formatted) {
-        Objects.requireNonNull(formatted, "String must not be null!");
-        if (!formatted.contains(":")) throw new IllegalArgumentException("String must contain a separator of ':'");
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null) return false;
-        if (o.getClass() == this.getClass()) {
-            return combined.equals(((NamespaceID) o).combined);
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return combined.hashCode();
-    }
-
-    @Override
-    public String toString() {
-        return combined;
-    }
-}
diff --git a/util/seed-viewer/src/main/java/org/useless/seedviewer/data/Biome.java b/util/seed-viewer/src/main/java/org/useless/seedviewer/data/Biome.java
index 57b70c018..5c4f56f7b 100644
--- a/util/seed-viewer/src/main/java/org/useless/seedviewer/data/Biome.java
+++ b/util/seed-viewer/src/main/java/org/useless/seedviewer/data/Biome.java
@@ -1,6 +1,6 @@
 package org.useless.seedviewer.data;
 
-import org.useless.seedviewer.collections.NamespaceID;
+import net.minecraft.core.util.collection.NamespaceID;
 
 public interface Biome {
     String getName();
diff --git a/util/seed-viewer/src/test/java/collections/NamespaceTest.java b/util/seed-viewer/src/test/java/collections/NamespaceTest.java
index e5b06e98d..1be1c8123 100644
--- a/util/seed-viewer/src/test/java/collections/NamespaceTest.java
+++ b/util/seed-viewer/src/test/java/collections/NamespaceTest.java
@@ -1,9 +1,10 @@
 package collections;
 
+import net.minecraft.core.util.HardIllegalArgumentException;
+import net.minecraft.core.util.collection.NamespaceID;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
-import org.useless.seedviewer.collections.NamespaceID;
 
 public class NamespaceTest {
     @Test
@@ -56,7 +57,7 @@ public class NamespaceTest {
 
     @Test
     @DisplayName("Test Namespace 1String Constructor")
-    void namespaceCreation2() {
+    void namespaceCreation2() throws HardIllegalArgumentException {
         String formatted_1 = "minecraft:value1";
         NamespaceID namespaceID_1 = new NamespaceID(formatted_1);
         Assertions.assertEquals(namespaceID_1.namespace, "minecraft");
@@ -76,11 +77,11 @@ public class NamespaceTest {
         Assertions.assertEquals(namespaceID_1.toString(), namespaceID_2.toString());
 
         Assertions.assertThrowsExactly(NullPointerException.class, () -> new NamespaceID(null));
-        Assertions.assertThrowsExactly(IllegalArgumentException.class, () -> new NamespaceID("minecraft::value1"));
-        Assertions.assertThrowsExactly(IllegalArgumentException.class, () -> new NamespaceID("minecraft:value1:"));
-        Assertions.assertThrowsExactly(IllegalArgumentException.class, () -> new NamespaceID(":value1"));
+        Assertions.assertThrowsExactly(HardIllegalArgumentException.class, () -> new NamespaceID("minecraft::value1"));
+        Assertions.assertThrowsExactly(HardIllegalArgumentException.class, () -> new NamespaceID("minecraft:value1:"));
+        Assertions.assertThrowsExactly(HardIllegalArgumentException.class, () -> new NamespaceID(":value1"));
         Assertions.assertDoesNotThrow(() -> new NamespaceID("minecraft:value"));
-        Assertions.assertThrowsExactly(IllegalArgumentException.class, () -> new NamespaceID("minecraft value"));
-        Assertions.assertThrowsExactly(IllegalArgumentException.class, () -> new NamespaceID("minecraft|value"));
+        Assertions.assertThrowsExactly(HardIllegalArgumentException.class, () -> new NamespaceID("minecraft value"));
+        Assertions.assertThrowsExactly(HardIllegalArgumentException.class, () -> new NamespaceID("minecraft|value"));
     }
 }
