diff --git a/.gitignore b/.gitignore
index 3deab9509..da66d74a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,5 @@
 src/main/java/net/minecraft/core/Version.java
 **.log
 BiomeLookup.png
-version.txt
\ No newline at end of file
+version.txt
+log4j.properties
diff --git a/build.gradle.kts b/build.gradle.kts
index 93a4bf8c8..153cb801a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -147,11 +147,14 @@ dependencies {
 
     implementation("objects:client:43db9b498cb67058d2e12d394e6507722e71bb45") // Minecraft client jar
 
-    val log4jVersion = "2.20.0"
-    implementation("org.apache.logging.log4j:log4j-core:${log4jVersion}")?.let { serverInclude(it) }
-    implementation("org.apache.logging.log4j:log4j-api:${log4jVersion}")?.let { serverInclude(it) }
-    implementation("org.apache.logging.log4j:log4j-1.2-api:${log4jVersion}")?.let { serverInclude(it) }
-    implementation("log4j:apache-log4j-extras:1.2.17")?.let { serverInclude (it) }
+    implementation("com.formdev:flatlaf:3.1.1")?.let { clientInclude(it) } // Dark theme used by SeedViewer
+    
+    implementation("org.slf4j:slf4j-api:2.0.7")?.let { clientInclude(it); serverInclude(it) }
+
+    val log4jVersion = "2.19.0"
+    implementation("org.apache.logging.log4j:log4j-core:${log4jVersion}")?.let { clientInclude(it); serverInclude(it) }
+    implementation("org.apache.logging.log4j:log4j-api:${log4jVersion}")?.let { clientInclude(it); serverInclude(it) }
+    implementation("org.apache.logging.log4j:log4j-slf4j2-impl:${log4jVersion}")?.let { clientInclude(it); serverInclude(it) }
 
     runtimeOnly(sourceSets.getByName("common").output)?.let { clientInclude(it); serverInclude(it) }
 }
diff --git a/devResources/sound/random/achievement1.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/achievement1.ogg
similarity index 100%
rename from devResources/sound/random/achievement1.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/achievement1.ogg
diff --git a/devResources/sound/random/achievement2.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/achievement2.ogg
similarity index 100%
rename from devResources/sound/random/achievement2.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/achievement2.ogg
diff --git a/devResources/sound/random/bite.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/bite.ogg
similarity index 100%
rename from devResources/sound/random/bite.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/bite.ogg
diff --git a/devResources/sound/random/bite_extended.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/bite_extended.ogg
similarity index 100%
rename from devResources/sound/random/bite_extended.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/bite_extended.ogg
diff --git a/devResources/sound/random/equip.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/equip.ogg
similarity index 100%
rename from devResources/sound/random/equip.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/equip.ogg
diff --git a/devResources/sound/random/page.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/page.ogg
similarity index 100%
rename from devResources/sound/random/page.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/page.ogg
diff --git a/devResources/sound/random/whoosh_in.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/whoosh_in.ogg
similarity index 100%
rename from devResources/sound/random/whoosh_in.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/whoosh_in.ogg
diff --git a/devResources/sound/random/whoosh_out.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/whoosh_out.ogg
similarity index 100%
rename from devResources/sound/random/whoosh_out.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/random/whoosh_out.ogg
diff --git a/devPacks/inTestingSoundsPack/assets/minecraft/sounds/sounds.json b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/sounds.json
new file mode 100644
index 000000000..8be244c7a
--- /dev/null
+++ b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/sounds.json
@@ -0,0 +1,49 @@
+{
+    "step.permafrost": {
+        "sounds": [
+            "step/permafrost1.ogg",
+            "step/permafrost2.ogg",
+            "step/permafrost3.ogg",
+            "step/permafrost4.ogg"
+        ]
+    },
+    "random.achievement": {
+        "sounds": [
+            "random/achievement1.ogg",
+            "random/achievement2.ogg"
+        ]
+    },
+    "random.bite": {
+        "subtitle": "subtitles.random.bite",
+        "sounds": [
+            "random/bite.ogg"
+        ]
+    },
+    "random.bite_extended": {
+        "subtitle": "subtitles.random.bite",
+        "sounds": [
+            "random/bite.ogg"
+        ]
+    },
+    "random.equip": {
+        "subtitle": "subtitles.random.equip",
+        "sounds": [
+            "random/equip.ogg"
+        ]
+    },
+    "random.page": {
+        "sounds": [
+            "random/page.ogg"
+        ]
+    },
+    "random.whoose.in": {
+        "sounds": [
+            "random/whoosh_in.ogg"
+        ]
+    },
+    "random.whoose.out": {
+        "sounds": [
+            "random/whoosh_out.ogg"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/devResources/sound/step/permafrost1.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/permafrost1.ogg
similarity index 100%
rename from devResources/sound/step/permafrost1.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/permafrost1.ogg
diff --git a/devResources/sound/step/permafrost2.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/permafrost2.ogg
similarity index 100%
rename from devResources/sound/step/permafrost2.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/permafrost2.ogg
diff --git a/devResources/sound/step/permafrost3.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/permafrost3.ogg
similarity index 100%
rename from devResources/sound/step/permafrost3.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/permafrost3.ogg
diff --git a/devResources/sound/step/permafrost4.ogg b/devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/permafrost4.ogg
similarity index 100%
rename from devResources/sound/step/permafrost4.ogg
rename to devPacks/inTestingSoundsPack/assets/minecraft/sounds/step/permafrost4.ogg
diff --git a/devResources/credits.txt b/devPacks/inTestingSoundsPack/credits.txt
similarity index 100%
rename from devResources/credits.txt
rename to devPacks/inTestingSoundsPack/credits.txt
diff --git a/devPacks/inTestingSoundsPack/manifest.json b/devPacks/inTestingSoundsPack/manifest.json
new file mode 100644
index 000000000..ad1ee857f
--- /dev/null
+++ b/devPacks/inTestingSoundsPack/manifest.json
@@ -0,0 +1,9 @@
+{
+    "description": {
+        "name": "§5In Testing Sounds",
+        "line1": "Sounds which we are considering adding",
+        "line2": "but havent added to the sound server yet.",
+        "packVersion": "7.3",
+        "format": 1
+    }
+}
diff --git a/src/main/resources/assets/minecraft/sounds/sounds.json b/src/common/resources/assets/minecraft/sounds/sounds.json
similarity index 74%
rename from src/main/resources/assets/minecraft/sounds/sounds.json
rename to src/common/resources/assets/minecraft/sounds/sounds.json
index 3c024bb37..e98ecd32b 100644
--- a/src/main/resources/assets/minecraft/sounds/sounds.json
+++ b/src/common/resources/assets/minecraft/sounds/sounds.json
@@ -1,5 +1,6 @@
 {
   "mob.wolf.bark": {
+    "subtitle": "subtitles.mob.wolf.bark",
     "sounds": [
       "mob/wolf/bark1.ogg",
       "mob/wolf/bark2.ogg",
@@ -7,6 +8,7 @@
     ]
   },
   "mob.sheep": {
+    "subtitle": "subtitles.mob.sheep",
     "sounds": [
       "mob/sheep1.ogg",
       "mob/sheep2.ogg",
@@ -14,11 +16,13 @@
     ]
   },
   "note.snare": {
+    "subtitle": "subtitles.note.snare",
     "sounds": [
       "note/snare.ogg"
     ]
   },
   "random.glass": {
+    "subtitle": "subtitles.random.glass",
     "sounds": [
       "random/glass1.ogg",
       "random/glass2.ogg",
@@ -26,6 +30,7 @@
     ]
   },
   "mob.zombiepig.zpigangry": {
+    "subtitle": "subtitles.mob.zombiepig.zpigangry",
     "sounds": [
       "mob/zombiepig/zpigangry1.ogg",
       "mob/zombiepig/zpigangry2.ogg",
@@ -34,11 +39,13 @@
     ]
   },
   "random.door_open": {
+    "subtitle": "subtitles.random.door_open",
     "sounds": [
       "random/door_open.ogg"
     ]
   },
   "mob.spider": {
+    "subtitle": "subtitles.mob.spider",
     "sounds": [
       "mob/spider1.ogg",
       "mob/spider2.ogg",
@@ -47,6 +54,7 @@
     ]
   },
   "mob.wolf.growl": {
+    "subtitle": "subtitles.mob.wolf.growl",
     "sounds": [
       "mob/wolf/growl1.ogg",
       "mob/wolf/growl2.ogg",
@@ -54,16 +62,19 @@
     ]
   },
   "mob.ghast.charge": {
+    "subtitle": "subtitles.mob.ghast.charge",
     "sounds": [
       "mob/ghast/charge.ogg"
     ]
   },
   "tile.piston.out": {
+    "subtitle": "subtitles.tile.piston.out",
     "sounds": [
       "tile/piston/out.ogg"
     ]
   },
   "damage.fallsmall": {
+    "subtitle": "subtitles.fall.small",
     "sounds": [
       "damage/fallsmall.ogg"
     ]
@@ -74,6 +85,7 @@
     ]
   },
   "mob.chicken": {
+    "subtitle": "subtitles.mob.chicken",
     "sounds": [
       "mob/chicken1.ogg",
       "mob/chicken2.ogg",
@@ -81,6 +93,7 @@
     ]
   },
   "damage.hurtflesh": {
+    "subtitle": "subtitles.hurt.flesh",
     "sounds": [
       "damage/hurtflesh1.ogg",
       "damage/hurtflesh2.ogg",
@@ -88,37 +101,44 @@
     ]
   },
   "liquid.water": {
+    "subtitle": "subtitles.liquid.water",
     "sounds": [
       "liquid/water.ogg"
     ]
   },
   "random.door_close": {
+    "subtitle": "subtitles.random.door_close",
     "sounds": [
       "random/door_close.ogg"
     ]
   },
   "mob.wolf.death": {
+    "subtitle": "subtitles.mob.wolf.death",
     "sounds": [
       "mob/wolf/death.ogg"
     ]
   },
   "mob.zombiehurt": {
+    "subtitle": "subtitles.mob.zombie.hurt",
     "sounds": [
       "mob/zombiehurt1.ogg",
       "mob/zombiehurt2.ogg"
     ]
   },
   "portal.portal": {
+    "subtitle": "subtitles.portal.portal",
     "sounds": [
       "portal/portal.ogg"
     ]
   },
   "random.fizz": {
+    "subtitle": "subtitles.random.fizz",
     "sounds": [
       "random/fizz.ogg"
     ]
   },
   "note.harp": {
+    "subtitle": "subtitles.note.harp",
     "sounds": [
       "note/harp.ogg"
     ]
@@ -132,11 +152,13 @@
     ]
   },
   "mob.wolf.whine": {
+    "subtitle": "subtitles.mob.wolf.whine",
     "sounds": [
       "mob/wolf/whine.ogg"
     ]
   },
   "note.pling": {
+    "subtitle": "subtitles.note.pling",
     "sounds": [
       "note/pling.ogg"
     ]
@@ -150,6 +172,7 @@
     ]
   },
   "ambient.weather.rain": {
+    "subtitle": "subtitles.ambient.weather.rain",
     "sounds": [
       "ambient/weather/rain1.ogg",
       "ambient/weather/rain2.ogg",
@@ -158,23 +181,27 @@
     ]
   },
   "mob.zombiepig.zpighurt": {
+    "subtitle": "subtitles.mob.zombiepig.zpighurt",
     "sounds": [
       "mob/zombiepig/zpighurt1.ogg",
       "mob/zombiepig/zpighurt2.ogg"
     ]
   },
   "mob.wolf.howl": {
+    "subtitle": "subtitles.mob.wolf.howl",
     "sounds": [
       "mob/wolf/howl1.ogg",
       "mob/wolf/howl2.ogg"
     ]
   },
   "mob.skeletondeath": {
+    "subtitle": "subtitles.mob.skeleton.death",
     "sounds": [
       "mob/skeletondeath.ogg"
     ]
   },
   "portal.trigger": {
+    "subtitle": "subtitles.portal.trigger",
     "sounds": [
       "portal/trigger.ogg"
     ]
@@ -185,16 +212,19 @@
     ]
   },
   "random.drr": {
+    "subtitle": "subtitles.random.drr",
     "sounds": [
       "random/drr.ogg"
     ]
   },
   "mob.zombiepig.zpigdeath": {
+    "subtitle": "subtitles.mob.zombiepig.zpigdeath",
     "sounds": [
       "mob/zombiepig/zpigdeath.ogg"
     ]
   },
   "ambient.weather.thunder": {
+    "subtitle": "subtitles.ambient.weather.thunder",
     "sounds": [
       "ambient/weather/thunder1.ogg",
       "ambient/weather/thunder2.ogg",
@@ -202,6 +232,7 @@
     ]
   },
   "mob.creeper": {
+    "subtitle": "subtitles.mob.creeper",
     "sounds": [
       "mob/creeper1.ogg",
       "mob/creeper2.ogg",
@@ -215,16 +246,19 @@
     ]
   },
   "mob.creeperdeath": {
+    "subtitle": "subtitles.mob.creeper.death",
     "sounds": [
       "mob/creeperdeath.ogg"
     ]
   },
   "note.hat": {
+    "subtitle": "subtitles.note.hat",
     "sounds": [
       "note/hat.ogg"
     ]
   },
   "mob.slime": {
+    "subtitle": "subtitles.mob.slime",
     "sounds": [
       "mob/slime1.ogg",
       "mob/slime2.ogg",
@@ -234,6 +268,7 @@
     ]
   },
   "mob.skeletonhurt": {
+    "subtitle": "subtitles.mob.skeleton.hurt",
     "sounds": [
       "mob/skeletonhurt1.ogg",
       "mob/skeletonhurt2.ogg",
@@ -242,21 +277,25 @@
     ]
   },
   "mob.wolf.panting": {
+    "subtitle": "subtitles.mob.wolf.panting",
     "sounds": [
       "mob/wolf/panting.ogg"
     ]
   },
   "note.bass": {
+    "subtitle": "subtitles.note.bass",
     "sounds": [
       "note/bass.ogg"
     ]
   },
   "random.fuse": {
+    "subtitle": "subtitles.random.fuse",
     "sounds": [
       "random/fuse.ogg"
     ]
   },
   "ambient.cave.cave": {
+    "subtitle": "subtitles.ambient.cave",
     "sounds": [
       "ambient/cave/cave1.ogg",
       "ambient/cave/cave10.ogg",
@@ -274,11 +313,13 @@
     ]
   },
   "mob.ghast.fireball": {
+    "subtitle": "subtitles.mob.ghast.fireball",
     "sounds": [
       "mob/ghast/fireball4.ogg"
     ]
   },
   "fire.ignite": {
+    "subtitle": "subtitles.fire.ignite",
     "sounds": [
       "fire/ignite.ogg"
     ]
@@ -289,12 +330,14 @@
     ]
   },
   "mob.chickenhurt": {
+    "subtitle": "subtitles.mob.chicken.hurt",
     "sounds": [
       "mob/chickenhurt1.ogg",
       "mob/chickenhurt2.ogg"
     ]
   },
   "mob.cowhurt": {
+    "subtitle": "subtitles.mob.cow.hurt",
     "sounds": [
       "mob/cowhurt1.ogg",
       "mob/cowhurt2.ogg",
@@ -306,12 +349,14 @@
       "ui/ui_back.ogg"
     ]
   },
-  "mob.ghast.affectionate scream": {
+  "mob.ghast.affectionate_scream": {
+    "subtitle": "subtitles.mob.ghast.affectionate_scream",
     "sounds": [
       "mob/ghast/affectionate scream.ogg"
     ]
   },
   "mob.ghast.death": {
+    "subtitle": "subtitles.mob.ghast.death",
     "sounds": [
       "mob/ghast/death.ogg"
     ]
@@ -322,6 +367,7 @@
     ]
   },
   "mob.zombiepig.zpig": {
+    "subtitle": "subtitles.mob.zombiepig.zpig",
     "sounds": [
       "mob/zombiepig/zpig1.ogg",
       "mob/zombiepig/zpig2.ogg",
@@ -330,16 +376,19 @@
     ]
   },
   "mob.chickenplop": {
+    "subtitle": "subtitles.mob.chicken.plop",
     "sounds": [
       "mob/chickenplop.ogg"
     ]
   },
   "random.explode": {
+    "subtitle": "subtitles.random.explode",
     "sounds": [
       "random/explode.ogg"
     ]
   },
   "mob.pig": {
+    "subtitle": "subtitles.mob.pig",
     "sounds": [
       "mob/pig1.ogg",
       "mob/pig2.ogg",
@@ -347,6 +396,7 @@
     ]
   },
   "random.bow": {
+    "subtitle": "subtitles.random.bow",
     "sounds": [
       "random/bow.ogg"
     ]
@@ -360,26 +410,31 @@
     ]
   },
   "mob.pigdeath": {
+    "subtitle": "subtitles.mob.pig.death",
     "sounds": [
       "mob/pigdeath.ogg"
     ]
   },
   "random.hurt": {
+    "subtitle": "subtitles.random.hurt",
     "sounds": [
       "random/hurt.ogg"
     ]
   },
   "random.splash": {
+    "subtitle": "subtitles.random.splash",
     "sounds": [
       "random/splash.ogg"
     ]
   },
   "random.breath": {
+    "subtitle": "subtitles.random.breath",
     "sounds": [
       "random/breath.ogg"
     ]
   },
   "mob.wolf.hurt": {
+    "subtitle": "subtitles.mob.wolf.hurt",
     "sounds": [
       "mob/wolf/hurt1.ogg",
       "mob/wolf/hurt2.ogg",
@@ -387,11 +442,13 @@
     ]
   },
   "liquid.lava": {
+    "subtitle": "subtitles.liquid.lava",
     "sounds": [
       "liquid/lava.ogg"
     ]
   },
   "mob.zombie": {
+    "subtitle": "subtitles.mob.zombie",
     "sounds": [
       "mob/zombie1.ogg",
       "mob/zombie2.ogg",
@@ -399,6 +456,7 @@
     ]
   },
   "note.bd": {
+    "subtitle": "subtitles.note.bd",
     "sounds": [
       "note/bd.ogg"
     ]
@@ -409,6 +467,7 @@
     ]
   },
   "mob.ghast.moan": {
+    "subtitle": "subtitles.mob.ghast.moan",
     "sounds": [
       "mob/ghast/moan1.ogg",
       "mob/ghast/moan2.ogg",
@@ -420,6 +479,7 @@
     ]
   },
   "fire.fire": {
+    "subtitle": "subtitles.fire.fire",
     "sounds": [
       "fire/fire.ogg"
     ]
@@ -433,6 +493,7 @@
     ]
   },
   "mob.ghast.scream": {
+    "subtitle": "subtitles.mob.ghast.scream",
     "sounds": [
       "mob/ghast/scream1.ogg",
       "mob/ghast/scream2.ogg",
@@ -442,22 +503,26 @@
     ]
   },
   "damage.fallbig": {
+    "subtitle": "subtitles.damage.fall.big",
     "sounds": [
       "damage/fallbig1.ogg",
       "damage/fallbig2.ogg"
     ]
   },
   "liquid.lavapop": {
+    "subtitle": "subtitles.liquid.lava.pop",
     "sounds": [
       "liquid/lavapop.ogg"
     ]
   },
   "note.bassattack": {
+    "subtitle": "subtitles.note.bassattack",
     "sounds": [
       "note/bassattack.ogg"
     ]
   },
   "mob.spiderdeath": {
+    "subtitle": "subtitles.mob.spider.death",
     "sounds": [
       "mob/spiderdeath.ogg"
     ]
@@ -476,6 +541,7 @@
     ]
   },
   "mob.skeleton": {
+    "subtitle": "subtitles.mob.skeleton",
     "sounds": [
       "mob/skeleton1.ogg",
       "mob/skeleton2.ogg",
@@ -483,22 +549,26 @@
     ]
   },
   "mob.slimeattack": {
+    "subtitle": "subtitles.mob.slime.attack",
     "sounds": [
       "mob/slimeattack1.ogg",
       "mob/slimeattack2.ogg"
     ]
   },
   "mob.zombiedeath": {
+    "subtitle": "subtitles.mob.zombie.death",
     "sounds": [
       "mob/zombiedeath.ogg"
     ]
   },
   "tile.piston.in": {
+    "subtitle": "subtitles.tile.piston.in",
     "sounds": [
       "tile/piston/in.ogg"
     ]
   },
   "mob.cow": {
+    "subtitle": "subtitles.mob.cow",
     "sounds": [
       "mob/cow1.ogg",
       "mob/cow2.ogg",
@@ -515,6 +585,7 @@
     ]
   },
   "random.pop": {
+    "subtitle": "subtitles.random.pop",
     "sounds": [
       "random/pop.ogg"
     ]
@@ -528,16 +599,19 @@
     ]
   },
   "portal.travel": {
+    "subtitle": "subtitles.portal.travel",
     "sounds": [
       "portal/travel.ogg"
     ]
   },
   "liquid.splash": {
+    "subtitle": "subtitles.liquid.splash",
     "sounds": [
       "liquid/splash.ogg"
     ]
   },
   "mob.wolf.shake": {
+    "subtitle": "subtitles.mob.wolf.shake",
     "sounds": [
       "mob/wolf/shake.ogg"
     ]
@@ -546,6 +620,8 @@
     "sounds": [
       {
         "name": "record/mall.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -554,6 +630,8 @@
     "sounds": [
       {
         "name": "record/dog.ogg",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -562,6 +640,8 @@
     "sounds": [
       {
         "name": "record/chirp.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -570,6 +650,8 @@
     "sounds": [
       {
         "name": "record/blocks.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -578,10 +660,14 @@
     "sounds": [
       {
         "name": "record/cat.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       },
       {
         "name": "record/cat.ogg",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -590,6 +676,8 @@
     "sounds": [
       {
         "name": "record/far.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -598,6 +686,8 @@
     "sounds": [
       {
         "name": "record/mellohi.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -606,6 +696,8 @@
     "sounds": [
       {
         "name": "record/wait.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -614,10 +706,14 @@
     "sounds": [
       {
         "name": "record/13.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       },
       {
         "name": "record/13.ogg",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -626,6 +722,8 @@
     "sounds": [
       {
         "name": "record/11.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -634,6 +732,8 @@
     "sounds": [
       {
         "name": "record/ward.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -642,6 +742,8 @@
     "sounds": [
       {
         "name": "record/stal.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
@@ -650,6 +752,8 @@
     "sounds": [
       {
         "name": "record/strad.mus",
+        "volume": 0.5,
+        "attenuation_distance": 64,
         "stream": true
       }
     ]
diff --git a/src/common/resources/lang/en_US/gui.lang b/src/common/resources/lang/en_US/gui.lang
index a04074ff7..03fe0ba6e 100644
--- a/src/common/resources/lang/en_US/gui.lang
+++ b/src/common/resources/lang/en_US/gui.lang
@@ -229,7 +229,7 @@ gui.options.page.debug.category.utility=Utilities
 gui.options.page.debug.category.settings=Settings
 gui.options.page.debug.category.test=Tests
 gui.options.page.debug.button.open.model_viewer=Open Model Viewer
-gui.options.page.debug.button.open.biome_finder=Open Biome Finder
+gui.options.page.debug.button.open.biome_finder=Open Seed Viewer
 gui.options.page.debug.button.open.datadumper=Run Data Dumper
 gui.options.page.debug.button.open.sound_test=Open Sound Test
 gui.options.page.debug.button.open.texture_viewer=Open Texture Viewer
@@ -246,7 +246,7 @@ gui.options.page.search.title=Search
 gui.sound_test.label.title=Sound Test
 gui.sound_test.label.repo=Sound Repository: %s
 gui.sound_test.label.id=ID: %s
-gui.sound_test.label.name=Name: %s
+gui.sound_test.label.subtitle=Subtitle: %s | %s
 gui.sound_test.label.url=URL: %s
 gui.sound_test.label.select_repo=Select Repo:
 gui.sound_test.label.select_entry=Select Entry:
diff --git a/src/common/resources/lang/en_US/options.lang b/src/common/resources/lang/en_US/options.lang
index 5f4904060..5ddc13e90 100644
--- a/src/common/resources/lang/en_US/options.lang
+++ b/src/common/resources/lang/en_US/options.lang
@@ -165,6 +165,7 @@ options.disableShaders=Disable Shaders
 options.loadAllSounds=Load All Sounds
 options.allowSoundOverrides=Allow Sound Overrides
 options.downloadSoundfiles=Download Sound Files
+options.subtitles=Subtitles
 
 options.tooltipStyle.default=Default
 options.tooltipStyle.modern=Modern
diff --git a/src/common/resources/lang/en_US/subtitles.lang b/src/common/resources/lang/en_US/subtitles.lang
index e69de29bb..3cb37f19b 100644
--- a/src/common/resources/lang/en_US/subtitles.lang
+++ b/src/common/resources/lang/en_US/subtitles.lang
@@ -0,0 +1,85 @@
+subtitles.mob.sheep=Sheep bleat
+subtitles.mob.chicken=Chicken clucking
+subtitles.mob.chicken.hurt=Chicken hurt
+subtitles.mob.chicken.plop=Chicken plop
+subtitles.mob.pig=Pig oinking
+subtitles.mob.pig.death=Pig death
+subtitles.mob.wolf.howl=Wolf howl
+subtitles.mob.wolf.panting=Wolf panting
+subtitles.mob.wolf.hurt=Wolf hurt
+subtitles.mob.wolf.bark=Wolf Bark
+subtitles.mob.wolf.growl=Wolf growl
+subtitles.mob.wolf.death=Wolf death
+subtitles.mob.wolf.whine=Wolf whine
+subtitles.mob.wolf.shake=Wolf shaking
+subtitles.mob.cow.hurt=Cow hurt
+subtitles.mob.cow=Cow mooing
+subtitles.mob.zombie=Zombie groans
+subtitles.mob.zombie.hurt=Zombie hurt
+subtitles.mob.zombie.death=Zombie death
+subtitles.mob.zombiepig.zpighurt=Zombie pigman hurt
+subtitles.mob.zombiepig.zpig=Zombie pigman groans
+subtitles.mob.zombiepig.zpigdeath=Zombie pigman death
+subtitles.mob.zombiepig.zpigangry=Zombie pigman angry
+subtitles.mob.skeleton=Skeleton rattles
+subtitles.mob.skeleton.death=Skeleton death
+subtitles.mob.skeleton.hurt=Skeleton hurt
+subtitles.mob.ghast.fireball=Ghast fireball
+subtitles.mob.ghast.moan=Ghast moan
+subtitles.mob.ghast.death=Ghast death
+subtitles.mob.ghast.scream=Ghast Scream
+subtitles.mob.ghast.affectionate_scream=Ghast affectionate scream
+subtitles.mob.creeper=Creeper hiss
+subtitles.mob.creeper.death=Creeper death
+subtitles.mob.spider.death=Spider death
+subtitles.mob.spider=Spider hiss
+subtitles.mob.ghast.charge=Ghast charging
+subtitles.mob.slime.attack=Slime attack
+subtitles.mob.slime=Slime plop
+
+subtitles.fall.small=Small fall
+subtitles.damage.fall.big=Big fall
+
+subtitles.liquid.water=Water flowing
+subtitles.liquid.lava.pop=Lava pop
+subtitles.liquid.lava=Lava bubbling
+subtitles.liquid.splash=Water splash
+
+subtitles.portal.portal=Portal ambience
+subtitles.portal.trigger=Portal trigger
+subtitles.portal.travel=Portal travel
+
+subtitles.random.fizz=Fizzing
+subtitles.random.drr=Arrow drr
+subtitles.random.fuse=Fuse lit
+subtitles.random.pop=Pop
+subtitles.random.glass=Glass
+subtitles.random.door_open=Door opened
+subtitles.random.door_close=Door closed
+subtitles.random.explode=Explosion
+subtitles.random.bow=Bow shot
+subtitles.random.hurt=Hurt
+subtitles.random.splash=Splash
+subtitles.random.breath=Breath
+subtitles.random.bite=Player Eating
+subtitles.random.equip=Armor Equipped
+
+subtitles.note.snare=Note snare
+subtitles.note.harp=Note harp
+subtitles.note.bass=Note bass
+subtitles.note.bd=Note bd
+subtitles.note.pling=Note pling
+subtitles.note.hat=Note hat
+subtitles.note.bassattack=Note bass attack
+
+subtitles.ambient.weather.thunder=Thunder
+subtitles.ambient.cave=Cave ambience
+subtitles.ambient.weather.rain=Rainfall
+
+subtitles.tile.piston.out=Piston extended
+subtitles.tile.piston.in=Piston retracted
+
+subtitles.hurt.flesh=Hurt flesh
+
+subtitles.fire.ignite=Fire lit
+subtitles.fire.fire=Fire crackling
diff --git a/src/common/resources/log4j2.xml b/src/common/resources/log4j2.xml
new file mode 100644
index 000000000..e4cf2345c
--- /dev/null
+++ b/src/common/resources/log4j2.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="WARN" packages="com.mojang.logging.plugins">
+    <Appenders>
+        <Console name="SysOut" target="SYSTEM_OUT">
+            <PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg{nolookups}%n" />
+        </Console>
+        <Queue name="ServerGuiConsole">
+            <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg{nolookups}%n" />
+        </Queue>
+        <RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
+            <PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg{nolookups}%n" />
+            <Policies>
+                <TimeBasedTriggeringPolicy />
+                <OnStartupTriggeringPolicy />
+            </Policies>
+        </RollingRandomAccessFile>
+    </Appenders>
+    <Loggers>
+        <Root level="info">
+            <filters>
+                <MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL" />
+            </filters>
+            <AppenderRef ref="SysOut"/>
+            <AppenderRef ref="File"/>
+            <AppenderRef ref="ServerGuiConsole"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/src/main/java/com/b100/utils/FileUtils.java b/src/main/java/com/b100/utils/FileUtils.java
index 214ec3fb1..1f8f5eeda 100644
--- a/src/main/java/com/b100/utils/FileUtils.java
+++ b/src/main/java/com/b100/utils/FileUtils.java
@@ -9,6 +9,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URL;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -132,8 +133,8 @@ public abstract class FileUtils {
 		try {
 			createNewFile(to);
 			
-			InputStream in = new FileInputStream(from);
-			OutputStream out = new FileOutputStream(to);
+			InputStream in = Files.newInputStream(from.toPath());
+			OutputStream out = Files.newOutputStream(to.toPath());
 			
 			StreamUtils.transferData(in, out);
 			
@@ -197,7 +198,7 @@ public abstract class FileUtils {
 		FileUtils.createNewFile(file);
 		
 		BufferedInputStream in = new BufferedInputStream(url.openStream());
-		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
+		BufferedOutputStream out = new BufferedOutputStream(Files.newOutputStream(file.toPath()));
 		
 		StreamUtils.transferDataAndClose(in, out);
 	}
diff --git a/src/main/java/com/b100/utils/ImageUtils.java b/src/main/java/com/b100/utils/ImageUtils.java
index cb50685b0..f506ce526 100644
--- a/src/main/java/com/b100/utils/ImageUtils.java
+++ b/src/main/java/com/b100/utils/ImageUtils.java
@@ -11,6 +11,8 @@ import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
 
 import javax.imageio.ImageIO;
 
@@ -34,9 +36,9 @@ public abstract class ImageUtils {
 			throw new RuntimeException("Not a file: "+file.getAbsolutePath());
 		}
 		
-		FileInputStream stream;
+		InputStream stream;
 		try {
-			stream = new FileInputStream(file);
+			stream = Files.newInputStream(file.toPath());
 		}catch (Exception e) {
 			throw new RuntimeException("Could not open file", e);
 		}
diff --git a/src/main/java/com/b100/utils/ReflectUtils.java b/src/main/java/com/b100/utils/ReflectUtils.java
index b0b7a0e5a..49874eb98 100644
--- a/src/main/java/com/b100/utils/ReflectUtils.java
+++ b/src/main/java/com/b100/utils/ReflectUtils.java
@@ -1,5 +1,7 @@
 package com.b100.utils;
 
+import net.minecraft.core.Global;
+
 import static com.b100.utils.Utils.*;
 
 import java.lang.reflect.Field;
diff --git a/src/main/java/com/b100/utils/StringUtils.java b/src/main/java/com/b100/utils/StringUtils.java
index 9394eee83..d7a0bc78a 100644
--- a/src/main/java/com/b100/utils/StringUtils.java
+++ b/src/main/java/com/b100/utils/StringUtils.java
@@ -7,6 +7,7 @@ import java.io.FileWriter;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URL;
+import java.nio.file.Files;
 import java.util.List;
 
 public abstract class StringUtils {
@@ -21,7 +22,7 @@ public abstract class StringUtils {
 		FileUtils.validateFileExists(file);
 		
 		try{
-			return readInputString(new FileInputStream(file));
+			return readInputString(Files.newInputStream(file.toPath()));
 		}catch (Exception e) {
 			throw new RuntimeException("Error while reading file", e);
 		}
diff --git a/src/main/java/com/mojang/logging/LogQueues.java b/src/main/java/com/mojang/logging/LogQueues.java
new file mode 100644
index 000000000..9c9d625c9
--- /dev/null
+++ b/src/main/java/com/mojang/logging/LogQueues.java
@@ -0,0 +1,54 @@
+// 
+// Decompiled by Procyon v0.6.0
+// 
+
+package com.mojang.logging;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.BlockingQueue;
+import java.util.Map;
+
+public class LogQueues
+{
+    private static final Map<String, BlockingQueue<String>> QUEUES = new HashMap<>();
+    private static final ReentrantReadWriteLock QUEUE_LOCK = new ReentrantReadWriteLock();
+    
+    public static BlockingQueue<String> getOrCreateQueue(final String target) {
+        try {
+            LogQueues.QUEUE_LOCK.readLock().lock();
+            final BlockingQueue<String> queue = LogQueues.QUEUES.get(target);
+            if (queue != null) {
+                return queue;
+            }
+        }
+        finally {
+            LogQueues.QUEUE_LOCK.readLock().unlock();
+        }
+        try {
+            LogQueues.QUEUE_LOCK.writeLock().lock();
+            return LogQueues.QUEUES.computeIfAbsent(target, k -> new LinkedBlockingQueue<>());
+        }
+        finally {
+            LogQueues.QUEUE_LOCK.writeLock().unlock();
+        }
+    }
+    
+    @Nullable
+    public static String getNextLogEvent(final String queueName) {
+        LogQueues.QUEUE_LOCK.readLock().lock();
+        final BlockingQueue<String> queue = LogQueues.QUEUES.get(queueName);
+        LogQueues.QUEUE_LOCK.readLock().unlock();
+        if (queue != null) {
+            try {
+                return queue.take();
+            }
+            catch (final InterruptedException ignored) {}
+        }
+        return null;
+    }
+
+}
diff --git a/src/main/java/com/mojang/logging/LogUtils.java b/src/main/java/com/mojang/logging/LogUtils.java
new file mode 100644
index 000000000..521a5ab35
--- /dev/null
+++ b/src/main/java/com/mojang/logging/LogUtils.java
@@ -0,0 +1,89 @@
+// 
+// Decompiled by Procyon v0.6.0
+// 
+
+package com.mojang.logging;
+
+import org.slf4j.MarkerFactory;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+import java.util.function.Supplier;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.slf4j.event.Level;
+import org.apache.logging.log4j.spi.LoggerContext;
+import org.apache.logging.log4j.core.LifeCycle;
+import org.apache.logging.log4j.LogManager;
+import org.slf4j.Marker;
+
+public class LogUtils
+{
+    public static final String FATAL_MARKER_ID = "FATAL";
+    public static final Marker FATAL_MARKER = MarkerFactory.getMarker(FATAL_MARKER_ID);
+//    private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+    
+    public static boolean isLoggerActive() {
+        final LoggerContext loggerContext = LogManager.getContext();
+        if (loggerContext instanceof LifeCycle) {
+            LifeCycle lifeCycle = (LifeCycle) loggerContext;
+            return !lifeCycle.isStopped();
+        }
+        return true;
+    }
+    
+    public static void configureRootLoggingLevel(final Level level) {
+        final org.apache.logging.log4j.core.LoggerContext ctx = (org.apache.logging.log4j.core.LoggerContext)LogManager.getContext(false);
+        final Configuration config = ctx.getConfiguration();
+        final LoggerConfig loggerConfig = config.getLoggerConfig("");
+        loggerConfig.setLevel(convertLevel(level));
+        ctx.updateLoggers();
+    }
+    
+    private static org.apache.logging.log4j.Level convertLevel(final Level level) {
+        switch (level) {
+            case INFO:
+                return org.apache.logging.log4j.Level.INFO;
+            case WARN:
+                return org.apache.logging.log4j.Level.WARN;
+            case DEBUG:
+                return org.apache.logging.log4j.Level.DEBUG;
+            case ERROR:
+                return org.apache.logging.log4j.Level.ERROR;
+            case TRACE:
+                return org.apache.logging.log4j.Level.TRACE;
+            default:
+                throw new IncompatibleClassChangeError();
+        }
+    }
+    
+    public static Object defer(final Supplier<Object> result) {
+        class ToString
+        {
+            @Override
+            public String toString() {
+                return result.get().toString();
+            }
+        }
+        return new ToString();
+    }
+    
+    public static Logger getLogger() {
+        return LoggerFactory.getLogger(getCallerClass());
+    }
+
+    private static Class<?> getCallerClass() { // Hacky way to replace the STACK_WALKER since STACK_WALKER uses java 9 language features
+        try {
+            StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
+            for (int i=1; i<stElements.length; i++) {
+                StackTraceElement ste = stElements[i];
+                if (!ste.getClassName().equals(LogUtils.class.getName()) && ste.getClassName().indexOf("java.lang.Thread")!=0) {
+                    return Class.forName(ste.getClassName());
+                }
+            }
+        } catch (ClassNotFoundException notFoundException) {
+            System.err.print("Could not find calling class!");
+        }
+        return LogUtils.class;
+    }
+
+}
diff --git a/src/main/java/com/mojang/logging/annotations/FieldsAreNonnullByDefault.java b/src/main/java/com/mojang/logging/annotations/FieldsAreNonnullByDefault.java
new file mode 100644
index 000000000..28ea0f259
--- /dev/null
+++ b/src/main/java/com/mojang/logging/annotations/FieldsAreNonnullByDefault.java
@@ -0,0 +1,14 @@
+// 
+// Decompiled by Procyon v0.6.0
+// 
+
+package com.mojang.logging.annotations;
+
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Retention;
+
+//@Nonnull
+//@TypeQualifierDefault({ ElementType.FIELD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FieldsAreNonnullByDefault {
+}
diff --git a/src/main/java/com/mojang/logging/annotations/MethodsReturnNonnullByDefault.java b/src/main/java/com/mojang/logging/annotations/MethodsReturnNonnullByDefault.java
new file mode 100644
index 000000000..3b35754cb
--- /dev/null
+++ b/src/main/java/com/mojang/logging/annotations/MethodsReturnNonnullByDefault.java
@@ -0,0 +1,14 @@
+// 
+// Decompiled by Procyon v0.6.0
+// 
+
+package com.mojang.logging.annotations;
+
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Retention;
+
+//@Nonnull
+//@TypeQualifierDefault({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MethodsReturnNonnullByDefault {
+}
diff --git a/src/main/java/com/mojang/logging/plugins/LegacyXMLLayout.java b/src/main/java/com/mojang/logging/plugins/LegacyXMLLayout.java
new file mode 100644
index 000000000..d4dcc1ed2
--- /dev/null
+++ b/src/main/java/com/mojang/logging/plugins/LegacyXMLLayout.java
@@ -0,0 +1,250 @@
+// 
+// Decompiled by Procyon v0.6.0
+// 
+
+package com.mojang.logging.plugins;
+
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.Level;
+import java.util.HashMap;
+import java.util.List;
+import org.apache.logging.log4j.message.Message;
+import java.util.Map;
+import org.apache.logging.log4j.core.util.Throwables;
+import org.apache.logging.log4j.message.MultiformatMessage;
+import org.apache.logging.log4j.core.util.Transform;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.util.Strings;
+import java.nio.charset.Charset;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.layout.AbstractStringLayout;
+
+@Plugin(name = "LegacyXMLLayout", category = "Core", elementType = "layout", printObject = true)
+public class LegacyXMLLayout extends AbstractStringLayout
+{
+    private static final String XML_NAMESPACE = "http://logging.apache.org/log4j/2.0/events";
+    private static final String ROOT_TAG = "Events";
+    private static final int DEFAULT_SIZE = 256;
+    private static final String DEFAULT_EOL = "\r\n";
+    private static final String COMPACT_EOL = "";
+    private static final String DEFAULT_INDENT = "  ";
+    private static final String COMPACT_INDENT = "";
+    private static final String DEFAULT_NS_PREFIX = "log4j";
+    private static final String[] FORMATS = new String[] { "xml" };
+    private final boolean locationInfo;
+    private final boolean properties;
+    private final boolean complete;
+    private final String namespacePrefix;
+    private final String eol;
+    private final String indent1;
+    private final String indent2;
+    private final String indent3;
+    
+    protected LegacyXMLLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact, final String nsPrefix, final Charset charset) {
+        super(charset);
+        this.locationInfo = locationInfo;
+        this.properties = properties;
+        this.complete = complete;
+        this.eol = (compact ? COMPACT_EOL : DEFAULT_EOL);
+        this.indent1 = (compact ? COMPACT_INDENT : DEFAULT_INDENT);
+        this.indent2 = this.indent1 + this.indent1;
+        this.indent3 = this.indent2 + this.indent1;
+        this.namespacePrefix = (Strings.isEmpty(nsPrefix) ? DEFAULT_NS_PREFIX : nsPrefix);
+    }
+    
+    public String toSerializable(final LogEvent event) {
+        final StringBuilder buf = new StringBuilder(DEFAULT_SIZE);
+        buf.append(this.indent1);
+        buf.append('<');
+        if (!this.complete) {
+            buf.append(this.namespacePrefix);
+        }
+        buf.append("Event logger=\"");
+        String name = event.getLoggerName();
+        if (name.isEmpty()) {
+            name = "root";
+        }
+        buf.append(Transform.escapeHtmlTags(name));
+        buf.append("\" timestamp=\"");
+        buf.append(event.getTimeMillis());
+        buf.append("\" level=\"");
+        buf.append(Transform.escapeHtmlTags(getEventLevel(event)));
+        buf.append("\" thread=\"");
+        buf.append(Transform.escapeHtmlTags(event.getThreadName()));
+        buf.append("\">");
+        buf.append(this.eol);
+        final Message msg = event.getMessage();
+        if (msg != null) {
+            boolean xmlSupported = false;
+            if (msg instanceof MultiformatMessage) {
+                final String[] formats2 = ((MultiformatMessage) msg).getFormats();
+                for (final String format : formats2) {
+                    if (format.equalsIgnoreCase("XML")) {
+                        xmlSupported = true;
+                        break;
+                    }
+                }
+            }
+            buf.append(this.indent2);
+            buf.append('<');
+            if (!this.complete) {
+                buf.append(this.namespacePrefix);
+            }
+            buf.append("Message>");
+            if (xmlSupported) {
+                buf.append(((MultiformatMessage)msg).getFormattedMessage(LegacyXMLLayout.FORMATS));
+            }
+            else {
+                buf.append("<![CDATA[");
+                Transform.appendEscapingCData(buf, event.getMessage().getFormattedMessage());
+                buf.append("]]>");
+            }
+            buf.append("</");
+            if (!this.complete) {
+                buf.append(this.namespacePrefix);
+            }
+            buf.append("Message>");
+            buf.append(this.eol);
+        }
+        if (event.getContextStack().getDepth() > 0) {
+            buf.append(this.indent2);
+            buf.append('<');
+            if (!this.complete) {
+                buf.append(this.namespacePrefix);
+            }
+            buf.append("NDC><![CDATA[");
+            Transform.appendEscapingCData(buf, event.getContextStack().toString());
+            buf.append("]]></");
+            if (!this.complete) {
+                buf.append(this.namespacePrefix);
+            }
+            buf.append("NDC>");
+            buf.append(this.eol);
+        }
+        final Throwable throwable = event.getThrown();
+        if (throwable != null) {
+            final List<String> s = Throwables.toStringList(throwable);
+            buf.append(this.indent2);
+            buf.append('<');
+            if (!this.complete) {
+                buf.append(this.namespacePrefix);
+            }
+            buf.append("Throwable><![CDATA[");
+            for (final String str : s) {
+                Transform.appendEscapingCData(buf, str);
+                buf.append(this.eol);
+            }
+            buf.append("]]></");
+            if (!this.complete) {
+                buf.append(this.namespacePrefix);
+            }
+            buf.append("Throwable>");
+            buf.append(this.eol);
+        }
+        if (this.locationInfo) {
+            final StackTraceElement element = event.getSource();
+            buf.append(this.indent2);
+            buf.append('<');
+            if (!this.complete) {
+                buf.append(this.namespacePrefix);
+            }
+            buf.append("LocationInfo class=\"");
+            buf.append(Transform.escapeHtmlTags(element.getClassName()));
+            buf.append("\" method=\"");
+            buf.append(Transform.escapeHtmlTags(element.getMethodName()));
+            buf.append("\" file=\"");
+            buf.append(Transform.escapeHtmlTags(element.getFileName()));
+            buf.append("\" line=\"");
+            buf.append(element.getLineNumber());
+            buf.append("\"/>");
+            buf.append(this.eol);
+        }
+        if (this.properties && event.getContextMap().size() > 0) {
+            buf.append(this.indent2);
+            buf.append('<');
+            if (!this.complete) {
+                buf.append(this.namespacePrefix);
+            }
+            buf.append("Properties>");
+            buf.append(this.eol);
+            for (final Map.Entry<String, String> entry : event.getContextMap().entrySet()) {
+                buf.append(this.indent3);
+                buf.append('<');
+                if (!this.complete) {
+                    buf.append(this.namespacePrefix);
+                }
+                buf.append("Data name=\"");
+                buf.append(Transform.escapeHtmlTags(entry.getKey()));
+                buf.append("\" value=\"");
+                buf.append(Transform.escapeHtmlTags(String.valueOf(entry.getValue())));
+                buf.append("\"/>");
+                buf.append(this.eol);
+            }
+            buf.append(this.indent2);
+            buf.append("</");
+            if (!this.complete) {
+                buf.append(this.namespacePrefix);
+            }
+            buf.append("Properties>");
+            buf.append(this.eol);
+        }
+        buf.append(this.indent1);
+        buf.append("</");
+        if (!this.complete) {
+            buf.append(this.namespacePrefix);
+        }
+        buf.append("Event>");
+        buf.append(this.eol);
+        return buf.toString();
+    }
+    
+    public byte[] getHeader() {
+        if (!this.complete) {
+            return null;
+        }
+        final StringBuilder buf = new StringBuilder();
+        buf.append("<?xml version=\"1.0\" encoding=\"");
+        buf.append(this.getCharset().name());
+        buf.append("\"?>");
+        buf.append(this.eol);
+        buf.append('<');
+        buf.append(ROOT_TAG);
+        buf.append(" xmlns=\"" + XML_NAMESPACE + "\">");
+        buf.append(this.eol);
+        return buf.toString().getBytes(this.getCharset());
+    }
+    
+    public byte[] getFooter() {
+        if (!this.complete) {
+            return null;
+        }
+        return ("</" + ROOT_TAG + ">" + this.eol).getBytes(this.getCharset());
+    }
+    
+    public Map<String, String> getContentFormat() {
+        final Map<String, String> result = new HashMap<String, String>();
+        result.put("xsd", "log4j-events.xsd");
+        result.put("version", "2.0");
+        return result;
+    }
+    
+    public String getContentType() {
+        return "text/xml; charset=" + this.getCharset();
+    }
+    
+    private static String getEventLevel(final LogEvent event) {
+        final Marker marker = event.getMarker();
+        if (marker != null && marker.isInstanceOf("FATAL")) {
+            return String.valueOf(Level.FATAL);
+        }
+        return String.valueOf(event.getLevel());
+    }
+    
+    @PluginFactory
+    public static LegacyXMLLayout createLayout(@PluginAttribute("locationInfo") final boolean locationInfo, @PluginAttribute("properties") final boolean properties, @PluginAttribute("complete") final boolean completeStr, @PluginAttribute("compact") final boolean compactStr, @PluginAttribute("namespacePrefix") final String namespacePrefix, @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset) {
+        return new LegacyXMLLayout(locationInfo, properties, completeStr, compactStr, namespacePrefix, charset);
+    }
+
+}
diff --git a/src/main/java/com/mojang/logging/plugins/QueueLogAppender.java b/src/main/java/com/mojang/logging/plugins/QueueLogAppender.java
new file mode 100644
index 000000000..0d1605c67
--- /dev/null
+++ b/src/main/java/com/mojang/logging/plugins/QueueLogAppender.java
@@ -0,0 +1,57 @@
+// 
+// Decompiled by Procyon v0.6.0
+// 
+
+package com.mojang.logging.plugins;
+
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import com.mojang.logging.LogQueues;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.LogEvent;
+import java.io.Serializable;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.Filter;
+import java.util.concurrent.BlockingQueue;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+
+@Plugin(name = "Queue", category = "Core", elementType = "appender", printObject = true)
+public class QueueLogAppender extends AbstractAppender
+{
+    private static final int MAX_CAPACITY = 250;
+    private final BlockingQueue<String> queue;
+    
+    public QueueLogAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout, final boolean ignoreExceptions, final BlockingQueue<String> queue) {
+        super(name, filter, layout, ignoreExceptions);
+        this.queue = queue;
+    }
+    
+    public void append(final LogEvent event) {
+        if (this.queue.size() >= MAX_CAPACITY) {
+            this.queue.clear();
+        }
+        this.queue.add(this.getLayout().toSerializable(event).toString());
+    }
+    
+    @PluginFactory
+    public static QueueLogAppender createAppender(@PluginAttribute("name") final String name, @PluginAttribute("ignoreExceptions") final String ignore, @PluginElement("Layout") Layout<? extends Serializable> layout, @PluginElement("Filters") final Filter filter, @PluginAttribute("target") final String target) {
+        final boolean ignoreExceptions = Boolean.parseBoolean(ignore);
+        if (name == null) {
+            QueueLogAppender.LOGGER.error("No name provided for QueueLogAppender");
+            return null;
+        }
+        final BlockingQueue<String> queue = LogQueues.getOrCreateQueue(requireNonNullElse(target, name));
+        if (layout == null) {
+            layout = PatternLayout.newBuilder().build();
+        }
+        return new QueueLogAppender(name, filter, layout, ignoreExceptions, queue);
+    }
+
+    private static <T> T requireNonNullElse(T obj, T defaultObj) {
+        if (obj != null) return obj;
+        if (defaultObj != null) return defaultObj;
+        throw new NullPointerException("defaultObj");
+    }
+}
diff --git a/src/main/java/com/mojang/nbt/LongArrayTag.java b/src/main/java/com/mojang/nbt/LongArrayTag.java
new file mode 100644
index 000000000..8042bdea3
--- /dev/null
+++ b/src/main/java/com/mojang/nbt/LongArrayTag.java
@@ -0,0 +1,45 @@
+package com.mojang.nbt;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class LongArrayTag extends Tag<long[]>{
+    public LongArrayTag()
+    {
+        setValue(new long[0]);
+    }
+
+    public LongArrayTag(long[] array)
+    {
+        super(array);
+    }
+    @Override
+    void write(DataOutput dos)
+        throws IOException
+    {
+        dos.writeInt(getValue().length);
+        byte[] bytes = new byte[getValue().length * 4];
+        ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(getValue());
+        dos.write(bytes);
+
+    }
+
+    @Override
+    void read(DataInput dis)
+        throws IOException
+    {
+        int length = dis.readInt();
+        setValue(new long[length]);
+        byte[] bytes = new byte[length * 4];
+        dis.readFully(bytes);
+        ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().get(getValue());
+    }
+
+    @Override
+    public byte getId() {
+        return 13;
+    }
+}
diff --git a/src/main/java/net/betterthanadventure/utils/BiomeFinder.java b/src/main/java/net/betterthanadventure/utils/BiomeFinder.java
index 2b74f56c4..c7d7813c0 100644
--- a/src/main/java/net/betterthanadventure/utils/BiomeFinder.java
+++ b/src/main/java/net/betterthanadventure/utils/BiomeFinder.java
@@ -1,11 +1,14 @@
 package net.betterthanadventure.utils;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.world.chunk.provider.ChunkProviderDynamic;
 import net.minecraft.core.Global;
 import net.minecraft.core.MinecraftAccessor;
+import net.minecraft.core.block.Blocks;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.entity.SkinVariantList;
+import net.minecraft.core.item.Items;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.SpawnerMobs;
 import net.minecraft.core.world.World;
@@ -21,6 +24,7 @@ import net.minecraft.core.world.save.SaveHandlerClientMP;
 import net.minecraft.core.world.save.mcregion.SaveFormat19134;
 import net.minecraft.core.world.type.WorldType;
 import net.minecraft.core.world.type.WorldTypes;
+import org.slf4j.Logger;
 
 import javax.swing.*;
 import javax.swing.border.TitledBorder;
@@ -39,7 +43,7 @@ import java.util.Map;
 import java.util.Set;
 
 public class BiomeFinder implements MinecraftAccessor {
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public static long seed = 0;
 	public static int renderRes = 1024;
 	public static int renderScale = 4;
@@ -55,11 +59,10 @@ public class BiomeFinder implements MinecraftAccessor {
 
 	private final Map<Biome, Integer> biomeCounts = new HashMap<>();
 	private File worldFolder;
-	private JFrame frame;
+	private final JFrame frame;
 	private final String title = "Biome Finder";
 
 	public static void main(String[] args) {
-		BiomeProviderOverworld.init();
 		File worldFolder = null;
 
 		Boolean highlight = null;
@@ -67,7 +70,7 @@ public class BiomeFinder implements MinecraftAccessor {
 		for(String arg : args) {
 			int i = arg.indexOf('=');
 			if(i == -1) {
-				System.out.println("Skipping argument '"+arg+"'");
+                LOGGER.warn("Skipping argument '{}'", arg);
 				continue;
 			}
 
@@ -103,13 +106,13 @@ public class BiomeFinder implements MinecraftAccessor {
                     highlight = Boolean.parseBoolean(value);
                     break;
                 default:
-                    System.out.println("Unknown argument '" + arg + "'.");
+                    LOGGER.warn("Unknown argument '{}'.", arg);
                     break;
             }
 		}
 
 		if(worldFolder == null) {
-			System.out.println("No world!");
+			LOGGER.info("No world specified");
 		}
 		if (highlight == null){
 			highlightLoaded = worldFolder != null;
@@ -145,6 +148,10 @@ public class BiomeFinder implements MinecraftAccessor {
 			Global.accessor = this;
 		}
 
+		Blocks.init();
+		Items.init();
+		BiomeProviderOverworld.init();
+
         try {
             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); //set Look and Feel to Windows
         } catch (ClassNotFoundException | InstantiationException | IllegalAccessException |
@@ -427,7 +434,7 @@ public class BiomeFinder implements MinecraftAccessor {
 					int result = worldSelector.showOpenDialog(frame);
 					if (result == JFileChooser.APPROVE_OPTION) {
 						File selectedFile = worldSelector.getSelectedFile();
-						System.out.println("Selected file: " + selectedFile.getAbsolutePath());
+                        LOGGER.info("Selected file: {}", selectedFile.getAbsolutePath());
 						this.worldFolder = selectedFile;
 						seedField.setEnabled(false);
 						closeWorldButton.setEnabled(true);
@@ -475,7 +482,7 @@ public class BiomeFinder implements MinecraftAccessor {
 	}
 
 	private BufferedImage createBiomePreview() {
-		System.out.printf("Seed: %d | World?: %s", seed, worldFolder != null);
+        LOGGER.info("Seed: {} | World?: {}", seed, worldFolder != null);
 		BiomeProviderOverworld.init();
 		biomeCounts.clear();
 		WorldType worldType = WorldTypes.OVERWORLD_EXTENDED;
@@ -496,12 +503,12 @@ public class BiomeFinder implements MinecraftAccessor {
 		BufferedImage biomeImage = new BufferedImage(renderRes, renderRes, BufferedImage.TYPE_INT_RGB);
 
 		int areaSize = renderRes * renderScale;
-		System.out.println("Render Area: " + areaSize + " x " + areaSize);
+        LOGGER.info("Render Area: {} x {}", areaSize, areaSize);
 
 		int offsetX = -areaSize / 2 + posX;
 		int offsetZ = -areaSize / 2 + posZ;
 
-		System.out.println("Offset: " + offsetX + ", " + offsetZ);
+        LOGGER.info("Offset: {}, {}", offsetX, offsetZ);
 
 		int lastChunkX = Integer.MIN_VALUE;
 		int lastChunkZ = Integer.MIN_VALUE;
@@ -524,7 +531,7 @@ public class BiomeFinder implements MinecraftAccessor {
 						}
                     } catch (Exception e){
 						chunk = null;
-						e.printStackTrace();
+						LOGGER.error("Failed to load chunk at X:{}, Z:{}", Math.floorDiv(x, Chunk.CHUNK_SIZE_X), Math.floorDiv(z, Chunk.CHUNK_SIZE_Z), e);
 					}
 				}
 				if (biome == null) {
@@ -550,7 +557,7 @@ public class BiomeFinder implements MinecraftAccessor {
 				lastProgress = System.currentTimeMillis();
 				float percent = i / (float)biomeImage.getHeight();
 				String progress = (int)(percent * 100) + "%";
-				System.out.println(progress);
+				LOGGER.info(progress);
 				frame.setTitle(title + " | loading " + progress);
 			}
 		}
@@ -604,7 +611,7 @@ public class BiomeFinder implements MinecraftAccessor {
 
 		g.setColor(bg);
 		g.fillRect(x, y, w, h);
-		g.setFont(new Font("Monospaced", 1, 13 * guiScale));
+		g.setFont(new Font("Monospaced", Font.BOLD, 13 * guiScale));
 
 		for(int i=0; i < biomeList.size(); i++) {
 			int y1 = y + i * lineHeight;
@@ -659,4 +666,5 @@ public class BiomeFinder implements MinecraftAccessor {
 	public String getMinecraftVersion() {
 		return null;
 	}
+
 }
diff --git a/src/main/java/net/betterthanadventure/utils/DataDumper.java b/src/main/java/net/betterthanadventure/utils/DataDumper.java
index 25cbca191..7e3590974 100644
--- a/src/main/java/net/betterthanadventure/utils/DataDumper.java
+++ b/src/main/java/net/betterthanadventure/utils/DataDumper.java
@@ -1,5 +1,6 @@
 package net.betterthanadventure.utils;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.core.Global;
 import net.minecraft.core.MinecraftAccessor;
@@ -23,6 +24,7 @@ import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.chunk.IChunkLoader;
 import net.minecraft.core.world.chunk.provider.IChunkProvider;
 import net.minecraft.core.world.weather.Weather;
+import org.slf4j.Logger;
 
 import java.io.BufferedWriter;
 import java.io.File;
@@ -31,6 +33,7 @@ import java.io.IOException;
 import java.util.List;
 
 public class DataDumper implements MinecraftAccessor {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private static File minecraftDir = null;
     private static I18n translator;
     public static boolean hideUnused = true;
@@ -38,7 +41,7 @@ public class DataDumper implements MinecraftAccessor {
         for(String arg : args) {
             int i = arg.indexOf('=');
             if(i == -1) {
-                System.out.println("Skipping argument '"+arg+"'");
+                LOGGER.error("Skipping argument '{}'", arg);
                 continue;
             }
 
@@ -48,7 +51,7 @@ public class DataDumper implements MinecraftAccessor {
             if(key.equals("hide-unused")) {
                 hideUnused = Boolean.parseBoolean(value);
             } else {
-                System.out.println("Skipping argument '" + arg + "'");
+                LOGGER.error("Skipping argument '{}'", arg);
             }
         }
 
@@ -63,8 +66,8 @@ public class DataDumper implements MinecraftAccessor {
         I18n.initialize("en_US");
         translator = I18n.getInstance();
 
-        System.out.println(Blocks.DIRT.id);
-        System.out.println(Items.STICK.id);
+        Blocks.init();
+        Items.init();
 
         File wikiDumpFile = new File(getMinecraftDir(), "infodump");
         wikiDumpFile.mkdirs();
@@ -227,4 +230,5 @@ public class DataDumper implements MinecraftAccessor {
     public String getMinecraftVersion() {
         return null;
     }
+
 }
diff --git a/src/main/java/net/betterthanadventure/utils/ResetBiomes.java b/src/main/java/net/betterthanadventure/utils/ResetBiomes.java
index 887f7050a..8be877107 100644
--- a/src/main/java/net/betterthanadventure/utils/ResetBiomes.java
+++ b/src/main/java/net/betterthanadventure/utils/ResetBiomes.java
@@ -7,6 +7,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import com.mojang.nbt.Tag;
@@ -15,16 +16,17 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.core.world.ProgressListener;
 import net.minecraft.core.world.save.mcregion.RegionFile;
 import net.minecraft.core.world.save.mcregion.RegionFileCache;
+import org.slf4j.Logger;
 
 public class ResetBiomes {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public static void main(String[] args) {
 		File worldFolder = null;
 		
 		for(String arg : args) {
 			int i = arg.indexOf('=');
 			if(i == -1) {
-				System.out.println("Skipping argument '"+arg+"'");
+                LOGGER.warn("Skipping argument '{}'", arg);
 				continue;
 			}
 			
@@ -39,20 +41,20 @@ public class ResetBiomes {
 		}
 		
 		if(worldFolder == null) {
-			System.out.println("No world!");
+			LOGGER.warn("No world!");
 			return;
 		}
-		
+
 		new ResetBiomes(worldFolder);
 	}
 	
 	public ResetBiomes(File worldFolder) {
-		System.out.println("Reset Biomes: " + worldFolder.getAbsolutePath());
+        LOGGER.info("Reset Biomes: {}", worldFolder.getAbsolutePath());
 		
 		ProgressListener progressUpdate = new ConsoleProgressUpdate();
 		List<ChunkPosition> chunks = new McRegionChunkCounter().count(worldFolder, progressUpdate);
-		
-		System.out.println("Chunk Count: " + chunks.size());
+
+        LOGGER.info("Chunk Count: {}", chunks.size());
 		
 		progressUpdate.progressStage("Converting Chunks");
 		progressUpdate.progressStagePercentage(0);
@@ -90,17 +92,21 @@ public class ResetBiomes {
 				throw new RuntimeException(e);
 			}finally {
 				try {
-					in.close();
-				}catch (Exception e) {}
+					if (in != null) {
+						in.close();
+					}
+				}catch (Exception ignored) {}
 				try {
-					out.close();
-				}catch (Exception e) {}
+					if (out != null) {
+						out.close();
+					}
+				}catch (Exception ignored) {}
 			}
 			
 			setLoadingProgress(progressUpdate, i, chunks.size());
 		}
-		
-		System.out.println("Done!");
+
+		LOGGER.info("Done!");
 	}
 	
 	static class McRegionChunkCounter {
@@ -110,12 +116,12 @@ public class ResetBiomes {
 		
 		public List<ChunkPosition> count(File saveFolder, ProgressListener progressUpdate) {
 			File[] dimensionFolders = new File(saveFolder, "dimensions").listFiles();
-			System.out.println(dimensionFolders.length + " Dimension Folders");
-			
 			if(dimensionFolders == null || dimensionFolders.length == 0) {
 				return null;
 			}
-			
+
+            LOGGER.info("{} Dimension Folders", dimensionFolders.length);
+
 			progressUpdate.progressStage("Counting Chunks");
 			progressUpdate.progressStagePercentage(0);
 			
@@ -123,16 +129,16 @@ public class ResetBiomes {
 			regionList = new ArrayList<>();
 			
 			for(int dim = 0; dim < dimensionFolders.length; dim++) {
-				System.out.println("Dimension: " + dimensionFolders[dim].getName());
+                LOGGER.info("Dimension: {}", dimensionFolders[dim].getName());
 				
 				File regionFolder = new File(dimensionFolders[dim], "region");
 				
 				File[] regionFiles = regionFolder.listFiles();
 				if(regionFiles == null) {
-					System.out.println("No Region Files!");
+					LOGGER.warn("No Region Files!");
 					continue;
 				}
-				System.out.println(regionFiles.length + " Region Files");
+                LOGGER.info("{} Region Files", regionFiles.length);
 				
 				for(int i=0; i < regionFiles.length; i++) {
 					RegionPosition region = RegionPosition.get(regionFiles[i]);
@@ -142,8 +148,8 @@ public class ResetBiomes {
 					}
 				}
 			}
-			
-			System.out.println("Region List: " + regionList.size());
+
+            LOGGER.info("Region List: {}", regionList.size());
 			
 			for(int i=0; i < regionList.size(); i++) {
 				RegionPosition region = regionList.get(i);
@@ -262,7 +268,7 @@ public class ResetBiomes {
 			}
 			long now = System.currentTimeMillis();
 			if(now > lastPrint + 250) {
-				System.out.println(string + ": " + i + "%");
+                LOGGER.info("{}: {}%", string, i);
 				lastPrint = now;
 				lastValue = i;
 			}
diff --git a/src/main/java/net/minecraft/client/Minecraft.java b/src/main/java/net/minecraft/client/Minecraft.java
index ed0ed089b..d71dc23ee 100644
--- a/src/main/java/net/minecraft/client/Minecraft.java
+++ b/src/main/java/net/minecraft/client/Minecraft.java
@@ -1,6 +1,5 @@
 package net.minecraft.client;
 
-import static net.minecraft.core.Global.*;
 import static org.lwjgl.opengl.GL11.*;
 
 import java.awt.Cursor;
@@ -9,53 +8,63 @@ import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.File;
 import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.URL;
 import java.util.ArrayList;
-import java.util.Comparator;
 import java.util.List;
+import java.util.Comparator;
 import java.util.Random;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.*;
+
+import com.mojang.logging.LogUtils;
+import com.mojang.nbt.CompoundTag;
+import net.minecraft.client.entity.ClientSkinVariantList;
+import net.minecraft.client.gui.toasts.HudToastsElement;
+import net.minecraft.core.achievement.Achievements;
+import net.minecraft.core.util.helper.LoggedPrintStream;
+import net.minecraft.core.util.helper.UUIDHelper;
+import net.minecraft.core.world.SpawnerMobs;
+import net.minecraft.core.world.type.WorldType;
+import net.minecraft.core.world.type.WorldTypeGroups;
 
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 
+import net.minecraft.client.gui.subtitles.SubtitleTracker;
 import net.minecraft.client.sound.SoundRepository;
 import net.minecraft.client.world.chunk.provider.ChunkProviderDynamic;
 import org.jetbrains.annotations.Nullable;
+
 import org.lwjgl.LWJGLException;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.GL11;
 
-import com.mojang.nbt.CompoundTag;
-
 import net.minecraft.client.discord.RichPresenceHandlerThread;
-import net.minecraft.client.entity.ClientSkinVariantList;
 import net.minecraft.client.entity.player.LocalPlayer;
 import net.minecraft.client.entity.player.MultiplayerLocalPlayer;
-import net.minecraft.client.gui.GuiBadJavaArch;
-import net.minecraft.client.gui.GuiChat;
-import net.minecraft.client.gui.GuiConflictWarning;
-import net.minecraft.client.gui.GuiConnecting;
-import net.minecraft.client.gui.GuiCreateWorld;
-import net.minecraft.client.gui.GuiException;
-import net.minecraft.client.gui.GuiGameOver;
-import net.minecraft.client.gui.GuiIngame;
-import net.minecraft.client.gui.GuiIngameMenu;
-import net.minecraft.client.gui.GuiInventory;
-import net.minecraft.client.gui.GuiInventoryCreative;
-import net.minecraft.client.gui.GuiMainMenu;
-import net.minecraft.client.gui.GuiMissingMinecraft;
-import net.minecraft.client.gui.GuiOutOfMemory;
-import net.minecraft.client.gui.GuiPhotoMode;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.GuiSelectWorld;
-import net.minecraft.client.gui.GuiSleepMP;
-import net.minecraft.client.gui.GuiSleepSP;
+import net.minecraft.client.gui.BadJavaArchScreen;
+import net.minecraft.client.gui.ChatScreen;
+import net.minecraft.client.gui.ConflictWarningScreen;
+import net.minecraft.client.gui.ConnectingScreen;
+import net.minecraft.client.gui.CreateWorldScreen;
+import net.minecraft.client.gui.ExceptionPopupElement;
+import net.minecraft.client.gui.GameOverScreen;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.PauseScreen;
+import net.minecraft.client.gui.container.InventoryScreen;
+import net.minecraft.client.gui.container.InventoryScreenCreative;
+import net.minecraft.client.gui.MainMenuScreen;
+import net.minecraft.client.gui.MissingMinecraftScreen;
+import net.minecraft.client.gui.OutOfMemoryScreen;
+import net.minecraft.client.gui.PhotoModeScreen;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.SelectWorldScreen;
+import net.minecraft.client.gui.SleepScreenMP;
+import net.minecraft.client.gui.SleepScreenSP;
 import net.minecraft.client.gui.MainMenuBackground;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
-import net.minecraft.client.gui.popup.GuiPopup;
-import net.minecraft.client.gui.toasts.GuiHudToasts;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
+import net.minecraft.client.gui.popup.PopupScreen;
 import net.minecraft.client.input.InputDevice;
 import net.minecraft.client.input.InputHandler;
 import net.minecraft.client.input.InputType;
@@ -69,17 +78,17 @@ import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.option.KeyBinding;
 import net.minecraft.client.option.enums.LightmapStyle;
 import net.minecraft.client.player.controller.PlayerController;
-import net.minecraft.client.render.EffectRenderer;
+import net.minecraft.client.render.ParticleEngine;
 import net.minecraft.client.render.EntityRenderDispatcher;
 import net.minecraft.client.render.FallbackRenderer;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.ItemRenderer;
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.LoadingScreenRenderer;
 import net.minecraft.client.render.OpenGLHelper;
 import net.minecraft.client.render.PostProcessingManager;
 import net.minecraft.client.render.RenderBlocks;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.RenderGlobal;
 import net.minecraft.client.render.Renderer;
 import net.minecraft.client.render.WorldRenderer;
@@ -110,7 +119,6 @@ import net.minecraft.core.MinecraftError;
 import net.minecraft.core.MinecraftException;
 import net.minecraft.core.Timer;
 import net.minecraft.core.UnexpectedThrowable;
-import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.achievement.stat.StatList;
 import net.minecraft.core.achievement.stat.StatsCounter;
 import net.minecraft.core.block.BaseLeavesBlock;
@@ -131,7 +139,6 @@ import net.minecraft.core.player.Session;
 import net.minecraft.core.player.gamemode.Gamemode;
 import net.minecraft.core.util.helper.Axis;
 import net.minecraft.core.util.helper.Direction;
-import net.minecraft.core.util.helper.LogPrintStream;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.ScreenShot;
 import net.minecraft.core.util.helper.Side;
@@ -141,7 +148,6 @@ import net.minecraft.core.util.phys.HitResult;
 import net.minecraft.core.util.phys.Vec3;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.PortalHandler;
-import net.minecraft.core.world.SpawnerMobs;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.provider.BiomeProviderOverworld;
 import net.minecraft.core.world.chunk.Chunk;
@@ -156,8 +162,27 @@ import net.minecraft.core.world.save.LevelStorage;
 import net.minecraft.core.world.save.SaveConverters;
 import net.minecraft.core.world.save.SaveFormats;
 import net.minecraft.core.world.save.mcregion.SaveFormat19134;
-import net.minecraft.core.world.type.WorldType;
-import net.minecraft.core.world.type.WorldTypeGroups;
+import org.slf4j.Logger;
+
+
+import static net.minecraft.core.Global.CURRENT_SAVE_VERSION;
+import static org.lwjgl.opengl.GL11.GL_ALPHA_TEST;
+import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
+import static org.lwjgl.opengl.GL11.glAlphaFunc;
+import static org.lwjgl.opengl.GL11.glClear;
+import static org.lwjgl.opengl.GL11.glClearColor;
+import static org.lwjgl.opengl.GL11.glClearDepth;
+import static org.lwjgl.opengl.GL11.glColor4f;
+import static org.lwjgl.opengl.GL11.glCullFace;
+import static org.lwjgl.opengl.GL11.glDepthFunc;
+import static org.lwjgl.opengl.GL11.glDisable;
+import static org.lwjgl.opengl.GL11.glEnable;
+import static org.lwjgl.opengl.GL11.glLoadIdentity;
+import static org.lwjgl.opengl.GL11.glMatrixMode;
+import static org.lwjgl.opengl.GL11.glOrtho;
+import static org.lwjgl.opengl.GL11.glShadeModel;
+import static org.lwjgl.opengl.GL11.glTranslatef;
+import static org.lwjgl.opengl.GL11.glViewport;
 
 // Referenced classes of package net.minecraft.client:
 //            MinecraftApplet
@@ -165,6 +190,7 @@ import net.minecraft.core.world.type.WorldTypeGroups;
 public class Minecraft
     implements Runnable, MinecraftAccessor
 {
+    public static Logger LOGGER = LogUtils.getLogger();
     public static final String VERSION = Global.VERSION;
     public static final boolean isMultiplayerDisabled = false;
     public static boolean doPartialTick = true;
@@ -177,7 +203,7 @@ public class Minecraft
     public RenderGlobal renderGlobal;
     public LocalPlayer thePlayer;
     public ICamera activeCamera;
-    public EffectRenderer effectRenderer;
+    public ParticleEngine particleEngine;
     public Session session;
 
     public String worldPresetName = null;
@@ -188,23 +214,24 @@ public class Minecraft
     public String minecraftUri;
     public boolean hideQuitButton;
     public volatile boolean isGamePaused;
-    public RenderEngine renderEngine;
-    public FontRenderer fontRenderer;
+    public TextureManager textureManager;
+    public Font font;
     /**
      * Current gui the player is looking at
      * is null when in a world during normal play
      */
-    public @Nullable GuiScreen currentScreen;
+    public @Nullable Screen currentScreen;
     public LoadingScreenRenderer loadingScreen;
     public WorldRenderer worldRenderer;
     public ThreadDownloadResources downloadResourcesThread;
     private int ticksRan;
-    public GuiHudToasts guiAchievementToast;
-    public GuiIngame ingameGUI;
+    public HudToastsElement guiToasts;
+    public IngameHud ingameHud;
     public boolean skipRenderWorld;
     public HitResult objectMouseOver;
     public GameSettings gameSettings;
     public SoundEngine sndManager;
+    public final SubtitleTracker subtitleTracker = new SubtitleTracker();
     public TexturePackList texturePackList;
     private File mcDataDir;
     private ISaveFormat saveFormat;
@@ -253,7 +280,7 @@ public class Minecraft
     	this.gameWindow = gameWindow;
     	
         Global.accessor = this;
-        LogPrintStream.setup();
+        LoggedPrintStream.wrapStreams();
         hasCrashed = false;
         timer = new Timer(Global.TICKS_PER_SECOND);
         session = null;
@@ -262,7 +289,7 @@ public class Minecraft
         currentScreen = null;
         loadingScreen = new LoadingScreenRenderer(this);
         ticksRan = 0;
-        guiAchievementToast = new GuiHudToasts(this);
+        guiToasts = new HudToastsElement(this);
         skipRenderWorld = false;
         objectMouseOver = null;
         sndManager = new SoundEngine();
@@ -297,8 +324,7 @@ public class Minecraft
 		if(!gameStarted) {
 			running = false;
 
-			System.err.println("An exception has occured while trying to start the game!");
-			throwable.exception.printStackTrace(System.err);
+			LOGGER.error("An exception has occurred while trying to start the game!", throwable.exception);
 			
 			gameWindow.displayCrashReport(throwable, 1);
 			hasCrashed = true;
@@ -310,8 +336,7 @@ public class Minecraft
 		if(disableCrashHandler) {
 			running = false;
 
-			System.err.println("An exception has occured, and the crash handler is disabled! The game will now exit!");
-			throwable.exception.printStackTrace(System.err);
+            LOGGER.error("An exception has occurred while trying to start the game!", throwable.exception);
 			
 			gameWindow.displayCrashReport(throwable, 1);
 			hasCrashed = true;
@@ -321,9 +346,8 @@ public class Minecraft
 
 		if(hasCrashed) {
 			running = false;
-			
-			System.err.println("An exception has occured while trying to render the crash handler! The game will now exit!");
-			throwable.exception.printStackTrace(System.err);
+
+            LOGGER.error("An exception has occurred while trying to start the game!", throwable.exception);
 			
 			gameWindow.displayCrashReport(throwable, 2);
 			shutdownMinecraftApplet();
@@ -331,26 +355,26 @@ public class Minecraft
 		}
 		
 		Debug.reset();
-		throwable.exception.printStackTrace(System.err);
+        LOGGER.error("Minecraft has crashed!", throwable.exception);
 		hasCrashed = true;
 		lastCrash = throwable;
 		
 		try {
             if (!gameStarted) {
-				GuiPopup error = GuiException.createStartupError(throwable.exception, this);
-				displayGuiScreen(error);
+				PopupScreen error = ExceptionPopupElement.createStartupError(throwable.exception, this);
+				displayScreen(error);
 				return;
 			}
 			if(throwable.exception instanceof RuntimeException) {
 				changeWorld(null);
-				GuiMainMenu guiMainMenu = new GuiMainMenu();
-				displayGuiScreen(guiMainMenu);
-				GuiPopup error = GuiException.create(guiMainMenu, throwable.exception, this);
-				displayGuiScreen(error);
+				MainMenuScreen mainMenuScreen = new MainMenuScreen();
+				displayScreen(mainMenuScreen);
+				PopupScreen error = ExceptionPopupElement.create(mainMenuScreen, throwable.exception, this);
+				displayScreen(error);
 			}else {
 				changeWorld(null);
-				GuiPopup error = GuiException.createFatal(throwable.exception, this);
-				displayGuiScreen(error);
+				PopupScreen error = ExceptionPopupElement.createFatal(throwable.exception, this);
+				displayScreen(error);
 			}
 		}catch (Throwable e) {
 			onMinecraftCrash(new UnexpectedThrowable("Trying to display crash handler", e));
@@ -365,7 +389,7 @@ public class Minecraft
     
     public void startGame() throws LWJGLException
     {
-        System.out.println("LWJGL version = " + org.lwjgl.Sys.getVersion());
+        LOGGER.info("LWJGL version = {}", org.lwjgl.Sys.getVersion());
         if (Integer.parseInt(org.lwjgl.Sys.getVersion().substring(0, 1)) < 3) {
             JOptionPane.showMessageDialog(null,
                 new Object[] {
@@ -381,7 +405,7 @@ public class Minecraft
                                     try {
                                         Desktop.getDesktop().browse(new URL("https://www.betterthanadventure.net/installation-guide/").toURI());
                                     } catch (Exception ex) {
-                                        ex.printStackTrace();
+                                        LOGGER.error("Exception occurred when attempting to open URL 'https://www.betterthanadventure.net/installation-guide/'!", ex);
                                     }
                                 }
                             });
@@ -405,8 +429,8 @@ public class Minecraft
 		GameResolution.defaultWidth = gameSettings.windowWidth.value;
 		GameResolution.defaultHeight = gameSettings.windowHeight.value;
 
-		System.out.println("Resolution: " + GameResolution.defaultWidth + " x " + GameResolution.defaultHeight);
-		System.out.println("Java Version: " + System.getProperty("java.version"));
+        LOGGER.info("Resolution: {} x {}", GameResolution.defaultWidth, GameResolution.defaultHeight);
+        LOGGER.info("Java Version: {}", System.getProperty("java.version"));
 
 		printWrongJavaVersionInfo();
 		
@@ -446,7 +470,7 @@ public class Minecraft
         }
 
         texturePackList = new TexturePackList(this, mcDataDir);
-        renderEngine = new RenderEngine(this, texturePackList, gameSettings);
+        textureManager = new TextureManager(this, texturePackList, gameSettings);
 
         SoundRepository.initialize(this);
 
@@ -467,20 +491,19 @@ public class Minecraft
         EntityRenderDispatcher.instance.itemRenderer = new ItemRenderer(this);
         loadScreen();	// Update loading screen so it doesn't say no response
 
-        System.out.println("Initializing input");
+        LOGGER.info("Initializing input");
         try {
             InputHandler.init(this);
 
             this.controllerInput = InputHandler.getController(gameSettings.selectedController.value);
         }catch (Exception e) {
-            System.err.println("Input init error!");
-            e.printStackTrace();
+            LOGGER.error("Input init error!", e);
         }
         mouseInput.setRawInput(gameSettings.rawMouseInput.value);
-        System.out.println("Input done!");
-        
-        System.out.println("Setting up OpenGL values...");
-        
+        LOGGER.info("Input done!");
+
+        LOGGER.info("Setting up OpenGL values...");
+
         OpenGLHelper.checkError("pre startup");
         glEnable(GL11.GL_TEXTURE_2D);
         glShadeModel(GL11.GL_SMOOTH);
@@ -500,26 +523,28 @@ public class Minecraft
         
         Colorizers.init(this);
         
-        renderEngine.refreshTextures(new ArrayList<>());
+        textureManager.refreshTextures(new ArrayList<>());
 
         loadScreen();	// Update loading screen so it doesn't say no response
-        
-        System.out.println("Initializing Renderer...");
+
+        LOGGER.info("Initializing Renderer...");
         
         TextureRegistry.blockAtlas.bind();
-        renderGlobal = new RenderGlobal(this, renderEngine);
+        renderGlobal = new RenderGlobal(this, textureManager);
         glViewport(0, 0, resolution.width, resolution.height);
-        effectRenderer = new EffectRenderer(theWorld, renderEngine);
+        particleEngine = new ParticleEngine(theWorld);
         try
         {
-            System.out.println("Starting Resource Download Thread...");
+            LOGGER.info("Starting Resource Download Thread...");
             downloadResourcesThread = new ThreadDownloadResources(mcDataDir, this);
             downloadResourcesThread.start();
         }
-        catch(Exception exception1) { }
+        catch(Exception e) {
+            LOGGER.error("Failed to start Resource Download Thread!", e);
+        }
         
         OpenGLHelper.checkError("post startup");
-        ingameGUI = new GuiIngame(this);
+        ingameHud = new IngameHud(this);
 
         new Registries();
 
@@ -537,8 +562,8 @@ public class Minecraft
         int groups = Registries.RECIPES.getAllGroups().size();
         int namespaces = Registries.RECIPES.size();
         int itemGroups = Registries.ITEM_GROUPS.size();
-        System.out.printf("%d item groups.%n",itemGroups);
-        System.out.printf("%d recipes in %d groups in %d namespaces.%n",recipes,groups,namespaces);
+        LOGGER.info(String.format("%d item groups.", itemGroups));
+        LOGGER.info(String.format("%d recipes in %d groups in %d namespaces.",recipes,groups,namespaces));
 
         StatList.init();
         statsCounter = new StatsCounter(session, mcDataDir);
@@ -577,28 +602,28 @@ public class Minecraft
         }
 
         if (!hasBeta173) {
-            displayGuiScreen(new GuiMissingMinecraft());
+            displayScreen(new MissingMinecraftScreen());
         }
         else if (System.getProperty("sun.arch.data.model").equals("32"))
         {
-            displayGuiScreen(new GuiBadJavaArch());
+            displayScreen(new BadJavaArchScreen());
         }
         else if(serverName != null)
         {
-            displayGuiScreen(new GuiConnecting(this, serverName, serverPort));
+            displayScreen(new ConnectingScreen(this, serverName, serverPort));
         }
         else if (worldPresetName != null && worldPresetSeed != null)
         {
-            GuiSelectWorld selectWorldScreen = new GuiSelectWorld(null);
-            displayGuiScreen(selectWorldScreen);
+            SelectWorldScreen selectWorldScreen = new SelectWorldScreen(null);
+            displayScreen(selectWorldScreen);
             selectWorldScreen.deletePresetWorld(worldPresetName);
-            GuiCreateWorld screen = new GuiCreateWorld(null);
-            displayGuiScreen(screen);
+            CreateWorldScreen screen = new CreateWorldScreen(null);
+            displayScreen(screen);
             screen.runPreset(worldPresetName, worldPresetSeed, worldPresetX, worldPresetY, worldPresetZ);
         }
         else
         {
-            displayGuiScreen(new GuiMainMenu());
+            displayScreen(new MainMenuScreen());
         }
         gameWindow.updateWindowState();
     }
@@ -609,20 +634,23 @@ public class Minecraft
     		return;
     	}
     	try {
-    		int major = Integer.parseInt(javaVersion.split(".")[0]);
+    		int major = Integer.parseInt(javaVersion.split("\\.")[0]);
     		if(major > 8) {
-    			System.out.println("Detected a probably incompatible Java version. If the game crashes with a message similar to \n"
+                LOGGER.warn("Detected a probably incompatible Java version. If the game crashes with a message similar to \n"
     					+ "\"Inconsistency detected by ld.so: dl-lookup.c: 111: check_match: Assertion `version->filename == NULL || ! _dl_name_match_p (version->filename, map)' failed!\", \n"
     					+ "use Java 8!");
     		}
     	}catch (Exception e) {
-    		e.printStackTrace();
+            LOGGER.error("Failed to retrieve Java version!", e);
+            LOGGER.warn("If the game crashes with a message similar to \n"
+                + "\"Inconsistency detected by ld.so: dl-lookup.c: 111: check_match: Assertion `version->filename == NULL || ! _dl_name_match_p (version->filename, map)' failed!\", \n"
+                + "use Java 8!");
 		}
     }
 
     private void loadScreen() throws LWJGLException
     {
-        System.out.println("Drawing Loading Screen...");
+        LOGGER.info("Drawing Loading Screen...");
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         glMatrixMode(GL11.GL_PROJECTION);
         glLoadIdentity();
@@ -638,9 +666,9 @@ public class Minecraft
         glDisable(GL11.GL_FOG);
         
         if(mojrand == 0)
-            renderEngine.loadTexture("/assets/minecraft/textures/gui/title/majonk.png").bind();
+            textureManager.loadTexture("/assets/minecraft/textures/gui/title/majonk.png").bind();
         else
-            renderEngine.loadTexture("/assets/minecraft/textures/gui/title/mojang.png").bind();
+            textureManager.loadTexture("/assets/minecraft/textures/gui/title/mojang.png").bind();
         
         tessellator.startDrawingQuads();
         tessellator.setColorOpaque_I(0xffffff);
@@ -671,10 +699,10 @@ public class Minecraft
         Tessellator tessellator = Tessellator.instance;
         tessellator.startDrawingQuads();
         tessellator.setColorOpaque_I(0xffffff);
-        tessellator.addVertexWithUV(minX + 0, minY + height, 0.0D, (float)(minU + 0) * scaleX, (float)(minV + height) * scaleY);
-        tessellator.addVertexWithUV(minX + width, minY + height, 0.0D, (float)(minU + width) * scaleX, (float)(minV + height) * scaleY);
-        tessellator.addVertexWithUV(minX + width, minY + 0, 0.0D, (float)(minU + width) * scaleX, (float)(minV + 0) * scaleY);
-        tessellator.addVertexWithUV(minX + 0, minY + 0, 0.0D, (float)(minU + 0) * scaleX, (float)(minV + 0) * scaleY);
+        tessellator.addVertexWithUV(minX + 0,       minY + height,  0.0D, (float)(minU + 0) * scaleX,       (float)(minV + height) * scaleY);
+        tessellator.addVertexWithUV(minX + width,   minY + height,  0.0D, (float)(minU + width) * scaleX,   (float)(minV + height) * scaleY);
+        tessellator.addVertexWithUV(minX + width,   minY + 0,       0.0D, (float)(minU + width) * scaleX,   (float)(minV + 0) * scaleY);
+        tessellator.addVertexWithUV(minX + 0,       minY + 0,       0.0D, (float)(minU + 0) * scaleX,       (float)(minV + 0) * scaleY);
         tessellator.draw();
     }
 
@@ -768,9 +796,9 @@ public class Minecraft
         return saveFormat;
     }
 
-    public void displayGuiScreen(GuiScreen guiscreen)
+    public void displayScreen(Screen screen)
     {
-        if(currentScreen == null && guiscreen != null)
+        if(currentScreen == null && screen != null)
         {
             if(controllerInput != null)
             {
@@ -780,32 +808,32 @@ public class Minecraft
         }
         if(currentScreen != null)
         {
-            currentScreen.onClosed();
+            currentScreen.removed();
         }
-        if(guiscreen instanceof GuiMainMenu)
+        if(screen instanceof MainMenuScreen)
         {
             statsCounter.fetchStats();
         }
         if(statsCounter != null){
             statsCounter.saveStats();
         }
-        if(guiscreen == null && theWorld == null)
+        if(screen == null && theWorld == null)
         {
-            guiscreen = new GuiMainMenu();
+            screen = new MainMenuScreen();
         }
-        else if(guiscreen == null && thePlayer.getHealth() <= 0)
+        else if(screen == null && thePlayer.getHealth() <= 0)
         {
-            guiscreen = new GuiGameOver();
+            screen = new GameOverScreen();
         }
-        if(guiscreen instanceof GuiMainMenu)
+        if(screen instanceof MainMenuScreen)
         {
-            ingameGUI.clearChatMessages();
+            ingameHud.clearChatMessages();
         }
-        currentScreen = guiscreen;
-        if(guiscreen != null)
+        currentScreen = screen;
+        if(screen != null)
         {
             setIngameNotInFocus();
-            guiscreen.setWorldAndResolution(this, resolution.scaledWidth, resolution.scaledHeight);
+            screen.init(this, resolution.scaledWidth, resolution.scaledHeight);
             skipRenderWorld = false;
         } else
         {
@@ -821,13 +849,13 @@ public class Minecraft
 					gameSettings.saveOptions();
 				}
 			}catch (Exception e) {
-				e.printStackTrace();
+                LOGGER.error("Exception occurred while saving settings! Some settings may be lost!", e);
 			}
 			if(statsCounter != null) {
                 statsCounter.fetchStats();
 				statsCounter.saveStats();
 			}
-			System.out.println("Stopping!");
+            LOGGER.info("Stopping!");
 			try {
 				changeWorld(null);
 			}catch (Throwable ignored) {
@@ -882,7 +910,7 @@ public class Minecraft
                     Vec3.initializePool();
                     
                     if(gameWindow.shouldClose()) shutdown();
-                    if(isGamePaused && theWorld != null && !(currentScreen instanceof GuiModelViewer))
+                    if(isGamePaused && theWorld != null && !(currentScreen instanceof ModelViewerScreen))
                     {
                         float temp = timer.partialTicks;
                         timer.advanceTime();
@@ -892,7 +920,6 @@ public class Minecraft
                         timer.advanceTime();
                     }
                     if (!doPartialTick) timer.partialTicks = 1f;
-                    long nanoTime = System.nanoTime();
 
                     mouseInput.update();
                     if(controllerInput != null && currentScreen != null)
@@ -914,9 +941,10 @@ public class Minecraft
                         catch(MinecraftException e)
                         {
                             theWorld = null;
+                            LOGGER.error("MinecraftException occurred while attempting to run tick, existing world!", e);
                         }
                         changeWorld(null);
-                        displayGuiScreen(new GuiConflictWarning());
+                        displayScreen(new ConflictWarningScreen());
                     }
                     
                     Debug.change("update"); // 1
@@ -972,7 +1000,7 @@ public class Minecraft
                         }
                     }
                     sndManager.setMuted(gameSettings.muteOnLostFocus.value && !gameWindow.isFocused());
-                    guiAchievementToast.render(timer.partialTicks);
+                    guiToasts.render(timer.partialTicks);
 
                     Debug.change("post");  // 3
                     renderer.endRenderGame(timer.partialTicks);
@@ -987,7 +1015,7 @@ public class Minecraft
                     }
                     OpenGLHelper.checkError("post render");
                     fpsCounter++;
-                    isGamePaused = !isMultiplayerWorld() && currentScreen != null && currentScreen.pausesGame();
+                    isGamePaused = !isMultiplayerWorld() && currentScreen != null && currentScreen.isPauseScreen();
                     while(System.currentTimeMillis() >= currentTime + 1000L)
                     {
                         debug = fpsCounter + " fps, " + ChunkRenderer.updates + " chunk updates";
@@ -1008,7 +1036,7 @@ public class Minecraft
 					Debug.pop();	// 2
 					Debug.pop();	// 1
 					if(gameSettings.showFrameTimes.value) {
-						DebugRender.render(fontRenderer);
+						DebugRender.render(font);
 					}
 					
                     screenshotListener();
@@ -1017,12 +1045,12 @@ public class Minecraft
                 {
                     theWorld = null;
                     changeWorld(null);
-                    displayGuiScreen(new GuiConflictWarning());
+                    displayScreen(new ConflictWarningScreen());
                 }
                 catch(OutOfMemoryError outofmemoryerror)
                 {
                     freeUpMemory();
-                    displayGuiScreen(new GuiOutOfMemory());
+                    displayScreen(new OutOfMemoryScreen());
                     System.gc();
                 }
                 catch(Throwable throwable)
@@ -1073,13 +1101,13 @@ public class Minecraft
 					if(Shaders.enableShaders) {
 						try {
 							screenshotHelper.takePanoramaScreenshot();
-							ingameGUI.addChatMessage("Saved panorama screenshot!");
+							ingameHud.addChatMessage("Saved panorama screenshot!");
 						}catch (Exception e) {
-							e.printStackTrace();
+                            LOGGER.error("Exception occurred while taking panoramic screenshot!", e);
 						}
 					}
 				}else {
-					ingameGUI.addChatMessage(ScreenShot.saveScreenshot(minecraftDir, resolution.width, resolution.height));	
+					ingameHud.addChatMessage(ScreenShot.saveScreenshot(minecraftDir, resolution.width, resolution.height));
 				}
 				Debug.pop();
 			}
@@ -1103,7 +1131,7 @@ public class Minecraft
         {
             inGameHasFocus = true;
             mouseInput.grabCursor();
-            displayGuiScreen(null);
+            displayScreen(null);
             mouseTicksRan = ticksRan + 10000;
             if(thePlayer != null) {
             	thePlayer.input.onGameFocused();
@@ -1130,7 +1158,7 @@ public class Minecraft
     {
         if(currentScreen == null)
         {
-            displayGuiScreen(new GuiIngameMenu());
+            displayScreen(new PauseScreen());
         }
     }
 
@@ -1288,7 +1316,7 @@ public class Minecraft
     {
         resolution.update();
         if(currentScreen != null) {
-            currentScreen.setWorldAndResolution(this, resolution.scaledWidth, resolution.scaledHeight);
+            currentScreen.init(this, resolution.scaledWidth, resolution.scaledHeight);
         }
     }
 
@@ -1319,7 +1347,7 @@ public class Minecraft
             }
             catch(Exception exception)
             {
-                exception.printStackTrace();
+                LOGGER.error("Error occurred while checking if paid client", exception);
             }
         }).start();
     }
@@ -1331,8 +1359,9 @@ public class Minecraft
             startCheckPaidThread();
         }
         Debug.push("gui");
+        subtitleTracker.tick();
         statsCounter.tick();
-        ingameGUI.updateTick();
+        ingameHud.updateTick();
         Debug.change("misc");
         worldRenderer.getMouseOver(1.0F);
         if(thePlayer != null)
@@ -1352,30 +1381,30 @@ public class Minecraft
         }
         Debug.change("textureTick");
         TextureRegistry.blockAtlas.bind();
-        renderEngine.updateDynamicTextures(isGamePaused);
+        textureManager.updateDynamicTextures(isGamePaused);
         Debug.change("misc");
         if(currentScreen == null && thePlayer != null)
         {
             if(thePlayer.getHealth() <= 0)
             {
-                displayGuiScreen(null);
+                displayScreen(null);
             }
             else if(thePlayer.isPlayerSleeping() && theWorld != null)
             {
                 if(theWorld.isClientSide)
                 {
-                    displayGuiScreen(new GuiSleepMP());
+                    displayScreen(new SleepScreenMP());
                 }
                 else
                 {
-                    displayGuiScreen(new GuiSleepSP());
+                    displayScreen(new SleepScreenSP());
                 }
                 
             }
         }
-        else if(currentScreen != null && (currentScreen instanceof GuiSleepMP) && !thePlayer.isPlayerSleeping())
+        else if(currentScreen != null && (currentScreen instanceof SleepScreenMP) && !thePlayer.isPlayerSleeping())
         {
-            displayGuiScreen(null);
+            displayScreen(null);
         }
         Debug.change("input");
         if(currentScreen != null)
@@ -1393,13 +1422,13 @@ public class Minecraft
 
         if (currentScreen != null)
         {
-            currentScreen.handleInput();
+            currentScreen.updateEvents();
             if (currentScreen != null)
             {
                 currentScreen.tick();
             }
         }
-        if (currentScreen == null || currentScreen.allowIngameInput)
+        if (currentScreen == null || currentScreen.passEvents)
         {
             while (Mouse.next())
             {
@@ -1421,7 +1450,7 @@ public class Minecraft
                         	gameSettings.flightSpeed.value = newSpeed;
                         	
                         	thePlayer.setFlySpeed(newSpeed);
-                        	ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.flightSpeed);
+                        	ingameHud.heldItemTooltipElement.setOptionNameAndValueString(gameSettings.flightSpeed);
                         }
                         else if (!gameSettings.keyZoom.isPressed())
                         {
@@ -1494,13 +1523,13 @@ public class Minecraft
                         if (gameSettings.keyToggleDebug.isPressed())
                         {
                             if(Keyboard.getEventKey() == Keyboard.KEY_Q) {
-                                ingameGUI.addChatMessage(TextFormatting.YELLOW + "Keyboard shortcuts: ");
+                                ingameHud.addChatMessage(TextFormatting.YELLOW + "Keyboard shortcuts: ");
                                 gameSettings.debugsKeys.sort(Comparator.comparing(KeyBinding::getKeyName));
                                 for (KeyBinding binding: gameSettings.debugsKeys){
-                                    ingameGUI.addChatMessage(String.format("%s + %s: %s", gameSettings.keyToggleDebug.getKeyName(), binding.getKeyName(), I18n.getInstance().translateKey(binding.getId())));
+                                    ingameHud.addChatMessage(String.format("%s + %s: %s", gameSettings.keyToggleDebug.getKeyName(), binding.getKeyName(), I18n.getInstance().translateKey(binding.getId())));
                                 }
-                                ingameGUI.addChatMessage(String.format("%s: %s", gameSettings.keyToggleTextureAtlas.getKeyName(), I18n.getInstance().translateKey(gameSettings.keyToggleTextureAtlas.getId())));
-                                ingameGUI.addChatMessage(String.format("%s: %s", gameSettings.keyReleaseCursor.getKeyName(), I18n.getInstance().translateKey(gameSettings.keyReleaseCursor.getId())));
+                                ingameHud.addChatMessage(String.format("%s: %s", gameSettings.keyToggleTextureAtlas.getKeyName(), I18n.getInstance().translateKey(gameSettings.keyToggleTextureAtlas.getId())));
+                                ingameHud.addChatMessage(String.format("%s: %s", gameSettings.keyReleaseCursor.getKeyName(), I18n.getInstance().translateKey(gameSettings.keyReleaseCursor.getId())));
                             }
                             if (gameSettings.keyReload.isPressEvent())
                             {
@@ -1549,43 +1578,43 @@ public class Minecraft
                                         }
                                     }
                                 }
-                                ingameGUI.guiHeldItemTooltip.setString("Fullbright: " + (fullbright ? "On" : "Off"));
+                                ingameHud.heldItemTooltipElement.setString("Fullbright: " + (fullbright ? "On" : "Off"));
                             }
                             else if (gameSettings.keyLightmaps.isPressEvent())
                             {
                             	if(gameSettings.lightmapStyle.value == LightmapStyle.DISABLED) {
                             		gameSettings.lightmapStyle.value = LightmapStyle.GRAY;
-                            		ingameGUI.guiHeldItemTooltip.setString("Lightmap: On");
+                            		ingameHud.heldItemTooltipElement.setString("Lightmap: On");
                             		renderGlobal.loadRenderers();
                             	}else {
                             		gameSettings.lightmapStyle.value = LightmapStyle.DISABLED;
-                            		ingameGUI.guiHeldItemTooltip.setString("Lightmap: Off");
+                            		ingameHud.heldItemTooltipElement.setString("Lightmap: Off");
                             		renderGlobal.loadRenderers();
                             	}
                             }
                             else if (gameSettings.keyCollisionBoxes.isPressEvent())
                             {
                             	gameSettings.showCollisionBoxes.toggle();
-                                ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.showCollisionBoxes);
+                                ingameHud.heldItemTooltipElement.setOptionNameAndValueString(gameSettings.showCollisionBoxes);
                             }
                             else if (gameSettings.keyChunkBorders.isPressEvent())
                             {
                             	gameSettings.showChunkBorders.toggle();
-                                ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.showChunkBorders);
+                                ingameHud.heldItemTooltipElement.setOptionNameAndValueString(gameSettings.showChunkBorders);
                             }
                             else if (gameSettings.keyClearChat.isPressEvent())
                             {
-                                ingameGUI.clearChatMessages();
+                                ingameHud.clearChatMessages();
                             }
                             else if (gameSettings.keyPauseLostFocus.isPressEvent())
                             {
                                 gameSettings.pauseOnLostFocus.toggle();
-                                ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.pauseOnLostFocus);
+                                ingameHud.heldItemTooltipElement.setOptionNameAndValueString(gameSettings.pauseOnLostFocus);
                             }
                             else if (gameSettings.keyToggleItemInfo.isPressEvent())
                             {
                                 gameSettings.showItemDebugInfo.toggle();
-                                ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.showItemDebugInfo);
+                                ingameHud.heldItemTooltipElement.setOptionNameAndValueString(gameSettings.showItemDebugInfo);
                             }
                             else if (gameSettings.keyReloadChunks.isPressEvent())
                             {
@@ -1595,7 +1624,7 @@ public class Minecraft
                             {
                                 gameSettings.ambientOcclusion.toggle();
                                 gameSettings.ambientOcclusion.onUpdate();
-                                ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.ambientOcclusion);
+                                ingameHud.heldItemTooltipElement.setOptionNameAndValueString(gameSettings.ambientOcclusion);
                             }
                             if(!gameSettings.keyToggleDebug.isPressEvent()) f3Press = false;
                         }
@@ -1609,7 +1638,7 @@ public class Minecraft
                         }
                         else if (gameSettings.keyCommand.isPressed())
                         {
-                            displayGuiScreen(new GuiChat("/"));
+                            displayScreen(new ChatScreen("/"));
                         }
                         else
                         {
@@ -1684,7 +1713,7 @@ public class Minecraft
             if(!isGamePaused)
             {
                 Debug.change("effects");
-                effectRenderer.updateEffects();
+                particleEngine.tick();
                 Debug.change("misc");
             }
         }
@@ -1750,20 +1779,20 @@ public class Minecraft
         // Cinematic camera
         if (gameSettings.keyCinematicCamera.isPressEvent(currentInputDevice)) {
             gameSettings.smoothCamera.value = !gameSettings.smoothCamera.value;
-            ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.smoothCamera);
+            ingameHud.heldItemTooltipElement.setOptionNameAndValueString(gameSettings.smoothCamera);
             return true;
         }
 
         // Display inventory
         if (gameSettings.keyInventory.isPressEvent(currentInputDevice)) {
-            displayGuiScreen(getGuiInventory());
+            displayScreen(getInventoryScreen());
             return true;
         }
 
         // Display Guidebook
         if (gameSettings.keyGuidebook.isPressEvent(currentInputDevice)) {
             thePlayer.triggerAchievement(Achievements.OPEN_GUIDEBOOK);
-            thePlayer.displayGUIGuidebook();
+            thePlayer.displayGuidebookScreen();
             return true;
         }
 
@@ -1775,13 +1804,13 @@ public class Minecraft
 
         // Enter photo mode
         if (gameSettings.keyPhotoMode.isPressEvent(currentInputDevice)) {
-            displayGuiScreen(new GuiPhotoMode());
+            displayScreen(new PhotoModeScreen());
             return true;
         }
 
         // Open chat
         if (gameSettings.keyChat.isPressEvent(currentInputDevice)) {
-            displayGuiScreen(new GuiChat());
+            displayScreen(new ChatScreen());
             return true;
         }
 
@@ -1846,7 +1875,7 @@ public class Minecraft
         // Toggle fog
         if (gameSettings.keyToggleFog.isPressEvent(currentInputDevice)) {
             gameSettings.renderDistance.toggle(shift ? -8 : 8);
-            ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.renderDistance);
+            ingameHud.heldItemTooltipElement.setOptionNameAndValueString(gameSettings.renderDistance);
             return true;
         }
 
@@ -1864,7 +1893,7 @@ public class Minecraft
             }
             int newGammaStep = ((currentGammaStep + (shift ? -1 : 1)) + 5) % 5;
             gameSettings.gamma.value = newGammaStep * 0.25f;
-            ingameGUI.guiHeldItemTooltip.setOptionNameAndValueString(gameSettings.gamma);
+            ingameHud.heldItemTooltipElement.setOptionNameAndValueString(gameSettings.gamma);
             return true;
         }
 
@@ -1913,15 +1942,15 @@ public class Minecraft
         return false;
     }
 
-    private GuiInventory getGuiInventory()
+    private InventoryScreen getInventoryScreen()
     {
         if (thePlayer.getGamemode() == Gamemode.creative)
         {
-            return new GuiInventoryCreative(thePlayer);
+            return new InventoryScreenCreative(thePlayer);
         }
         else
         {
-            return new GuiInventory(thePlayer);
+            return new InventoryScreen(thePlayer);
         }
     }
     
@@ -1929,7 +1958,7 @@ public class Minecraft
         try{
             controllerInput.update();
         }catch (Exception e) {
-            e.printStackTrace();
+            LOGGER.warn("Error occurred while updating controller input! Disabling controller input!", e);
             controllerInput = null;
             setInputType(InputType.KEYBOARD);
             return;
@@ -1957,13 +1986,13 @@ public class Minecraft
                 thePlayer.dropCurrentItem(false);
             }
             if(controller.buttonY.pressedThisFrame() || controller.buttonX.pressedThisFrame()) {
-                displayGuiScreen(getGuiInventory());
+                displayScreen(getInventoryScreen());
             }
             if(controller.buttonBack.pressedThisFrame()) {
                 gameSettings.showPlayerList.value = !gameSettings.showPlayerList.value;
             }
             if(controller.buttonStart.pressedThisFrame()) {
-                displayGuiScreen(new GuiIngameMenu());
+                displayScreen(new PauseScreen());
             }
             if(controller.digitalPad.up.pressedThisFrame()) {
                 thePlayer.setHotbarOffset((thePlayer.inventory.hotbarOffset + 27) % (36));
@@ -1989,27 +2018,27 @@ public class Minecraft
                 gameSettings.thirdPersonView.value%=3;
             }
             if (controllerInput.digitalPad.right.pressedThisFrame()){
-                thePlayer.displayGUIGuidebook();
+                thePlayer.displayGuidebookScreen();
             }
         }else {
-            GuiScreen currentScreen = this.currentScreen;
+            Screen currentScreen = this.currentScreen;
             if(controller.buttonB.pressedThisFrame()) {
-                currentScreen.keyTyped((char)0, Keyboard.KEY_BACK, -1, -1);
+                currentScreen.keyPressed((char)0, Keyboard.KEY_BACK, -1, -1);
             }
             if(controller.buttonStart.pressedThisFrame()) {
-                currentScreen.keyTyped((char)0, Keyboard.KEY_ESCAPE, -1, -1);
+                currentScreen.keyPressed((char)0, Keyboard.KEY_ESCAPE, -1, -1);
             }
             if(controller.buttonA.pressedThisFrame()) {
                 currentScreen.mouseClicked((int)controller.cursorX, (int)controller.cursorY, 0);
             }
             if(controller.buttonA.releasedThisFrame()) {
-                currentScreen.mouseMovedOrButtonReleased((int)controller.cursorX, (int)controller.cursorY, 0);
+                currentScreen.mouseReleased((int)controller.cursorX, (int)controller.cursorY, 0);
             }
             if(controller.buttonY.pressedThisFrame()) {
                 currentScreen.mouseClicked((int)controller.cursorX, (int)controller.cursorY, 1);
             }
             if(controller.buttonY.releasedThisFrame()) {
-                currentScreen.mouseMovedOrButtonReleased((int)controller.cursorX, (int)controller.cursorY, 1);
+                currentScreen.mouseReleased((int)controller.cursorX, (int)controller.cursorY, 1);
             }
             if(controller.buttonX.pressedThisFrame()) {
                 currentScreen.mouseClicked((int)controller.cursorX, (int)controller.cursorY, 10);
@@ -2019,7 +2048,7 @@ public class Minecraft
             try{
                 currentScreen.controllerInput(controller);
             }catch (Exception e) {
-                e.printStackTrace();
+                LOGGER.error("Exception occurred while running gui specific controller actions!", e);
             }
         }
     }
@@ -2027,7 +2056,7 @@ public class Minecraft
     private void forceReload()
     {
         long start = System.nanoTime();
-        System.out.println("FORCING RELOAD!");
+        LOGGER.info("FORCING RELOAD!");
         sndManager = new SoundEngine();
         sndManager.init(gameSettings);
         texturePackList.refresh();
@@ -2035,7 +2064,7 @@ public class Minecraft
         if (renderGlobal != null){
             renderGlobal.loadRenderers();
         }
-        System.out.println("RELOAD TOOK '" + (System.nanoTime() - start)/ 1_000_000_000d + "' SECONDS!");
+        LOGGER.debug("RELOAD TOOK '{}' SECONDS!", (System.nanoTime() - start) / 1_000_000_000d);
     }
 
     public boolean isMultiplayerWorld()
@@ -2106,7 +2135,7 @@ public class Minecraft
     {
         Dimension lastDim = Dimension.getDimensionList().get(thePlayer.dimension);
         Dimension newDim = Dimension.getDimensionList().get(dim);
-        System.out.println("Switching to dimension \"" + newDim.getTranslatedName() + "\"!!");
+        LOGGER.info("Switching to dimension \"{}\"!!", newDim.getTranslatedName());
         thePlayer.dimension = dim;
         theWorld.setEntityDead(thePlayer);
         thePlayer.removed = false;
@@ -2210,10 +2239,7 @@ public class Minecraft
             else if(thePlayer != null)
             {
                 thePlayer.resetPos();
-                if(world != null)
-                {
-                    world.entityJoinedWorld(thePlayer);
-                }
+                world.entityJoinedWorld(thePlayer);
             }
             if(!world.isClientSide)
             {
@@ -2230,9 +2256,9 @@ public class Minecraft
             {
                 renderGlobal.changeWorld(world);
             }
-            if(effectRenderer != null)
+            if(particleEngine != null)
             {
-                effectRenderer.clearEffects(world);
+                particleEngine.setWorld(world);
             }
             playerController.adjustPlayer(thePlayer);
             IChunkProvider ichunkprovider = world.getChunkProvider();
@@ -2366,7 +2392,7 @@ public class Minecraft
     
     public String getEntityCountsInfoString()
     {
-        return "P: " + effectRenderer.getNumParticlesString() + ". T: " + theWorld.getNumLoadedEntitiesString();
+        return "P: " + particleEngine.countParticles() + ". T: " + theWorld.getNumLoadedEntitiesString();
     }
 
     public void respawn(boolean flag, int i)
@@ -2438,12 +2464,12 @@ public class Minecraft
         theWorld.spawnPlayerWithLoadedChunks(thePlayer);
         thePlayer.input = new PlayerInput(this);
         thePlayer.id = j;
-        thePlayer.func_6420_o();
+        thePlayer.animate4();
         playerController.adjustPlayer(thePlayer);
         prepareLevel("Respawning");
-        if(currentScreen instanceof GuiGameOver)
+        if(currentScreen instanceof GameOverScreen)
         {
-            displayGuiScreen(null);
+            displayScreen(null);
         }
     }
 
@@ -2466,47 +2492,92 @@ public class Minecraft
         this.renderer.reload();
     }
 
-    public static void startMainThread(String username, String sessionId)
+    public static void startMainThread(String username, String sessionId, String uuid)
     {
-        boolean flag = false;
-        String sessionUsername = username;
         GameWindow gameWindow = new GameWindowGLFW();
         Minecraft mc = new Minecraft(gameWindow);
         Thread thread = new Thread(mc, "Client-Main");
         thread.setPriority(10);
         mc.minecraftUri = "www.minecraft.net";
-        if(sessionUsername != null && sessionId != null)
-        {
-            mc.session = new Session(sessionUsername, sessionId);
-        }
-        else
-        {
-            mc.session = new Session("Player" + System.currentTimeMillis() % 1000L, "");
+
+        sessionId = sessionId == null ? "" : sessionId;
+        if (uuid == null) {
+            if (username != null) {
+                UUID nameUUID = UUIDHelper.getUUIDFromName(username);
+                if (nameUUID != null) {
+                    uuid = nameUUID.toString();
+                }
+            }
+            if (uuid == null) {
+                uuid = "00000000-0000-0000-0000-000000000000";
+            }
         }
+        username = username == null ? "Player" + System.currentTimeMillis() % 1000L : username;
+
+        mc.session = new Session(username, uuid, sessionId);
         thread.start();
     }
 
     public static void main(String[] args)
     {
-
         String playerName = null;
         String sessionId = null;
-        playerName = "Player" + System.currentTimeMillis() % 1000L;
-        if(args.length > 0)
-        {
-            playerName = args[0];
-        }
-        sessionId = "-";
-        if(args.length > 1)
-        {
-            sessionId = args[1];
+        String gameDirectory = null;
+        String uuid = null;
+
+        int pointer = 0;
+        while (pointer < args.length) {
+            switch (args[pointer]) {
+                case "--username": {
+                    try {
+                        playerName = args[pointer + 1];
+                        pointer++;
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    pointer++;
+                    break;
+                }
+                case "--session": {
+                    try {
+                        sessionId = args[pointer + 1];
+                        pointer++;
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    pointer++;
+                    break;
+                }
+                case "--uuid": {
+                    try {
+                        uuid = args[pointer + 1];
+                        pointer++;
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    pointer++;
+                    break;
+                }
+                case "--gameDir": {
+                    try {
+                        gameDirectory = args[pointer + 1];
+                        pointer++;
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    pointer++;
+                    break;
+                }
+                default:
+                    pointer++;
+            }
         }
-        startMainThread(playerName, sessionId);
+        startMainThread(playerName, sessionId, uuid);
     }
     
     public void setInputType(InputType inputType) {
         if(inputType != this.inputType) {
-            System.out.println("Set input type to "+inputType.name());
+            LOGGER.info("Set input type to {}", inputType.name());
         }
         this.inputType = inputType;
         if(inputType == InputType.CONTROLLER) {
@@ -2576,8 +2647,4 @@ public class Minecraft
         }
         return INSTANCE;
     }
-    
-    public static void crash() {
-    	throw new RuntimeException("lol");
-    }
 }
diff --git a/src/main/java/net/minecraft/client/MinecraftApplet.java b/src/main/java/net/minecraft/client/MinecraftApplet.java
index 9eac7fd98..3836593ca 100644
--- a/src/main/java/net/minecraft/client/MinecraftApplet.java
+++ b/src/main/java/net/minecraft/client/MinecraftApplet.java
@@ -8,5 +8,4 @@ public class MinecraftApplet extends Applet {
 	public MinecraftApplet() {
 		throw new RuntimeException("Applet wrapper is not supported!");
 	}
-	
 }
diff --git a/src/main/java/net/minecraft/client/discord/DownloadNativeLibrary.java b/src/main/java/net/minecraft/client/discord/DownloadNativeLibrary.java
index ea6fac289..bbce60cc5 100644
--- a/src/main/java/net/minecraft/client/discord/DownloadNativeLibrary.java
+++ b/src/main/java/net/minecraft/client/discord/DownloadNativeLibrary.java
@@ -1,8 +1,5 @@
 package net.minecraft.client.discord;
 
-import de.jcm.discordgamesdk.Core;
-import de.jcm.discordgamesdk.CreateParams;
-
 import java.io.File;
 import java.io.IOException;
 import java.net.HttpURLConnection;
@@ -12,14 +9,8 @@ import java.util.Locale;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
-/**
- * An examples showing how to automatically download, extract and load
- * Discord's native library.
- */
-public class DownloadNativeLibrary
-{
-    public static File downloadDiscordLibrary() throws IOException
-    {
+public class DownloadNativeLibrary {
+    public static File downloadDiscordLibrary() throws IOException {
         // Find out which name Discord's library has (.dll for Windows, .so for Linux)
         String name = "discord_game_sdk";
         String suffix;
@@ -27,32 +18,25 @@ public class DownloadNativeLibrary
         String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
         String arch = System.getProperty("os.arch").toLowerCase(Locale.ROOT);
 
-        if(osName.contains("windows"))
-        {
+        if (osName.contains("windows")) {
             suffix = ".dll";
-        }
-        else if(osName.contains("linux"))
-        {
+        } else if (osName.contains("linux")) {
             suffix = ".so";
-        }
-        else if(osName.contains("mac os"))
-        {
+        } else if (osName.contains("mac os")) {
             suffix = ".dylib";
-        }
-        else
-        {
-            throw new RuntimeException("cannot determine OS type: "+osName);
+        } else {
+            throw new RuntimeException("cannot determine OS type: " + osName);
         }
 
 		/*
 		Some systems report "amd64" (e.g. Windows and Linux), some "x86_64" (e.g. Mac OS).
 		At this point we need the "x86_64" version, as this one is used in the ZIP.
 		 */
-        if(arch.equals("amd64"))
+        if (arch.equals("amd64"))
             arch = "x86_64";
 
         // Path of Discord's library inside the ZIP
-        String zipPath = "lib/"+arch+"/"+name+suffix;
+        String zipPath = "lib/" + arch + "/" + name + suffix;
 
         // Open the URL as a ZipInputStream
         URL downloadUrl = new URL("https://dl-game-sdk.discordapp.net/2.5.6/discord_game_sdk.zip");
@@ -62,19 +46,17 @@ public class DownloadNativeLibrary
 
         // Search for the right file inside the ZIP
         ZipEntry entry;
-        while((entry = zin.getNextEntry())!=null)
-        {
-            if(entry.getName().equals(zipPath))
-            {
+        while ((entry = zin.getNextEntry()) != null) {
+            if (entry.getName().equals(zipPath)) {
                 // Create a new temporary directory
                 // We need to do this, because we may not change the filename on Windows
-                File tempDir = new File(System.getProperty("java.io.tmpdir"), "java-"+name+System.nanoTime());
-                if(!tempDir.mkdir())
+                File tempDir = new File(System.getProperty("java.io.tmpdir"), "java-" + name + System.nanoTime());
+                if (!tempDir.mkdir())
                     throw new IOException("Cannot create temporary directory");
                 tempDir.deleteOnExit();
 
                 // Create a temporary file inside our directory (with a "normal" name)
-                File temp = new File(tempDir, name+suffix);
+                File temp = new File(tempDir, name + suffix);
                 temp.deleteOnExit();
 
                 // Copy the file in the ZIP to our temporary file
diff --git a/src/main/java/net/minecraft/client/discord/RichPresenceHandlerThread.java b/src/main/java/net/minecraft/client/discord/RichPresenceHandlerThread.java
index 89fc87b6b..d973e777f 100644
--- a/src/main/java/net/minecraft/client/discord/RichPresenceHandlerThread.java
+++ b/src/main/java/net/minecraft/client/discord/RichPresenceHandlerThread.java
@@ -6,36 +6,39 @@ import java.time.Instant;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.mojang.logging.LogUtils;
 import de.jcm.discordgamesdk.Core;
 import de.jcm.discordgamesdk.CreateParams;
 import de.jcm.discordgamesdk.GameSDKException;
 import de.jcm.discordgamesdk.activity.Activity;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.player.MultiplayerLocalPlayer;
-import net.minecraft.client.gui.GuiIngameMenu;
+import net.minecraft.client.gui.PauseScreen;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.biome.Biomes;
 import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.weather.Weathers;
+import org.slf4j.Logger;
 
-public class RichPresenceHandlerThread extends Thread
-{
+public class RichPresenceHandlerThread extends Thread {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private final static long clientId = 896803609696677898L;
     private Core core;
-    private Minecraft minecraft;
+    private final Minecraft minecraft;
     private Instant startTime;
     private boolean hasRegistered = false;
-    private static Map<Dimension, String> dimensionNamesMap = new HashMap<>();
-    static
-    {
+    private static final Map<Dimension, String> dimensionNamesMap = new HashMap<>();
+
+    static {
         dimensionNamesMap.put(Dimension.overworld, "the Overworld");
         dimensionNamesMap.put(Dimension.nether, "the Nether");
         dimensionNamesMap.put(Dimension.paradise, "Paradise");
     }
-    private static Map<Biome, String> biomeNamesMap = new HashMap<>();
-    static
-    {
+
+    private static final Map<Biome, String> biomeNamesMap = new HashMap<>();
+
+    static {
         biomeNamesMap.put(Biomes.OVERWORLD_RAINFOREST, "a rainforest");
         biomeNamesMap.put(Biomes.OVERWORLD_SWAMPLAND, "the swamplands");
         biomeNamesMap.put(Biomes.OVERWORLD_SEASONAL_FOREST, "a seasonal forest");
@@ -60,9 +63,10 @@ public class RichPresenceHandlerThread extends Thread
         biomeNamesMap.put(Biomes.OVERWORLD_CAATINGA, "the caatinga");
         biomeNamesMap.put(Biomes.OVERWORLD_CAATINGA_PLAINS, "the caatinga");
     }
-    private static Map<Weather, String> weatherNamesMap = new HashMap<>();
-    static
-    {
+
+    private static final Map<Weather, String> weatherNamesMap = new HashMap<>();
+
+    static {
         // overworldClear
         weatherNamesMap.put(Weathers.OVERWORLD_RAIN, "in the rain");
         weatherNamesMap.put(Weathers.OVERWORLD_SNOW, "in the snow");
@@ -74,28 +78,22 @@ public class RichPresenceHandlerThread extends Thread
         // overworldRainBlood
     }
 
-    public RichPresenceHandlerThread(Minecraft mc)
-    {
+    public RichPresenceHandlerThread(Minecraft mc) {
         this.minecraft = mc;
     }
 
     @Override
-    public void run()
-    {
+    public void run() {
         File discordLibrary;
-        try
-        {
+        try {
             discordLibrary = DownloadNativeLibrary.downloadDiscordLibrary();
-        }
-        catch (IOException e)
-        {
-            e.printStackTrace();
+        } catch (IOException e) {
+            LOGGER.warn("Error downloading Discord SDK.", e);
             return;
         }
 
-        if(discordLibrary == null)
-        {
-            System.err.println("Error downloading Discord SDK.");
+        if (discordLibrary == null) {
+            LOGGER.warn("Error downloading Discord SDK.");
             return;
         }
         // Initialize the Core
@@ -110,7 +108,7 @@ public class RichPresenceHandlerThread extends Thread
         // Run callbacks forever
         while (true) {
             if (core != null) {
-                if (!hasRegistered){
+                if (!hasRegistered) {
                     core.activityManager().registerCommand("e");
                     hasRegistered = true;
                 }
@@ -125,24 +123,18 @@ public class RichPresenceHandlerThread extends Thread
                     updateActivity();
                 }
             } catch (InterruptedException e) {
-                e.printStackTrace();
+                LOGGER.error("Unexpected Interrupt!", e);
             }
         }
     }
 
-    private void updateActivity()
-    {
-        if (!minecraft.gameSettings.discordRichPresence.value)
-        {
-            if (core != null)
-            {
+    private void updateActivity() {
+        if (!minecraft.gameSettings.discordRichPresence.value) {
+            if (core != null) {
                 destroyCore();
             }
-        }
-        else
-        {
-            if (core == null)
-            {
+        } else {
+            if (core == null) {
                 createCore();
             }
         }
@@ -153,32 +145,23 @@ public class RichPresenceHandlerThread extends Thread
         activity.assets().setLargeImage("bta-logo");
         activity.timestamps().setStart(startTime);
 
-        if (minecraft.theWorld == null)
-        {
+        if (minecraft.theWorld == null) {
             activity.setState("In the main menu");
-        }
-        else if (minecraft.theWorld != null && minecraft.thePlayer != null)
-        {
-            if (minecraft.thePlayer instanceof MultiplayerLocalPlayer)
-            {
+        } else if (minecraft.thePlayer != null) {
+            if (minecraft.thePlayer instanceof MultiplayerLocalPlayer) {
                 activity.setDetails("Multiplayer");
                 int playerCount = ((MultiplayerLocalPlayer) minecraft.thePlayer).sendQueue.players.size();
                 activity.party().size().setCurrentSize(playerCount);
                 activity.party().size().setMaxSize(100);
-            }
-            else
-            {
-                if (minecraft.currentScreen instanceof GuiIngameMenu)
-                {
+            } else {
+                if (minecraft.currentScreen instanceof PauseScreen) {
                     activity.setDetails("Singleplayer (paused)");
-                }
-                else
-                {
+                } else {
                     activity.setDetails("Singleplayer");
                 }
             }
             Dimension activeDimension = Dimension.getDimensionList().get(minecraft.thePlayer.dimension);
-            Biome biome = minecraft.theWorld.getBlockBiome((int)minecraft.thePlayer.x, (int)minecraft.thePlayer.y, (int)minecraft.thePlayer.z);
+            Biome biome = minecraft.theWorld.getBlockBiome((int) minecraft.thePlayer.x, (int) minecraft.thePlayer.y, (int) minecraft.thePlayer.z);
             Weather weather = minecraft.theWorld.getCurrentWeather();
 
             boolean displayDimension = activeDimension != null && dimensionNamesMap.containsKey(activeDimension);
@@ -186,24 +169,18 @@ public class RichPresenceHandlerThread extends Thread
             boolean displayWeather = weather != null && weatherNamesMap.containsKey(weather);
 
             StringBuilder stateString = new StringBuilder();
-            if (displayDimension)
-            {
+            if (displayDimension) {
                 stateString.append("In ").append(dimensionNamesMap.get(activeDimension));
-            }
-            else
-            {
+            } else {
                 stateString.append("Somewhere else");
             }
-            if (displayBiome || displayWeather)
-            {
+            if (displayBiome || displayWeather) {
                 stateString.append(", ");
             }
-            if (displayBiome)
-            {
+            if (displayBiome) {
                 stateString.append("exploring ").append(biomeNamesMap.get(biome));
             }
-            if (displayWeather)
-            {
+            if (displayWeather) {
                 stateString.append(" ").append(weatherNamesMap.get(weather));
             }
 
@@ -213,22 +190,20 @@ public class RichPresenceHandlerThread extends Thread
         core.activityManager().updateActivity(activity);
     }
 
-    private void createCore()
-    {
+    private void createCore() {
         try {
             CreateParams params = new CreateParams();
             params.setClientID(clientId);
             params.setFlags(CreateParams.Flags.NO_REQUIRE_DISCORD);
             // Create the Core
             core = new Core(params);
-        } catch (GameSDKException sdkException){
+        } catch (GameSDKException sdkException) {
             // Exception normally occurs only when discord is not opened on the client
             core = null;
         }
     }
 
-    private void destroyCore()
-    {
+    private void destroyCore() {
         core.close();
         core = null;
     }
diff --git a/src/main/java/net/minecraft/client/entity/ClientSkinVariantList.java b/src/main/java/net/minecraft/client/entity/ClientSkinVariantList.java
index 3c51810b2..530b597ed 100644
--- a/src/main/java/net/minecraft/client/entity/ClientSkinVariantList.java
+++ b/src/main/java/net/minecraft/client/entity/ClientSkinVariantList.java
@@ -14,13 +14,16 @@ import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParseException;
 import com.google.gson.JsonParser;
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.core.entity.SkinVariantList;
 import net.minecraft.core.util.helper.MathHelper;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
 
 public class ClientSkinVariantList extends SkinVariantList {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public static final int MAX_VARIANT_ID = 0xFF;
 
 	private final Minecraft mc;
@@ -50,6 +53,8 @@ public class ClientSkinVariantList extends SkinVariantList {
 				return var.getKeyFromIndex(skinIndex);
 			}
 		} catch (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
 			e.printStackTrace();
 		}
 		return defaultKey;
@@ -61,7 +66,7 @@ public class ClientSkinVariantList extends SkinVariantList {
 			try {
 				jsonString = StringUtils.readInputString(stream);
 			} catch (Exception e) {
-				e.printStackTrace();
+                LOGGER.error("Failed to parse '{}' as a Json String!", variantJsonPath, e);
 				break load;
 			}
             try {
@@ -86,15 +91,15 @@ public class ClientSkinVariantList extends SkinVariantList {
 						variantProcessorMap.put(variantJsonPath, new EntityVariants(variants));
 						return;
 					} else {
-						System.out.println("Error: value 'skins' must either be a integer or an array!");
+                        LOGGER.error("Error at {}: value 'skins' must either be a integer or an array!", variantJsonPath);
 						break load;
 					}
 				}
-            } catch (JsonParseException e) { // TODO, replace with proper non-fatal error logging
-                e.printStackTrace();
+            } catch (JsonParseException e) {
+                LOGGER.error("Failed to parse Json at {}", variantJsonPath, e);
             }
         } catch (IOException e) {
-            e.printStackTrace();
+            LOGGER.error("IO Exception while trying to read '{}'!", variantJsonPath, e);
 			break load;
         }
 		variantProcessorMap.put(variantJsonPath, null);
@@ -106,6 +111,7 @@ public class ClientSkinVariantList extends SkinVariantList {
 		private final int skins;
 
 		public EntityVariants(int skins) {
+			if (skins <= 0) throw new IllegalArgumentException("Skins number attribute must be at-least 1!");
 			this.skins = skins;
 			this.variantEntries = null;
 		}
@@ -117,7 +123,6 @@ public class ClientSkinVariantList extends SkinVariantList {
 			entries.sort(Comparator.comparingDouble(o -> -o.weight));
 
 			for (VariantEntry e : entries) {
-//				System.out.println(e.weight);
 				accWeight += e.weight;
 			}
 
@@ -149,7 +154,6 @@ public class ClientSkinVariantList extends SkinVariantList {
 				counts.putIfAbsent(e.textureKey, 0);
 				counts.put(e.textureKey, counts.get(e.textureKey) + 1);
 			}
-//			System.out.println(counts);
 		}
 
 		public String getKeyFromIndex(int index) {
diff --git a/src/main/java/net/minecraft/client/entity/particle/BreakingItemParticle.java b/src/main/java/net/minecraft/client/entity/particle/BreakingItemParticle.java
index 138809446..229e5628a 100644
--- a/src/main/java/net/minecraft/client/entity/particle/BreakingItemParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/BreakingItemParticle.java
@@ -6,6 +6,7 @@ import net.minecraft.client.render.LightmapHelper;
 //            EntityFX, Item, Block, Tessellator,
 //            World
 
+import net.minecraft.client.render.ParticleEngine;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.Blocks;
@@ -13,8 +14,7 @@ import net.minecraft.core.item.Item;
 import net.minecraft.core.world.World;
 
 public class BreakingItemParticle extends Particle {
-    public BreakingItemParticle(World world, double x, double y, double z, Item item)
-    {
+    public BreakingItemParticle(World world, double x, double y, double z, Item item) {
         super(world, x, y, z, 0.0D, 0.0D, 0.0D);
         this.tex = ItemModelDispatcher.getInstance().getDispatch(item).getIcon(null, item.getDefaultStack());
         this.rCol = this.gCol = this.bCol = 1.0F;
@@ -23,25 +23,25 @@ public class BreakingItemParticle extends Particle {
     }
 
     @Override
-	public int getParticleTexture() {
-        return 2;
+    public int getParticleTexture() {
+        return ParticleEngine.ITEM_TEXTURE;
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float u0 = (float) this.tex.getSubIconU(this.uo / 4F);
         float u2 = (float) this.tex.getSubIconU(0.25f + this.uo / 4F);
         float v0 = (float) this.tex.getSubIconV(this.uo / 4F);
         float v2 = (float) this.tex.getSubIconV(0.25f + this.uo / 4F);
         float r = 0.1F * this.size;
-        float x = (float)(xo + (this.x - this.xo) * partialTick - BreakingItemParticle.xOff);
-        float y = (float)(yo + (this.y - this.yo) * partialTick - BreakingItemParticle.yOff);
-        float z = (float)(zo + (this.z - this.zo) * partialTick - BreakingItemParticle.zOff);
+        float x = (float) (xo + (this.x - this.xo) * partialTick - xOff);
+        float y = (float) (yo + (this.y - this.yo) * partialTick - yOff);
+        float z = (float) (zo + (this.z - this.zo) * partialTick - zOff);
         float br = 1.0f;
         if (LightmapHelper.isLightmapEnabled()) {
-        	t.setLightmapCoord(getLightmapCoord(partialTick));
+            t.setLightmapCoord(getLightmapCoord(partialTick));
         } else {
-        	br = getBrightness(partialTick);
+            br = getBrightness(partialTick);
         }
         t.setColorOpaque_F(br * this.rCol, br * this.gCol, br * this.bCol);
         t.addVertexWithUV(x - xa * r - xa2 * r, y - ya * r, z - za * r - za2 * r, u0, v2);
diff --git a/src/main/java/net/minecraft/client/entity/particle/BubbleParticle.java b/src/main/java/net/minecraft/client/entity/particle/BubbleParticle.java
index 450f0c4a8..6d9f5237c 100644
--- a/src/main/java/net/minecraft/client/entity/particle/BubbleParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/BubbleParticle.java
@@ -17,14 +17,14 @@ public class BubbleParticle extends Particle {
         this.tex = TextureRegistry.getTexture("minecraft:particle/bubble");
         this.setSize(0.02F, 0.02F);
         this.size = this.size * (this.random.nextFloat() * 0.6F + 0.2F);
-        this.xd = xa * 0.2D + (float)(Math.random() * 2D - 1.0D) * 0.02F;
-        this.yd = ya * 0.2D + (float)(Math.random() * 2D - 1.0D) * 0.02F;
-        this.zd = za * 0.2D + (float)(Math.random() * 2D - 1.0D) * 0.02F;
-        this.lifetime = (int)(8D / (Math.random() * 0.8D + 0.2D));
+        this.xd = xa * 0.2D + (Math.random() * 2D - 1.0D) * 0.02F;
+        this.yd = ya * 0.2D + (Math.random() * 2D - 1.0D) * 0.02F;
+        this.zd = za * 0.2D + (Math.random() * 2D - 1.0D) * 0.02F;
+        this.lifetime = (int) (8D / (Math.random() * 0.8D + 0.2D));
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
@@ -36,7 +36,7 @@ public class BubbleParticle extends Particle {
         if (this.needsWater && this.world.getBlockMaterial(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z)) != Material.water) {
             remove();
         }
-        if(this.lifetime-- <= 0) {
+        if (this.lifetime-- <= 0) {
             remove();
         }
     }
diff --git a/src/main/java/net/minecraft/client/entity/particle/ExplodeParticle.java b/src/main/java/net/minecraft/client/entity/particle/ExplodeParticle.java
index 3cad7ad5d..f9fa36927 100644
--- a/src/main/java/net/minecraft/client/entity/particle/ExplodeParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/ExplodeParticle.java
@@ -6,20 +6,20 @@ import net.minecraft.core.world.World;
 public class ExplodeParticle extends Particle {
     public ExplodeParticle(World world, double x, double y, double z, double xa, double ya, double za) {
         super(world, x, y, z, xa, ya, za);
-        this.xd = xa + (float)(Math.random() * 2D - 1.0D) * 0.05F;
-        this.yd = ya + (float)(Math.random() * 2D - 1.0D) * 0.05F;
-        this.zd = za + (float)(Math.random() * 2D - 1.0D) * 0.05F;
+        this.xd = xa + (Math.random() * 2D - 1.0D) * 0.05F;
+        this.yd = ya + (Math.random() * 2D - 1.0D) * 0.05F;
+        this.zd = za + (Math.random() * 2D - 1.0D) * 0.05F;
         this.rCol = this.gCol = this.bCol = this.random.nextFloat() * 0.3F + 0.7F;
         this.size = this.random.nextFloat() * this.random.nextFloat() * 6F + 1.0F;
-        this.lifetime = (int)(16D / (this.random.nextFloat() * 0.8D + 0.2D)) + 2;
+        this.lifetime = (int) (16D / (this.random.nextFloat() * 0.8D + 0.2D)) + 2;
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
-        if(this.age++ >= this.lifetime) {
+        if (this.age++ >= this.lifetime) {
             this.remove();
         }
         int val = (7 - ((this.age * 8) / this.lifetime));
diff --git a/src/main/java/net/minecraft/client/entity/particle/FireflyParticle.java b/src/main/java/net/minecraft/client/entity/particle/FireflyParticle.java
index 5336dc744..bde2b322b 100644
--- a/src/main/java/net/minecraft/client/entity/particle/FireflyParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/FireflyParticle.java
@@ -8,21 +8,20 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 
 public class FireflyParticle extends Particle {
-    float oSize;
-    float sinTimer = 0;
-    boolean isReversed = false;
-    float midR = 0.0f;
-    float midG = 0.0f;
-    float midB = 0.0f;
-    final float minR = 96 / 255f;
-    final float minG = 54 / 255f;
-    final float minB = 0 / 255f;
-    float maxR = 240 / 255f;
-    float maxG = 255 / 255f;
-    float maxB = 173 / 255f;
-    float oR;
-    float oG;
-    float oB;
+    private float sinTimer = 0;
+    private boolean isReversed = false;
+    private float midR = 0.0f;
+    private float midG = 0.0f;
+    private float midB = 0.0f;
+    private final float minR = 96 / 255f;
+    private final float minG = 54 / 255f;
+    private final float minB = 0 / 255f;
+    private float maxR = 240 / 255f;
+    private float maxG = 255 / 255f;
+    private float maxB = 173 / 255f;
+    private final float oR;
+    private final float oG;
+    private final float oB;
 
     public FireflyParticle(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);
@@ -38,7 +37,6 @@ public class FireflyParticle extends Particle {
         this.zd += za;
         this.setColor(type);
         this.size = 2.0F;
-        this.oSize = size;
         this.lifetime = (int) (24D + random.nextInt(6));
         this.lifetime *= (int) scale;
         this.noPhysics = false;
@@ -51,7 +49,7 @@ public class FireflyParticle extends Particle {
         this.oB = this.random.nextFloat() * 0.06f - 0.03f;
     }
 
-    private void setColor(int type){
+    private void setColor(int type) {
         float[] color = FireflyClusterMob.FireflyColor.fireFlyColors.get(type).getMidColor();
         this.midR = color[0];
         this.midG = color[1];
@@ -70,22 +68,19 @@ public class FireflyParticle extends Particle {
     }
 
     @Override
-    public float getBrightness(float partialTick)
-    {
+    public float getBrightness(float partialTick) {
         float internalBrightness = this.getInternalBrightness(partialTick);
         float worldBrightness = super.getBrightness(partialTick);
         return Math.max(internalBrightness, worldBrightness);
     }
 
-    public float getInternalBrightness(float partialTick)
-    {
+    public float getInternalBrightness(float partialTick) {
         float b = (float) (Math.sin(this.age * 0.25f) + 1.0f) / 2f;
         return MathHelper.clamp(b, 0f, 1f);
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2)
-    {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float ibr = getInternalBrightness(partialTick);
         if (ibr < 0.5f) {
             this.rCol = MathHelper.lerp(this.minR, this.midR, ibr * 2);
@@ -101,7 +96,7 @@ public class FireflyParticle extends Particle {
         this.gCol += this.oG;
         this.bCol += this.oB;
 
-        super.render(t, partialTick, xa, ya, za, xa2, za2);
+        super.render(t, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
     }
 
     public void renderParticleInGui(Tessellator t, float partialTick) {
@@ -121,17 +116,17 @@ public class FireflyParticle extends Particle {
         this.bCol += this.oB;
 
         float u0 = (float) tex.getIconUMin();
-        float u2 = (float) tex.getSubIconU(1/16f);
+        float u2 = (float) tex.getSubIconU(1 / 16f);
         float v0 = (float) tex.getIconVMin();
-        float v2 = (float) tex.getSubIconV(1/16f);
+        float v2 = (float) tex.getSubIconV(1 / 16f);
         float r = 0.1F * size;
-        float x = (float)(xo + (this.x - xo) * partialTick);
-        float y = (float)(yo + (this.y - yo) * partialTick);
+        float x = (float) (xo + (this.x - xo) * partialTick);
+        float y = (float) (yo + (this.y - yo) * partialTick);
         float br = 1.0f;
         if (LightmapHelper.isLightmapEnabled()) {
-        	t.setLightmapCoord(getLightmapCoord(partialTick));
+            t.setLightmapCoord(getLightmapCoord(partialTick));
         } else {
-        	br = getBrightness(partialTick);
+            br = getBrightness(partialTick);
         }
         t.setColorOpaque_F(rCol * br, gCol * br, bCol * br);
         t.addVertexWithUV(x + r, y - r, 0, u2, v2);
@@ -139,10 +134,10 @@ public class FireflyParticle extends Particle {
         t.addVertexWithUV(x - r, y + r, 0, u0, v0);
         t.addVertexWithUV(x - r, y - r, 0, u0, v2);
     }
-    
+
     @Override
     public int getLightmapCoord(float partialTick) {
-    	return LightmapHelper.setBlocklightValue(super.getLightmapCoord(partialTick), 15);
+        return LightmapHelper.setBlocklightValue(super.getLightmapCoord(partialTick), 15);
     }
 
     public void tickGui() {
@@ -159,7 +154,7 @@ public class FireflyParticle extends Particle {
         this.yo = this.y;
         this.xd = (MathHelper.sin((this.sinTimer) * 0.15f)) / 60f;
         this.yd = (MathHelper.cos((this.sinTimer) * 0.15f)) / 60f;
-        if (this.isReversed){
+        if (this.isReversed) {
             this.xd = -this.xd;
             this.yd = -this.yd;
         }
@@ -182,7 +177,7 @@ public class FireflyParticle extends Particle {
         this.zo = this.z;
         this.xd = (MathHelper.sin(this.sinTimer * 0.15f)) / 60f;
         this.zd = (MathHelper.cos(this.sinTimer * 0.15f)) / 60f;
-        if (this.isReversed){
+        if (this.isReversed) {
             this.xd = -this.xd;
             this.yd = -this.yd;
             this.zd = -this.zd;
diff --git a/src/main/java/net/minecraft/client/entity/particle/FlameParticle.java b/src/main/java/net/minecraft/client/entity/particle/FlameParticle.java
index 1f7b57ff3..709eb1d42 100644
--- a/src/main/java/net/minecraft/client/entity/particle/FlameParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/FlameParticle.java
@@ -8,43 +8,43 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 
 public class FlameParticle extends Particle {
-    private float oSize;
+    private final float oSize;
 
     public FlameParticle(World world, double x, double y, double z, double xd, double yd, double zd, Type type) {
         super(world, x, y, z, xd, yd, zd);
         this.xd = this.xd * 0.01D + xd;
         this.yd = this.yd * 0.01D + yd;
         this.zd = this.zd * 0.01D + zd;
-        x += (this.random.nextFloat() - this.random.nextFloat()) * 0.05F;
-        y += (this.random.nextFloat() - this.random.nextFloat()) * 0.05F;
-        z += (this.random.nextFloat() - this.random.nextFloat()) * 0.05F;
+        this.x += (this.random.nextFloat() - this.random.nextFloat()) * 0.05F;
+        this.y += (this.random.nextFloat() - this.random.nextFloat()) * 0.05F;
+        this.z += (this.random.nextFloat() - this.random.nextFloat()) * 0.05F;
         this.oSize = this.size;
         this.rCol = this.gCol = this.bCol = 1.0F;
-        this.lifetime = (int)(8D / (Math.random() * 0.8D + 0.2D)) + 4;
+        this.lifetime = (int) (8D / (Math.random() * 0.8D + 0.2D)) + 4;
         this.noPhysics = true;
         this.tex = type.texture;
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float s = ((float) age + partialTick) / (float) lifetime;
         this.size = this.oSize * (1.0F - s * s * 0.5F);
-        super.render(t, partialTick, xa, ya, za, xa2, za2);
+        super.render(t, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
     }
 
     @Override
-	public float getBrightness(float partialTick) {
+    public float getBrightness(float partialTick) {
         float decay = MathHelper.clamp(((float) this.age + partialTick) / (float) this.lifetime, 0.0f, 1.0f);
         return super.getBrightness(partialTick) * decay + (1.0F - decay);
     }
-    
+
     @Override
     public int getLightmapCoord(float partialTick) {
-    	return LightmapHelper.setBlocklightValue(super.getLightmapCoord(partialTick), 15);
+        return LightmapHelper.setBlocklightValue(super.getLightmapCoord(partialTick), 15);
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
@@ -62,14 +62,14 @@ public class FlameParticle extends Particle {
     }
 
     public enum Type {
-    	ORANGE(TextureRegistry.getTexture("minecraft:particle/fire")),
-    	SOUL(TextureRegistry.getTexture("minecraft:particle/fire_soul")),
-    	BLUE(TextureRegistry.getTexture("minecraft:particle/fire_blue"));
-    	
-    	private final IconCoordinate texture;
-    	
-    	Type(IconCoordinate tex) {
-    		this.texture = tex;
-    	}
+        ORANGE(TextureRegistry.getTexture("minecraft:particle/fire")),
+        SOUL(TextureRegistry.getTexture("minecraft:particle/fire_soul")),
+        BLUE(TextureRegistry.getTexture("minecraft:particle/fire_blue"));
+
+        private final IconCoordinate texture;
+
+        Type(IconCoordinate tex) {
+            this.texture = tex;
+        }
     }
 }
diff --git a/src/main/java/net/minecraft/client/entity/particle/FootstepParticle.java b/src/main/java/net/minecraft/client/entity/particle/FootstepParticle.java
index c512d7891..fa2426f45 100644
--- a/src/main/java/net/minecraft/client/entity/particle/FootstepParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/FootstepParticle.java
@@ -1,40 +1,42 @@
 package net.minecraft.client.entity.particle;
 
+import net.minecraft.client.render.ParticleEngine;
 import net.minecraft.core.util.helper.MathHelper;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.world.World;
 import org.lwjgl.opengl.GL11;
 
 public class FootstepParticle extends Particle {
     private int life;
-    private int lifeTime;
-    private final RenderEngine renderEngine;
+    private final int lifeTime;
+    private final TextureManager textureManager;
 
-    public FootstepParticle(RenderEngine renderEngine, World world, double x, double y, double z) {
+    public FootstepParticle(TextureManager textureManager, World world, double x, double y, double z) {
         super(world, x, y, z, 0.0D, 0.0D, 0.0D);
         this.life = 0;
-        this.renderEngine = renderEngine;
+        this.textureManager = textureManager;
         this.xd = this.yd = this.zd = 0.0D;
         this.lifeTime = 200;
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float time = (life + partialTick) / lifeTime;
         time *= time;
         float a = 2.0F - time * 2.0F;
-        if(a > 1.0F) {
+        if (a > 1.0F) {
             a = 1.0F;
         }
         a *= 0.2F;
         GL11.glDisable(GL11.GL_LIGHTING);
         float s = 0.125F;
-        float x = (float)(this.x - xOff);
-        float y = (float)(this.y - yOff);
-        float z = (float)(this.z - zOff);
+        float x = (float) (this.x - xOff);
+        float y = (float) (this.y - yOff);
+        float z = (float) (this.z - zOff);
         float br = this.world.getLightBrightness(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z));
-        this.renderEngine.bindTexture(this.renderEngine.loadTexture("/assets/minecraft/textures/misc/footprint.png"));
+        this.textureManager.bindTexture(this.textureManager.loadTexture("/assets/minecraft/textures/misc/footprint.png"));
+
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
         t.startDrawingQuads();
@@ -49,7 +51,7 @@ public class FootstepParticle extends Particle {
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.life++;
         if (this.life == this.lifeTime) {
             this.remove();
@@ -57,7 +59,7 @@ public class FootstepParticle extends Particle {
     }
 
     @Override
-	public int getParticleTexture() {
-        return 3;
+    public int getParticleTexture() {
+        return ParticleEngine.ENTITY_PARTICLE_TEXTURE;
     }
 }
diff --git a/src/main/java/net/minecraft/client/entity/particle/GoldenArrowParticle.java b/src/main/java/net/minecraft/client/entity/particle/GoldenArrowParticle.java
index d343798e3..57681c0ad 100644
--- a/src/main/java/net/minecraft/client/entity/particle/GoldenArrowParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/GoldenArrowParticle.java
@@ -5,7 +5,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.world.World;
 
 public class GoldenArrowParticle extends Particle {
-    float oSize;
+    private final float oSize;
 
     public GoldenArrowParticle(World world, double x, double y, double z, double xa, double ya, double za) {
         this(world, x, y, z, xa, ya, za, 1.0F);
@@ -20,17 +20,17 @@ public class GoldenArrowParticle extends Particle {
         this.yd += ya;
         this.zd += za;
         this.rCol = gCol = 0.8f;
-        this.bCol = (float)(Math.random() * 0.3D);
+        this.bCol = (float) (Math.random() * 0.3D);
         this.size *= 0.75F;
         this.size *= scale;
         this.oSize = this.size;
-        this.lifetime = (int)(8D / (Math.random() * 0.8D + 0.2D));
+        this.lifetime = (int) (8D / (Math.random() * 0.8D + 0.2D));
         this.lifetime *= (int) scale;
         this.noPhysics = false;
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float l = ((this.age + partialTick) / this.lifetime) * 32F;
         if (l < 0.0F) {
             l = 0.0F;
@@ -39,11 +39,11 @@ public class GoldenArrowParticle extends Particle {
             l = 1.0F;
         }
         this.size = this.oSize * l;
-        super.render(t, partialTick, xa, ya, za, xa2, za2);
+        super.render(t, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
diff --git a/src/main/java/net/minecraft/client/entity/particle/HeartParticle.java b/src/main/java/net/minecraft/client/entity/particle/HeartParticle.java
index 161d5c441..69de17d2d 100644
--- a/src/main/java/net/minecraft/client/entity/particle/HeartParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/HeartParticle.java
@@ -5,14 +5,13 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.world.World;
 
 public class HeartParticle extends Particle {
-    float oSize;
+    private final float oSize;
 
     public HeartParticle(World world, double x, double y, double z, double xa, double ya, double za) {
         this(world, x, y, z, xa, ya, za, 2.0F);
     }
 
-    public HeartParticle(World world, double x, double y, double z, double xa, double ya, double za, float scale)
-    {
+    public HeartParticle(World world, double x, double y, double z, double xa, double ya, double za, float scale) {
         super(world, x, y, z, 0.0D, 0.0D, 0.0D);
         this.xd *= 0.01D;
         this.yd *= 0.01D;
@@ -27,8 +26,7 @@ public class HeartParticle extends Particle {
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2)
-    {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float l = ((this.age + partialTick) / this.lifetime) * 32F;
         if (l < 0.0F) {
             l = 0.0F;
@@ -37,11 +35,11 @@ public class HeartParticle extends Particle {
             l = 1.0F;
         }
         this.size = this.oSize * l;
-        super.render(t, partialTick, xa, ya, za, xa2, za2);
+        super.render(t, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
diff --git a/src/main/java/net/minecraft/client/entity/particle/LavaParticle.java b/src/main/java/net/minecraft/client/entity/particle/LavaParticle.java
index 602656adf..9df62f8f8 100644
--- a/src/main/java/net/minecraft/client/entity/particle/LavaParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/LavaParticle.java
@@ -5,7 +5,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.world.World;
 
 public class LavaParticle extends Particle {
-    private float oSize;
+    private final float oSize;
 
     public LavaParticle(World world, double x, double y, double z) {
         super(world, x, y, z, 0.0D, 0.0D, 0.0D);
@@ -27,10 +27,10 @@ public class LavaParticle extends Particle {
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float l = (this.age + partialTick) / this.lifetime;
         this.size = this.oSize * (1.0F - l * l);
-        super.render(t, partialTick, xa, ya, za, xa2, za2);
+        super.render(t, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/entity/particle/LeafParticle.java b/src/main/java/net/minecraft/client/entity/particle/LeafParticle.java
index 509d371b5..ad3b9990b 100644
--- a/src/main/java/net/minecraft/client/entity/particle/LeafParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/LeafParticle.java
@@ -5,6 +5,7 @@ import net.minecraft.client.render.LightmapHelper;
 // Referenced classes of package net.minecraft.src:
 //            EntityFX, Block, Tessellator, World
 
+import net.minecraft.client.render.ParticleEngine;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
@@ -29,32 +30,31 @@ public class LeafParticle extends Particle {
         return !(block instanceof BaseLeavesBlock);
     }
 
-    public LeafParticle init(int x, int y, int z)
-    {
+    public LeafParticle init(int x, int y, int z) {
         Block block = Block.blocksList[this.world.getBlockId(x, y, z)];
         if (!(block instanceof BaseLeavesBlock)) this.remove();
         int col = BlockColorDispatcher.getInstance().getDispatch(block).getWorldColor(world, x, y, z);
-        this.rCol *= (float)(col >> 16 & 0xff) / 255F;
-        this.gCol *= (float)(col >> 8 & 0xff) / 255F;
-        this.bCol *= (float)(col & 0xff) / 255F;
+        this.rCol *= (float) (col >> 16 & 0xff) / 255F;
+        this.gCol *= (float) (col >> 8 & 0xff) / 255F;
+        this.bCol *= (float) (col & 0xff) / 255F;
         return this;
     }
-    
+
     @Override
-	public void tick() {
+    public void tick() {
         float windDirection = this.world.worldType.getWindManager().getWindDirection(this.world, (float) this.x, (float) this.y, (float) this.z);
         float windIntensity = this.world.worldType.getWindManager().getWindIntensity(this.world, (float) this.x, (float) this.y, (float) this.z) * 0.01f;
 
         float dx = (float) (Math.cos(windDirection * Math.PI * 2) * windIntensity);
         float dz = (float) (Math.sin(windDirection * Math.PI * 2) * windIntensity);
-        
+
         this.xd += dx;
         this.zd += dz;
-        
+
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
-        if(this.age++ >= this.lifetime) {
+        if (this.age++ >= this.lifetime) {
             this.remove();
         }
         this.yd -= 0.04D * this.gravity;
@@ -66,25 +66,25 @@ public class LeafParticle extends Particle {
     }
 
     @Override
-	public int getParticleTexture() {
-        return 1;
+    public int getParticleTexture() {
+        return ParticleEngine.TERRAIN_TEXTURE;
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float u0 = (float) this.tex.getSubIconU(this.uo / 4F);
         float u2 = (float) this.tex.getSubIconU(0.25f);
         float v0 = (float) this.tex.getSubIconV(this.uo / 4F);
         float v2 = (float) this.tex.getSubIconV(0.25f);
         float r = 0.1F * this.size;
-        float x = (float)(this.xo + (this.x - this.xo) * partialTick - LeafParticle.xOff);
-        float y = (float)(this.yo + (this.y - this.yo) * partialTick - LeafParticle.yOff);
-        float z = (float)(this.zo + (this.z - this.zo) * partialTick - LeafParticle.zOff);
+        float x = (float) (this.xo + (this.x - this.xo) * partialTick - xOff);
+        float y = (float) (this.yo + (this.y - this.yo) * partialTick - yOff);
+        float z = (float) (this.zo + (this.z - this.zo) * partialTick - zOff);
         float br = 1.0f;
-        if(LightmapHelper.isLightmapEnabled()) {
-        	t.setLightmapCoord(getLightmapCoord(partialTick));
+        if (LightmapHelper.isLightmapEnabled()) {
+            t.setLightmapCoord(getLightmapCoord(partialTick));
         } else {
-        	br = getBrightness(partialTick);
+            br = getBrightness(partialTick);
         }
         t.setColorOpaque_F(br * this.rCol, br * this.gCol, br * this.bCol);
         t.addVertexWithUV(x - xa * r - xa2 * r, y - ya * r, z - za * r - za2 * r, u0, v2);
diff --git a/src/main/java/net/minecraft/client/entity/particle/NoteParticle.java b/src/main/java/net/minecraft/client/entity/particle/NoteParticle.java
index 682ec57ea..42dfd9f8b 100644
--- a/src/main/java/net/minecraft/client/entity/particle/NoteParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/NoteParticle.java
@@ -7,7 +7,7 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 
 public class NoteParticle extends Particle {
-    float oSize;
+    private final float oSize;
 
     public NoteParticle(World world, double x, double y, double z, double xa, double ya, double za) {
         this(world, x, y, z, xa, ya, za, 2.0F);
@@ -19,9 +19,9 @@ public class NoteParticle extends Particle {
         this.yd *= 0.01D;
         this.zd *= 0.01D;
         this.yd += 0.2D;
-        this.rCol = MathHelper.sin(((float)xa + 0.0F) * MathHelper.PI * 2.0F) * 0.65F + 0.35F;
-        this.gCol = MathHelper.sin(((float)xa + 1f/3) * MathHelper.PI * 2.0F) * 0.65F + 0.35F;
-        this.bCol = MathHelper.sin(((float)xa + 2f/3) * MathHelper.PI * 2.0F) * 0.65F + 0.35F;
+        this.rCol = MathHelper.sin(((float) xa + 0.0F) * MathHelper.PI * 2.0F) * 0.65F + 0.35F;
+        this.gCol = MathHelper.sin(((float) xa + 1f / 3) * MathHelper.PI * 2.0F) * 0.65F + 0.35F;
+        this.bCol = MathHelper.sin(((float) xa + 2f / 3) * MathHelper.PI * 2.0F) * 0.65F + 0.35F;
         this.size *= 0.75F;
         this.size *= scale;
         this.oSize = this.size;
@@ -31,7 +31,7 @@ public class NoteParticle extends Particle {
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float l = ((this.age + partialTick) / this.lifetime) * 32F;
         if (l < 0.0F) {
             l = 0.0F;
@@ -40,11 +40,11 @@ public class NoteParticle extends Particle {
             l = 1.0F;
         }
         this.size = this.oSize * l;
-        super.render(t, partialTick, xa, ya, za, xa2, za2);
+        super.render(t, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
@@ -64,5 +64,4 @@ public class NoteParticle extends Particle {
             this.zd *= 0.7D;
         }
     }
-
 }
diff --git a/src/main/java/net/minecraft/client/entity/particle/Particle.java b/src/main/java/net/minecraft/client/entity/particle/Particle.java
index bd7c57556..28bbe4f01 100644
--- a/src/main/java/net/minecraft/client/entity/particle/Particle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/Particle.java
@@ -1,6 +1,7 @@
 package net.minecraft.client.entity.particle;
 
 import net.minecraft.client.render.LightmapHelper;
+import net.minecraft.client.render.ParticleEngine;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.Entity;
@@ -8,6 +9,9 @@ import net.minecraft.core.util.helper.MathHelper;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.world.World;
 
+/**
+ * Displays a small, temporary texture in the world, used as a visual effect. Managed by {@link ParticleEngine}.
+ */
 public class Particle extends Entity {
     protected IconCoordinate tex;
     protected float uo;
@@ -19,14 +23,19 @@ public class Particle extends Entity {
     protected float rCol;
     protected float gCol;
     protected float bCol;
-    public static double xOff;
-    public static double yOff;
-    public static double zOff;
 
+    /**
+     * Creates a new Particle.
+     * @param world The world the particle will join.
+     * @param x The particle's initial X position.
+     * @param y The particle's initial Y position.
+     * @param z The particle's initial Z position.
+     * @param xa The particle's initial X velocity.
+     * @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) {
         super(world);
-        this.age = 0;
-        this.lifetime = 0;
         setSize(0.2F, 0.2F);
         this.heightOffset = this.bbHeight / 2.0F;
         setPos(x, y, z);
@@ -54,6 +63,10 @@ public class Particle extends Entity {
         return false;
     }
 
+    /**
+     * Sets the "power" of the particle, modifying its speed.
+     * @param power The particle's power.
+     */
     public Particle setPower(float power) {
         this.xd *= power;
         this.yd = (this.yd - 0.1D) * (double)power + 0.1D;
@@ -61,6 +74,10 @@ public class Particle extends Entity {
         return this;
     }
 
+    /**
+     * Sets the visual scale of the particle.
+     * @param scale The new scale of the particle.
+     */
     public Particle setScale(float scale) {
         setSize(0.2F * scale, 0.2F * scale);
         this.size *= scale;
@@ -95,16 +112,24 @@ public class Particle extends Entity {
         }
     }
 
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    /**
+     * Renders the particle in the world.
+     * @param t The tessellator to use to draw the particle.
+     * @param partialTick The time since the last tick.
+     * @param xOff The camera's X offset.
+     * @param yOff The camera's Y offset.
+     * @param zOff The camera's Z offset.
+     */
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         if (this.tex == null) return;
         float u0 = (float) this.tex.getIconUMin();
         float u2 = (float) this.tex.getSubIconU(1);
         float v0 = (float) this.tex.getIconVMin();
         float v2 = (float) this.tex.getSubIconV(1);
         float r = 0.1F * this.size;
-        float x = (float)(this.xo + (this.x - this.xo) * partialTick - Particle.xOff);
-        float y = (float)(this.yo + (this.y - this.yo) * partialTick - Particle.yOff);
-        float z = (float)(this.zo + (this.z - this.zo) * partialTick - Particle.zOff);
+        float x = (float)(this.xo + (this.x - this.xo) * partialTick - xOff);
+        float y = (float)(this.yo + (this.y - this.yo) * partialTick - yOff);
+        float z = (float)(this.zo + (this.z - this.zo) * partialTick - zOff);
         float br = 1.0f;
         if (LightmapHelper.isLightmapEnabled()) {
         	t.setLightmapCoord(getLightmapCoord(partialTick));
@@ -119,7 +144,7 @@ public class Particle extends Entity {
     }
 
     public int getParticleTexture() {
-        return 0;
+        return ParticleEngine.MISC_TEXTURE;
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/entity/particle/ParticleDispatcher.java b/src/main/java/net/minecraft/client/entity/particle/ParticleDispatcher.java
index 957e4322e..39dda81c3 100644
--- a/src/main/java/net/minecraft/client/entity/particle/ParticleDispatcher.java
+++ b/src/main/java/net/minecraft/client/entity/particle/ParticleDispatcher.java
@@ -12,21 +12,24 @@ import net.minecraft.core.util.helper.MathHelper;
 import java.util.ArrayList;
 import java.util.List;
 
-public class ParticleDispatcher extends Dispatcher<String, ParticleLambda> {
-    private static final ParticleDispatcher instance = new ParticleDispatcher();
-    private static final ParticleLambda blank = (world, x, y, z, motionX, motionY, motionZ, data) -> null;
-    public static ParticleDispatcher getInstance()
-    {
-        return instance;
+public final class ParticleDispatcher extends Dispatcher<String, ParticleLambda> {
+    private static final ParticleDispatcher INSTANCE = new ParticleDispatcher();
+    private static final ParticleLambda BLANK = (world, x, y, z, motionX, motionY, motionZ, data) -> null;
+
+    public static ParticleDispatcher getInstance() {
+        return INSTANCE;
     }
-    public List<String> getParticleIds(){
+
+    public List<String> getParticleIds() {
         return new ArrayList<>(dispatches.keySet());
     }
+
     @Override
     protected ParticleLambda getDefault() {
-        return blank;
+        return BLANK;
     }
-    private ParticleDispatcher(){
+
+    private ParticleDispatcher() {
         Minecraft mc = Minecraft.getMinecraft(this);
         addDispatch("bubble", (world, x, y, z, motionX, motionY, motionZ, data) -> new BubbleParticle(world, x, y, z, motionX, motionY, motionZ, true));
         addDispatch("smoke", (world, x, y, z, motionX, motionY, motionZ, data) -> new SmokeParticle(world, x, y, z, motionX, motionY, motionX));
@@ -37,16 +40,16 @@ public class ParticleDispatcher extends Dispatcher<String, ParticleLambda> {
         addDispatch("blueflame", (world, x, y, z, motionX, motionY, motionZ, data) -> new FlameParticle(world, x, y, z, motionX, motionY, motionX, FlameParticle.Type.BLUE));
         addDispatch("soulflame", (world, x, y, z, motionX, motionY, motionZ, data) -> new FlameParticle(world, x, y, z, motionX, motionY, motionX, FlameParticle.Type.SOUL));
         addDispatch("lava", (world, x, y, z, motionX, motionY, motionZ, data) -> new LavaParticle(world, x, y, z));
-        addDispatch("footstep", (world, x, y, z, motionX, motionY, motionZ, data) -> new FootstepParticle(mc.renderEngine, world, x, y, z));
+        addDispatch("footstep", (world, x, y, z, motionX, motionY, motionZ, data) -> new FootstepParticle(mc.textureManager, world, x, y, z));
         addDispatch("splash", (world1, d, d1, d2, d3, d4, d5, data) -> new SplashParticle(world1, d, d1, d2, d3, d4, d5));
         addDispatch("largesmoke", (world, x, y, z, motionX, motionY, motionZ, data) -> new SmokeParticle(world, x, y, z, motionX, motionY, motionX, 2.5f));
         addDispatch("reddust", (world, x, y, z, motionX, motionY, motionZ, data) -> new RedstoneDustParticle(world, x, y, z, (float) motionX, (float) motionY, (float) motionZ, data));
         addDispatch("item", (world, x, y, z, motionX, motionY, motionZ, data) -> new BreakingItemParticle(world, x, y, z, Item.itemsList[MathHelper.clamp(data, 0, Item.itemsList.length - 1)]));
-        addDispatch("block", (world, x, y, z, motionX, motionY, motionZ, data) -> new TerrainParticle(world, x, y, z,motionX,motionY,motionZ, Block.blocksList[BlockParticleHelper.decodeBlockID(data)], BlockParticleHelper.decodeBlockSide(data), BlockParticleHelper.decodeBlockMeta(data)).init((int) x, (int) y, (int) z));
+        addDispatch("block", (world, x, y, z, motionX, motionY, motionZ, data) -> new TerrainParticle(world, x, y, z, motionX, motionY, motionZ, Block.blocksList[BlockParticleHelper.decodeBlockID(data)], BlockParticleHelper.decodeBlockSide(data), BlockParticleHelper.decodeBlockMeta(data)).init((int) x, (int) y, (int) z));
         addDispatch("snowshovel", (world, x, y, z, motionX, motionY, motionZ, data) -> new SnowShovelParticle(world, x, y, z, motionX, motionY, motionX));
         addDispatch("heart", (world, x, y, z, motionX, motionY, motionZ, data) -> new HeartParticle(world, x, y, z, motionX, motionY, motionX));
         addDispatch("slimechunk", (world, x, y, z, motionX, motionY, motionZ, data) -> {
-            if (mc.gameSettings.slimeParticles.value){
+            if (mc.gameSettings.slimeParticles.value) {
                 return new SlimeChunkParticle(world, x, y, z, Items.SLIMEBALL);
             }
             return null;
@@ -57,9 +60,9 @@ public class ParticleDispatcher extends Dispatcher<String, ParticleLambda> {
         addDispatch("fireflyRed", (world, x, y, z, motionX, motionY, motionZ, data) -> new FireflyParticle(world, x, y, z, motionX, motionY, motionX, FireflyClusterMob.FireflyColor.RED.getId()));
         addDispatch("arrowtrail", (world, x, y, z, motionX, motionY, motionZ, data) -> new GoldenArrowParticle(world, x, y, z, motionX, motionY, motionX));
         addDispatch("fallingleaf", (world, x, y, z, motionX, motionY, motionZ, data) -> {
-            int id = world.getBlockId((int)x, (int)y, (int)z);
-            if (id != 0){
-                return new LeafParticle(world, x, y, z, motionX, motionY, motionX).init((int)x, (int)y, (int)z);
+            int id = world.getBlockId(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z));
+            if (id != 0) {
+                return new LeafParticle(world, x, y, z, motionX, motionY, motionX).init(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z));
             }
             return null;
         });
diff --git a/src/main/java/net/minecraft/client/entity/particle/PortalParticle.java b/src/main/java/net/minecraft/client/entity/particle/PortalParticle.java
index c15436794..5fb1b84f6 100644
--- a/src/main/java/net/minecraft/client/entity/particle/PortalParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/PortalParticle.java
@@ -5,13 +5,12 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.world.World;
 
 public class PortalParticle extends Particle {
-    private float oSize;
-    private double xStart;
-    private double yStart;
-    private double zStart;
+    private final float oSize;
+    private final double xStart;
+    private final double yStart;
+    private final double zStart;
 
-    public PortalParticle(World world, double x, double y, double z, double xd, double yd, double zd)
-    {
+    public PortalParticle(World world, double x, double y, double z, double xd, double yd, double zd) {
         super(world, x, y, z, xd, yd, zd);
         this.xd = xd;
         this.yd = yd;
@@ -21,26 +20,26 @@ public class PortalParticle extends Particle {
         this.zStart = this.z = z;
         float br = this.random.nextFloat() * 0.6F + 0.4F;
         this.oSize = this.size = random.nextFloat() * 0.2F + 0.5F;
-        this.rCol = this.gCol = this.bCol = 1.0F * br;
+        this.rCol = this.gCol = this.bCol = br;
         this.gCol *= 0.3F;
         this.rCol *= 0.9F;
-        this.lifetime = (int)(Math.random() * 10D) + 40;
+        this.lifetime = (int) (Math.random() * 10D) + 40;
         this.noPhysics = true;
-        this.tex = TextureRegistry.getTexture("minecraft:particle/puff_" + (int)(Math.random() * 8D));
+        this.tex = TextureRegistry.getTexture("minecraft:particle/puff_" + (int) (Math.random() * 8D));
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float s = (age + partialTick) / lifetime;
         s = 1.0F - s;
         s *= s;
         s = 1.0F - s;
         this.size = this.oSize * s;
-        super.render(t, partialTick, xa, ya, za, xa2, za2);
+        super.render(t, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
     }
 
     @Override
-	public float getBrightness(float partialTick) {
+    public float getBrightness(float partialTick) {
         float br = super.getBrightness(partialTick);
         float pos = (float) this.age / (float) this.lifetime;
         pos *= pos;
@@ -49,7 +48,7 @@ public class PortalParticle extends Particle {
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
diff --git a/src/main/java/net/minecraft/client/entity/particle/RedstoneDustParticle.java b/src/main/java/net/minecraft/client/entity/particle/RedstoneDustParticle.java
index 7126d32d3..e5504509f 100644
--- a/src/main/java/net/minecraft/client/entity/particle/RedstoneDustParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/RedstoneDustParticle.java
@@ -8,7 +8,7 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
 
 public class RedstoneDustParticle extends Particle {
-    float oSize;
+    private final float oSize;
     private int brightness;
 
     public RedstoneDustParticle(World world, double x, double y, double z, float red, float green, float blue, int brightness) {
@@ -18,31 +18,31 @@ public class RedstoneDustParticle extends Particle {
     public RedstoneDustParticle(World world, double x, double y, double z, float scale, float red, float green, float blue, int brightness) {
         super(world, x, y, z, 0.0D, 0.0D, 0.0D);
         this.brightness = -1;
-        if (brightness >= 0){
+        if (brightness >= 0) {
             this.brightness = brightness;
         }
         this.xd *= 0.1D;
         this.yd *= 0.1D;
         this.zd *= 0.1D;
-        float n = (float)Math.random() * 0.4F + 0.6F;
-        this.rCol = ((float)(Math.random() * 0.2D) + 0.8F) * red * n;
-        this.gCol = ((float)(Math.random() * 0.2D) + 0.8F) * green * n;
-        this.bCol = ((float)(Math.random() * 0.2D) + 0.8F) * blue * n;
+        float n = (float) Math.random() * 0.4F + 0.6F;
+        this.rCol = ((float) (Math.random() * 0.2D) + 0.8F) * red * n;
+        this.gCol = ((float) (Math.random() * 0.2D) + 0.8F) * green * n;
+        this.bCol = ((float) (Math.random() * 0.2D) + 0.8F) * blue * n;
         this.size *= 0.75F;
         this.size *= scale;
         this.oSize = this.size;
-        this.lifetime = (int)(8D / (Math.random() * 0.8D + 0.2D));
+        this.lifetime = (int) (8D / (Math.random() * 0.8D + 0.2D));
         this.lifetime *= (int) scale;
         this.noPhysics = false;
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float l = ((this.age + partialTick) / this.lifetime) * 32F;
         if (l < 0.0F) {
             l = 0.0F;
         }
-        if(l > 1.0F) {
+        if (l > 1.0F) {
             l = 1.0F;
         }
         this.size = this.oSize * l;
@@ -53,11 +53,11 @@ public class RedstoneDustParticle extends Particle {
         float v0 = (float) this.tex.getIconVMin();
         float v2 = (float) this.tex.getSubIconV(1);
         float r = 0.1F * this.size;
-        float x = (float)(this.xo + (this.x - this.xo) * partialTick - RedstoneDustParticle.xOff);
-        float y = (float)(this.yo + (this.y - this.yo) * partialTick - RedstoneDustParticle.yOff);
-        float z = (float)(this.zo + (this.z - this.zo) * partialTick - RedstoneDustParticle.zOff);
+        float x = (float) (this.xo + (this.x - this.xo) * partialTick - xOff);
+        float y = (float) (this.yo + (this.y - this.yo) * partialTick - yOff);
+        float z = (float) (this.zo + (this.z - this.zo) * partialTick - zOff);
         float br = 1f;
-        if(LightmapHelper.isLightmapEnabled()) {
+        if (LightmapHelper.isLightmapEnabled()) {
             int xTile = MathHelper.floor(this.x);
             int yTile = MathHelper.floor(this.y);
             int zTile = MathHelper.floor(this.z);
@@ -79,7 +79,7 @@ public class RedstoneDustParticle extends Particle {
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
@@ -87,13 +87,13 @@ public class RedstoneDustParticle extends Particle {
             this.remove();
         }
         int val = (7 - ((this.age * 8) / this.lifetime));
-        if (val >= 0){
+        if (val >= 0) {
             this.tex = TextureRegistry.getTexture("minecraft:particle/puff_" + val);
         } else {
             this.tex = null;
         }
         this.move(this.xd, this.yd, this.zd);
-        if(this.y == this.yo) {
+        if (this.y == this.yo) {
             this.xd *= 1.1D;
             this.zd *= 1.1D;
         }
diff --git a/src/main/java/net/minecraft/client/entity/particle/SlimeChunkParticle.java b/src/main/java/net/minecraft/client/entity/particle/SlimeChunkParticle.java
index ecf458f3f..02fd9054f 100644
--- a/src/main/java/net/minecraft/client/entity/particle/SlimeChunkParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/SlimeChunkParticle.java
@@ -6,6 +6,7 @@ import net.minecraft.client.render.LightmapHelper;
 //            EntityFX, Item, Block, Tessellator,
 //            World
 
+import net.minecraft.client.render.ParticleEngine;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.item.Item;
@@ -22,25 +23,25 @@ public class SlimeChunkParticle extends Particle {
     }
 
     @Override
-	public int getParticleTexture() {
-        return 2;
+    public int getParticleTexture() {
+        return ParticleEngine.ITEM_TEXTURE;
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float u0 = (float) this.tex.getSubIconU(this.uo / 4F);
         float u2 = (float) this.tex.getSubIconU(0.25f + this.uo / 4F);
         float v0 = (float) this.tex.getSubIconV(this.uo / 4F);
         float v2 = (float) this.tex.getSubIconV(0.25f + this.uo / 4F);
         float r = 0.1F * this.size;
-        float x = (float)(this.xo + (this.x - this.xo) * partialTick - SlimeChunkParticle.xOff);
-        float y = (float)(this.yo + (this.y - this.yo) * partialTick - SlimeChunkParticle.yOff);
-        float z = (float)(this.zo + (this.z - this.zo) * partialTick - SlimeChunkParticle.zOff);
+        float x = (float) (this.xo + (this.x - this.xo) * partialTick - xOff);
+        float y = (float) (this.yo + (this.y - this.yo) * partialTick - yOff);
+        float z = (float) (this.zo + (this.z - this.zo) * partialTick - zOff);
         float br = 1.0f;
         if (LightmapHelper.isLightmapEnabled()) {
-        	t.setLightmapCoord(getLightmapCoord(partialTick));
+            t.setLightmapCoord(getLightmapCoord(partialTick));
         } else {
-        	br = getBrightness(partialTick);
+            br = getBrightness(partialTick);
         }
         t.setColorOpaque_F(br * this.rCol, br * this.gCol, br * this.bCol);
         t.addVertexWithUV(x - xa * r - xa2 * r, y - ya * r, z - za * r - za2 * r, u0, v2);
diff --git a/src/main/java/net/minecraft/client/entity/particle/SmokeParticle.java b/src/main/java/net/minecraft/client/entity/particle/SmokeParticle.java
index a3eeaac7e..ae6b527b1 100644
--- a/src/main/java/net/minecraft/client/entity/particle/SmokeParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/SmokeParticle.java
@@ -5,7 +5,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.world.World;
 
 public class SmokeParticle extends Particle {
-    float oSize;
+    private final float oSize;
 
     public SmokeParticle(World world, double x, double y, double z, double xa, double ya, double za) {
         this(world, x, y, z, xa, ya, za, 1.0F);
@@ -29,7 +29,7 @@ public class SmokeParticle extends Particle {
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float l = ((this.age + partialTick) / this.lifetime) * 32F;
         if (l < 0.0F) {
             l = 0.0F;
@@ -38,7 +38,7 @@ public class SmokeParticle extends Particle {
             l = 1.0F;
         }
         this.size = this.oSize * l;
-        super.render(t, partialTick, xa, ya, za, xa2, za2);
+        super.render(t, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/entity/particle/SnowShovelParticle.java b/src/main/java/net/minecraft/client/entity/particle/SnowShovelParticle.java
index fd46b2775..dc888765b 100644
--- a/src/main/java/net/minecraft/client/entity/particle/SnowShovelParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/SnowShovelParticle.java
@@ -6,7 +6,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.world.World;
 
 public class SnowShovelParticle extends Particle {
-    float oSize;
+    private final float oSize;
 
     public SnowShovelParticle(World world, double x, double y, double z, double xa, double ya, double za) {
         this(world, x, y, z, xa, ya, za, 1.0F);
@@ -30,7 +30,7 @@ public class SnowShovelParticle extends Particle {
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float l = ((this.age + partialTick) / this.lifetime) * 32F;
         if(l < 0.0F) {
             l = 0.0F;
@@ -39,7 +39,7 @@ public class SnowShovelParticle extends Particle {
             l = 1.0F;
         }
         this.size = this.oSize * l;
-        super.render(t, partialTick, xa, ya, za, xa2, za2);
+        super.render(t, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/entity/particle/TakeAnimationParticle.java b/src/main/java/net/minecraft/client/entity/particle/TakeAnimationParticle.java
index dd9252e5f..83386fad2 100644
--- a/src/main/java/net/minecraft/client/entity/particle/TakeAnimationParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/TakeAnimationParticle.java
@@ -1,5 +1,6 @@
 package net.minecraft.client.entity.particle;
 
+import net.minecraft.client.render.ParticleEngine;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.client.render.EntityRenderDispatcher;
@@ -9,16 +10,15 @@ import net.minecraft.core.world.World;
 import org.lwjgl.opengl.GL11;
 
 public class TakeAnimationParticle extends Particle {
-    private Entity item;
-    private Entity target;
+    private final Entity item;
+    private final Entity target;
     private int life;
-    private int lifeTime;
-    private float yOffs;
+    private final int lifeTime;
+    private final float yOffs;
 
     public TakeAnimationParticle(World world, Entity item, Entity target, float scale) {
         super(world, item.x, item.y, item.z, item.xd, item.yd, item.zd);
         this.life = 0;
-        this.lifeTime = 0;
         this.item = item;
         this.target = target;
         this.lifeTime = 3;
@@ -26,36 +26,36 @@ public class TakeAnimationParticle extends Particle {
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         float time = (this.life + partialTick) / this.lifeTime;
         time *= time;
         double xo = item.x;
         double yo = item.y;
         double zo = item.z;
-        double xt = target.xo + (target.x - target.xo) * (double) partialTick;
-        double yt = target.yo + (target.y - target.yo) * (double) partialTick + (double) yOffs;
-        double zt = target.zo + (target.z - target.zo) * (double) partialTick;
+        double xt = target.xo + (target.x - target.xo) * partialTick;
+        double yt = target.yo + (target.y - target.yo) * partialTick + yOffs;
+        double zt = target.zo + (target.z - target.zo) * partialTick;
         double xx = xo + (xt - xo) * time;
         double yy = yo + (yt - yo) * time;
         double zz = zo + (zt - zo) * time;
         int xTile = MathHelper.floor(xx);
-        int yTile = MathHelper.floor(yy + (double)(this.heightOffset / 2.0F));
+        int yTile = MathHelper.floor(yy + (this.heightOffset / 2.0F));
         int zTile = MathHelper.floor(zz);
-        xx -= TakeAnimationParticle.xOff;
-        yy -= TakeAnimationParticle.yOff;
-        zz -= TakeAnimationParticle.zOff;
+        xx -= xOff;
+        yy -= yOff;
+        zz -= zOff;
         float br = 1.0f;
-        if(LightmapHelper.isLightmapEnabled()) {
-        	LightmapHelper.setLightmapCoord(this.item.world.getLightmapCoord(xTile, yTile, zTile, 0));
-        }else {
-        	br = this.world.getLightBrightness(xTile, yTile, zTile);
+        if (LightmapHelper.isLightmapEnabled()) {
+            LightmapHelper.setLightmapCoord(this.item.world.getLightmapCoord(xTile, yTile, zTile, 0));
+        } else {
+            br = this.world.getLightBrightness(xTile, yTile, zTile);
         }
         GL11.glColor4f(br, br, br, 1.0F);
-        EntityRenderDispatcher.instance.renderEntityWithPosYaw(t, this.item, (float)xx, (float)yy, (float)zz, this.item.yRot, partialTick);
+        EntityRenderDispatcher.instance.renderEntityWithPosYaw(t, this.item, (float) xx, (float) yy, (float) zz, this.item.yRot, partialTick);
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.life++;
         if (this.life == this.lifeTime) {
             remove();
@@ -63,7 +63,7 @@ public class TakeAnimationParticle extends Particle {
     }
 
     @Override
-	public int getParticleTexture() {
-        return 3;
+    public int getParticleTexture() {
+        return ParticleEngine.ENTITY_PARTICLE_TEXTURE;
     }
 }
diff --git a/src/main/java/net/minecraft/client/entity/particle/TerrainParticle.java b/src/main/java/net/minecraft/client/entity/particle/TerrainParticle.java
index 721c3bbb0..40d1e002b 100644
--- a/src/main/java/net/minecraft/client/entity/particle/TerrainParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/TerrainParticle.java
@@ -5,6 +5,7 @@ import net.minecraft.client.render.LightmapHelper;
 // Referenced classes of package net.minecraft.src:
 //            EntityFX, Block, Tessellator, World
 
+import net.minecraft.client.render.ParticleEngine;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
@@ -17,16 +18,14 @@ public class TerrainParticle extends Particle {
     private final Block block;
     private final Side side;
 
-    public TerrainParticle(World world, double x, double y, double z, double xa, double ya, double za, Block block, int side, int meta)
-    {
+    public TerrainParticle(World world, double x, double y, double z, double xa, double ya, double za, Block block, Side side, int meta) {
         super(world, x, y, z, xa, ya, za);
-        this.side = Side.getSideById(side);
+        this.side = side;
         this.block = block;
         this.tex = BlockModelDispatcher.getInstance().getDispatch(block).getParticleTexture(this.side, meta);
         this.gravity = block != null ? block.blockParticleGravity : 0;
         this.rCol = this.gCol = this.bCol = 0.6F;
         this.size /= 2.0F;
-
     }
 
     public TerrainParticle init(int x, int y, int z) {
@@ -42,26 +41,26 @@ public class TerrainParticle extends Particle {
     }
 
     @Override
-	public int getParticleTexture() {
-        return 1;
+    public int getParticleTexture() {
+        return ParticleEngine.TERRAIN_TEXTURE;
     }
 
     @Override
-    public void render(Tessellator t, float partialTick, float xa, float ya, float za, float xa2, float za2) {
+    public void render(Tessellator t, float partialTick, double xOff, double yOff, double zOff, float xa, float ya, float za, float xa2, float za2) {
         if (this.tex == null) return;
         float u0 = (float) this.tex.getSubIconU(this.uo / 4F);
         float u2 = (float) this.tex.getSubIconU(0.25f + this.uo / 4F);
         float v0 = (float) this.tex.getSubIconV(this.uo / 4F);
         float v2 = (float) this.tex.getSubIconV(0.25f + this.uo / 4F);
         float r = 0.1F * this.size;
-        float x = (float)(this.xo + (this.x - this.xo) * partialTick - TerrainParticle.xOff);
-        float y = (float)(this.yo + (this.y - this.yo) * partialTick - TerrainParticle.yOff);
-        float z = (float)(this.zo + (this.z - this.zo) * partialTick - TerrainParticle.zOff);
+        float x = (float) (this.xo + (this.x - this.xo) * partialTick - xOff);
+        float y = (float) (this.yo + (this.y - this.yo) * partialTick - yOff);
+        float z = (float) (this.zo + (this.z - this.zo) * partialTick - zOff);
         float br = 1.0f;
         if (LightmapHelper.isLightmapEnabled()) {
-        	t.setLightmapCoord(getLightmapCoord(partialTick));
+            t.setLightmapCoord(getLightmapCoord(partialTick));
         } else {
-        	br = getBrightness(partialTick);
+            br = getBrightness(partialTick);
         }
         t.setColorOpaque_F(br * this.rCol, br * this.gCol, br * this.bCol);
         t.addVertexWithUV(x - xa * r - xa2 * r, y - ya * r, z - za * r - za2 * r, u0, v2);
diff --git a/src/main/java/net/minecraft/client/entity/particle/WaterDropParticle.java b/src/main/java/net/minecraft/client/entity/particle/WaterDropParticle.java
index 7f7c7640f..8de343b4b 100644
--- a/src/main/java/net/minecraft/client/entity/particle/WaterDropParticle.java
+++ b/src/main/java/net/minecraft/client/entity/particle/WaterDropParticle.java
@@ -18,11 +18,11 @@ public class WaterDropParticle extends Particle {
         this.tex = TextureRegistry.getTexture("minecraft:particle/splash_rain_" + this.random.nextInt(4));
         this.setSize(0.01F, 0.01F);
         this.gravity = 0.06F;
-        this.lifetime = (int)(8D / (Math.random() * 0.8D + 0.2D));
+        this.lifetime = (int) (8D / (Math.random() * 0.8D + 0.2D));
     }
 
     @Override
-	public void tick() {
+    public void tick() {
         this.xo = this.x;
         this.yo = this.y;
         this.zo = this.z;
@@ -34,8 +34,7 @@ public class WaterDropParticle extends Particle {
         if (this.lifetime-- <= 0) {
             this.remove();
         }
-        if (this.onGround)
-        {
+        if (this.onGround) {
             if (Math.random() < 0.5D) {
                 this.remove();
             }
@@ -43,10 +42,9 @@ public class WaterDropParticle extends Particle {
             this.zd *= 0.7D;
         }
         Material m = this.world.getBlockMaterial(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z));
-        if(m.isLiquid() || m.isSolid()) {
+        if (m.isLiquid() || m.isSolid()) {
             double y0 = (MathHelper.floor(this.y) + 1) - FluidBlock.getWaterVolume(this.world.getBlockMetadata(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z)));
-            if(this.y < y0)
-            {
+            if (this.y < y0) {
                 remove();
             }
         }
diff --git a/src/main/java/net/minecraft/client/entity/player/LocalPlayer.java b/src/main/java/net/minecraft/client/entity/player/LocalPlayer.java
index 6f7cb3f0c..1ab8f1887 100644
--- a/src/main/java/net/minecraft/client/entity/player/LocalPlayer.java
+++ b/src/main/java/net/minecraft/client/entity/player/LocalPlayer.java
@@ -1,20 +1,22 @@
 package net.minecraft.client.entity.player;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.particle.TakeAnimationParticle;
-import net.minecraft.client.gui.GuiChest;
-import net.minecraft.client.gui.GuiCrafting;
-import net.minecraft.client.gui.GuiDispenser;
-import net.minecraft.client.gui.GuiEditFlag;
-import net.minecraft.client.gui.GuiEditLabel;
-import net.minecraft.client.gui.GuiEditSign;
-import net.minecraft.client.gui.GuiFurnace;
-import net.minecraft.client.gui.GuiPaintingPicker;
-import net.minecraft.client.gui.GuiPickMonster;
-import net.minecraft.client.gui.GuiTrommel;
-import net.minecraft.client.gui.GuiWandPickerMonster;
+import net.minecraft.client.gui.container.ContainerScreen;
+import net.minecraft.client.gui.container.CraftingScreen;
+import net.minecraft.client.gui.container.DispenserScreen;
+import net.minecraft.client.gui.container.FlagEditorScreen;
+import net.minecraft.client.gui.LabelEditorScreen;
+import net.minecraft.client.gui.SignEditorScreen;
+import net.minecraft.client.gui.container.FurnaceScreen;
+import net.minecraft.client.gui.PaintingPickerScreen;
+import net.minecraft.client.gui.MobPickerScreen;
+import net.minecraft.client.gui.container.TrommelScreen;
+import net.minecraft.client.gui.WandMobPickerScreen;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.input.PlayerInput;
 import net.minecraft.core.achievement.Achievement;
 import net.minecraft.core.achievement.Achievements;
@@ -48,18 +50,11 @@ import net.minecraft.core.util.helper.GetSkinUrlThread;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.world.World;
-
-// Referenced classes of package net.minecraft.src:
-//            Player, MouseFilter, Session, MovementInput,
-//            Achievements, StatFileWriter, GuiHudToasts, World,
-//            SoundEngine, AxisAlignedBB, NBTTagCompound, GuiEditSign,
-//            GuiChest, GuiCrafting, GuiFurnace, GuiDispenser, 
-//            EntityPickupFX, EffectRenderer, InventoryPlayer, GuiIngame, 
-//            StatBase, Achievement, MathHelper, SignBlockEntity,
-//            IInventory, FurnaceBlockEntity, DispenserBlockEntity, Entity
+import org.slf4j.Logger;
 
 public class LocalPlayer extends Player
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public PlayerInput input;
     protected Minecraft mc;
     public final ClientPlayerCommandSender sender;
@@ -72,9 +67,10 @@ public class LocalPlayer extends Player
         sender = new ClientPlayerCommandSender(minecraft, this);
         this.dimension = dimension;
         username = session.username;
+        uuid = session.uuid;
         
         new GetSkinUrlThread(this);
-        System.out.println("logged in with session name: " + username);
+        LOGGER.info("logged in with session name: {}", username);
     }
 
     public float getFovModifier() {
@@ -131,17 +127,17 @@ public class LocalPlayer extends Player
         AchievementToast invToast = new AchievementToast(Achievements.OPEN_INVENTORY, true);
         AchievementToast guideToast = new AchievementToast(Achievements.OPEN_GUIDEBOOK, true);
 
-        if (!this.mc.statsCounter.isUnlocked(Achievements.OPEN_INVENTORY) && !this.mc.guiAchievementToast.isDisplayingToast(invToast))
+        if (!this.mc.statsCounter.isUnlocked(Achievements.OPEN_INVENTORY) && !this.mc.guiToasts.isDisplayingToast(invToast))
         {
-            this.mc.guiAchievementToast.addToast(invToast);
+            this.mc.guiToasts.addToast(invToast);
         }
         if (/*this.mc.statsCounter.isUnlocked(Achievements.OPEN_INVENTORY) &&*/
                 !this.mc.statsCounter.isUnlocked(Achievements.OPEN_GUIDEBOOK) &&
 //                !this.mc.guiAchievementToast.isDisplayingToast(invToast) &&
-                !this.mc.guiAchievementToast.isDisplayingToast(guideToast)
+                !this.mc.guiToasts.isDisplayingToast(guideToast)
         )
         {
-            this.mc.guiAchievementToast.addToast(guideToast);
+            this.mc.guiToasts.addToast(guideToast);
         }
 
         prevTimeInPortal = timeInPortal;
@@ -153,7 +149,7 @@ public class LocalPlayer extends Player
             }
             if(mc.currentScreen != null)
             {
-                mc.displayGuiScreen(null);
+                mc.displayScreen(null);
             }
             if(timeInPortal == 0.0F)
             {
@@ -237,7 +233,7 @@ public class LocalPlayer extends Player
     @Override
     public void wakeUpPlayer(boolean flag, boolean flag1) {
         super.wakeUpPlayer(flag, flag1);
-        mc.displayGuiScreen(null);
+        mc.displayScreen(null);
     }
     
     @Override
@@ -258,85 +254,84 @@ public class LocalPlayer extends Player
     public void closeScreen()
     {
         super.closeScreen();
-        mc.displayGuiScreen(null);
+        mc.displayScreen(null);
     }
 
     @Override
-    public void displayGUIEditSign(SignBlockEntity tileentitysign)
+    public void displaySignEditorScreen(SignBlockEntity blockEntity)
     {
-        mc.displayGuiScreen(new GuiEditSign(tileentitysign));
+        mc.displayScreen(new SignEditorScreen(blockEntity));
     }
 
     @Override
-    public void displayGUIEditFlag(FlagBlockEntity tileEntityFlag)
+    public void displayFlagEditorScreen(FlagBlockEntity blockEntity)
     {
-        mc.displayGuiScreen(new GuiEditFlag(this, tileEntityFlag));
+        mc.displayScreen(new FlagEditorScreen(this, blockEntity));
     }
 
     @Override
-    public void displayGUIChest(Container iinventory)
+    public void displayContainerScreen(Container container)
     {
-        mc.displayGuiScreen(new GuiChest(inventory, iinventory));
+        mc.displayScreen(new ContainerScreen(inventory, container));
     }
 
     @Override
-    public void displayGUIWorkbench(int i, int j, int k)
+    public void displayWorkbenchScreen(int x, int y, int z)
     {
-        mc.displayGuiScreen(new GuiCrafting(inventory, world, i, j, k));
+        mc.displayScreen(new CraftingScreen(inventory, world, x, y, z));
     }
 
     @Override
-    public void displayGUIEditLabel(ItemStack itemstack, int slot)
+    public void displayLabelEditorScreen(ItemStack itemStack, int slot)
     {
-        mc.displayGuiScreen(new GuiEditLabel(itemstack, slot));
+        mc.displayScreen(new LabelEditorScreen(itemStack, slot));
     }
 
     @Override
-    public void displayGUIPaintingPicker()
+    public void displayPaintingPickerScreen()
     {
-        mc.displayGuiScreen(new GuiPaintingPicker(this));
+        mc.displayScreen(new PaintingPickerScreen(this));
     }
 
     @Override
-    public void displayGUIMobSpawnerPicker(int x, int y, int z) {
+    public void displayMobPickerScreen(int x, int y, int z) {
         String currentMobId = ((MobSpawnerBlockEntity) world.getBlockEntity(x, y, z)).getMobId();
-        mc.displayGuiScreen(new GuiPickMonster(currentMobId, x, y, z));
+        mc.displayScreen(new MobPickerScreen(currentMobId, x, y, z));
     }
     @Override
-    public void displayGUIWandMonsterPicker(ItemStack stack) {
-        String currentMobId = stack.getData().getStringOrDefault("monster", "Pig");
-        mc.displayGuiScreen(new GuiWandPickerMonster(currentMobId, stack));
+    public void displayWandMobPickerScreen(ItemStack itemStack) {
+        String currentMobId = itemStack.getData().getStringOrDefault("monster", "Pig");
+        mc.displayScreen(new WandMobPickerScreen(currentMobId, itemStack));
     }
 
     @Override
-    public void displayGUIFurnace(FurnaceBlockEntity tileentityfurnace)
+    public void displayFurnaceScreen(FurnaceBlockEntity blockEntity)
     {
-        mc.displayGuiScreen(new GuiFurnace(inventory, tileentityfurnace));
+        mc.displayScreen(new FurnaceScreen(inventory, blockEntity));
     }
 
     @Override
-    public void displayGUITrommel(TrommelBlockEntity tileEntityTrommel)
+    public void displayTrommelScreen(TrommelBlockEntity blockEntity)
     {
-        mc.displayGuiScreen(new GuiTrommel(inventory, tileEntityTrommel));
+        mc.displayScreen(new TrommelScreen(inventory, blockEntity));
     }
 
     @Override
-    public void displayGUIDispenser(DispenserBlockEntity tileentitydispenser)
+    public void displayDispenserScreen(DispenserBlockEntity blockEntity)
     {
-        mc.displayGuiScreen(new GuiDispenser(inventory, tileentitydispenser));
+        mc.displayScreen(new DispenserScreen(inventory, blockEntity));
     }
 
-    public void displayGUIGuidebook()
-    {
-//        mc.displayGuiScreen(new GuiGuidebook(this));
-        mc.displayGuiScreen(new net.minecraft.client.gui.guidebook.GuiGuidebook());
+    @Override
+    public void displayGuidebookScreen() {
+        mc.displayScreen(new GuidebookScreen());
     }
 
     @Override
     public void onItemPickup(Entity entity, ItemStack item)
     {
         addStat(item.getItem().getStat(StatList.STAT_PICKED_UP), 1);
-        mc.effectRenderer.addEffect(new TakeAnimationParticle(mc.theWorld, entity, this, -0.5F));
+        mc.particleEngine.add(new TakeAnimationParticle(mc.theWorld, entity, this, -0.5F));
     }
 
     public int getPlayerProtectionAmount()
@@ -373,11 +368,12 @@ public class LocalPlayer extends Player
                 }
                 sender.sendMessage(TextFormatting.RED + "Command '" + args[0] + "' does not exist!");
             }catch (Exception e) {
-                e.printStackTrace();
-                mc.ingameGUI.addChatMessage(TextFormatting.RED + "Error!");
+                LOGGER.error("Exception while trying to perform command '" + s + "'!", e);
+                mc.ingameHud.addChatMessage(TextFormatting.RED + "Error!");
+                mc.ingameHud.addChatMessage(TextFormatting.RED + e.getMessage());
             }
         } else {
-            mc.ingameGUI.addChatMessage("<" + getDisplayName() + TextFormatting.RESET + "> " + TextFormatting.WHITE + s);
+            mc.ingameHud.addChatMessage("<" + getDisplayName() + TextFormatting.RESET + "> " + TextFormatting.WHITE + s);
         }
     }
     
@@ -429,7 +425,7 @@ public class LocalPlayer extends Player
     }
 
     @Override
-    public void func_6420_o()
+    public void animate4()
     {
     }
     
@@ -445,7 +441,7 @@ public class LocalPlayer extends Player
             {
                 if(!mc.statsCounter.isUnlocked(achievement))
                 {
-                    mc.guiAchievementToast.addToast(new AchievementToast(achievement, false));
+                    mc.guiToasts.addToast(new AchievementToast(achievement, false));
                 }
                 mc.statsCounter.add(stat, i);
             }
@@ -456,9 +452,9 @@ public class LocalPlayer extends Player
     }
     
     @Override
-    public int getStat(Stat statbase)
+    public int getStat(Stat stat)
     {
-        return mc.statsCounter.readStat(statbase);
+        return mc.statsCounter.readStat(stat);
     }
 
     private boolean isBlockTranslucent(int i, int j, int k)
@@ -530,12 +526,12 @@ public class LocalPlayer extends Player
     
 	@Override
 	public void sendMessage(String message) {
-		mc.ingameGUI.addChatMessage(message);
+		mc.ingameHud.addChatMessage(message);
 	}
 
 	@Override
 	public void sendStatusMessage(String message) {
-		mc.ingameGUI.guiHeldItemTooltip.setString(message);
+		mc.ingameHud.heldItemTooltipElement.setString(message);
 	}
 
 }
diff --git a/src/main/java/net/minecraft/client/entity/player/MultiplayerLocalPlayer.java b/src/main/java/net/minecraft/client/entity/player/MultiplayerLocalPlayer.java
index 66adcb25e..2c8de1243 100644
--- a/src/main/java/net/minecraft/client/entity/player/MultiplayerLocalPlayer.java
+++ b/src/main/java/net/minecraft/client/entity/player/MultiplayerLocalPlayer.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.entity.player;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.guidebook.GuiGuidebook;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.net.handler.ClientPacketHandler;
 import net.minecraft.core.achievement.stat.Stat;
 import net.minecraft.core.data.registry.Registries;
@@ -188,10 +188,10 @@ public class MultiplayerLocalPlayer extends LocalPlayer
     }
 
     @Override
-	public void displayGUIGuidebook()
+	public void displayGuidebookScreen()
     {
-        mc.displayGuiScreen(new GuiGuidebook());
-        sendQueue.addToSendQueue(new GuidebookPacket(mc.currentScreen instanceof GuiGuidebook));
+        mc.displayScreen(new GuidebookScreen());
+        sendQueue.addToSendQueue(new GuidebookPacket(mc.currentScreen instanceof GuidebookScreen));
     }
 
     @Override
@@ -248,11 +248,11 @@ public class MultiplayerLocalPlayer extends LocalPlayer
     }
     
     @Override
-	public int getStat(Stat statbase)
+	public int getStat(Stat stat)
     {
-    	if (statbase.clientside)
+    	if (stat.clientside)
     	{
-    		return super.getStat(statbase);
+    		return super.getStat(stat);
     	}
     	return 0;
     }
diff --git a/src/main/java/net/minecraft/client/entity/player/RemotePlayer.java b/src/main/java/net/minecraft/client/entity/player/RemotePlayer.java
index 8d599b232..4e08e4566 100644
--- a/src/main/java/net/minecraft/client/entity/player/RemotePlayer.java
+++ b/src/main/java/net/minecraft/client/entity/player/RemotePlayer.java
@@ -14,6 +14,8 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.util.helper.DamageType;
 import net.minecraft.core.util.helper.GetSkinUrlThread;
 
+import java.util.UUID;
+
 public class RemotePlayer extends Player
 {
     private int lerpSteps;
@@ -23,11 +25,12 @@ public class RemotePlayer extends Player
     private double lerpYRot;
     private double lerpXRot;
 //    float fallTime;
-    public RemotePlayer(World world, String username)
+    public RemotePlayer(World world, String username, UUID uuid)
     {
         super(world);
 //        fallTime = 0.0F;
         this.username = username;
+        this.uuid = uuid;
         heightOffset = 0.0F;
         footSize = 0.0F;
         noPhysics = true;
@@ -143,7 +146,7 @@ public class RemotePlayer extends Player
     }
 
     @Override
-	public void func_6420_o()
+	public void animate4()
     {
     }
 	@Override
diff --git a/src/main/java/net/minecraft/client/gui/GuiAddServer.java b/src/main/java/net/minecraft/client/gui/AddServerScreen.java
similarity index 58%
rename from src/main/java/net/minecraft/client/gui/GuiAddServer.java
rename to src/main/java/net/minecraft/client/gui/AddServerScreen.java
index 672eb2d4a..51e8773a7 100644
--- a/src/main/java/net/minecraft/client/gui/GuiAddServer.java
+++ b/src/main/java/net/minecraft/client/gui/AddServerScreen.java
@@ -5,23 +5,21 @@ import net.minecraft.core.net.SavedServerList;
 import net.minecraft.core.lang.I18n;
 import org.lwjgl.input.Keyboard;
 
-import java.time.LocalDateTime;
-
 // Referenced classes of package net.minecraft.src:
 //            GuiScreen, GuiTextField, StringTranslate, GuiButton, 
 //            gGameSettings, GuiConnecting
 
-public class GuiAddServer extends GuiScreen
+public class AddServerScreen extends Screen
 {
-    private GuiButton buttonSave;
-    private GuiButton buttonCancel;
-    private GuiButton buttonShowIp;
-    private GuiTextField ipTextField;
-    private GuiTextField serverNameTextField;
+    private ButtonElement buttonSave;
+    private ButtonElement buttonCancel;
+    private ButtonElement buttonShowIp;
+    private TextFieldElement ipTextField;
+    private TextFieldElement serverNameTextField;
     private SavedServerList serverList;
     private boolean showIp = true;
 
-    public GuiAddServer(GuiScreen guiscreen, SavedServerList serverList)
+    public AddServerScreen(Screen guiscreen, SavedServerList serverList)
     {
         super(guiscreen);
         this.serverList = serverList;
@@ -39,15 +37,15 @@ public class GuiAddServer extends GuiScreen
     {
         I18n stringtranslate = I18n.getInstance();
         Keyboard.enableRepeatEvents(true);
-        controlList.clear();
-        controlList.add(buttonSave = new GuiButton(0, width / 2 - 100, height / 4 + 96 + 12, stringtranslate.translateKey("gui.add_server.button.save")));
-        controlList.add(buttonCancel = new GuiButton(1, width / 2 - 100, height / 4 + 120 + 12, stringtranslate.translateKey("gui.add_server.button.cancel")));
-        serverNameTextField = new GuiTextField(this, fontRenderer, width / 2 - 100, (height / 4 - 10) + 18, 200, 20, "", "");
+        buttons.clear();
+        buttons.add(buttonSave = new ButtonElement(0, width / 2 - 100, height / 4 + 96 + 12, stringtranslate.translateKey("gui.add_server.button.save")));
+        buttons.add(buttonCancel = new ButtonElement(1, width / 2 - 100, height / 4 + 120 + 12, stringtranslate.translateKey("gui.add_server.button.cancel")));
+        serverNameTextField = new TextFieldElement(this, font, width / 2 - 100, (height / 4 - 10) + 18, 200, 20, "", "");
         serverNameTextField.isFocused = true;
         serverNameTextField.setMaxStringLength(32);
-        ipTextField = new GuiTextField(this, fontRenderer, width / 2 - 100, (height / 4 - 10) + 50 + 18, 200, 20, "", "");
+        ipTextField = new TextFieldElement(this, font, width / 2 - 100, (height / 4 - 10) + 50 + 18, 200, 20, "", "");
         ipTextField.setMaxStringLength(128);
-        controlList.add(buttonShowIp = new GuiButton(2, width / 2 - 100, (height / 4 - 10) + 50 + 18 + 20 + 4, 200, 20, getShowIpLabel()));
+        buttons.add(buttonShowIp = new ButtonElement(2, width / 2 - 100, (height / 4 - 10) + 50 + 18 + 20 + 4, 200, 20, getShowIpLabel()));
         buttonSave.enabled = false;
     }
 
@@ -57,13 +55,13 @@ public class GuiAddServer extends GuiScreen
     }
 
     @Override
-	public void onClosed()
+	public void removed()
     {
         Keyboard.enableRepeatEvents(false);
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
         if(!button.enabled)
         {
@@ -71,7 +69,7 @@ public class GuiAddServer extends GuiScreen
         }
         if(button.id == 1)
         {
-            mc.displayGuiScreen(parentScreen);
+            mc.displayScreen(parentScreen);
         }
         else if(button.id == 0)
         {
@@ -83,7 +81,7 @@ public class GuiAddServer extends GuiScreen
             serverList.servers.add(new ServerData(serverName, ipText, showIp));
             serverList.writeToFile();
 
-            mc.displayGuiScreen(parentScreen);
+            mc.displayScreen(parentScreen);
         }
         else if (button.id == 2)
         {
@@ -93,10 +91,10 @@ public class GuiAddServer extends GuiScreen
     }
 
     @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
-        if(i != Keyboard.KEY_BACK) super.keyTyped(c, i, mouseX, mouseY);
-        if (i == Keyboard.KEY_TAB)
+        if(eventKey != Keyboard.KEY_BACK) super.keyPressed(eventCharacter, eventKey, mx, my);
+        if (eventKey == Keyboard.KEY_TAB)
         {
             if (!ipTextField.isFocused && !serverNameTextField.isFocused)
             {
@@ -109,43 +107,43 @@ public class GuiAddServer extends GuiScreen
             }
             return;
         }
-        if (i == Keyboard.KEY_RETURN)
+        if (eventKey == Keyboard.KEY_RETURN)
         {
             if (buttonSave.enabled)
             {
-                buttonPressed(buttonSave);
+                buttonClicked(buttonSave);
             }
         }
         if (ipTextField.isFocused)
         {
-            ipTextField.textboxKeyTyped(c, i);
+            ipTextField.textboxKeyTyped(eventCharacter, eventKey);
         }
         if (serverNameTextField.isFocused)
         {
-            serverNameTextField.textboxKeyTyped(c, i);
+            serverNameTextField.textboxKeyTyped(eventCharacter, eventKey);
         }
 
         buttonSave.enabled = ipTextField.getText().length() > 0;
     }
 
     @Override
-	public void mouseClicked(int mouseX, int mouseY, int mouseButton)
+	public void mouseClicked(int mx, int my, int buttonNum)
     {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
-        ipTextField.mouseClicked(mouseX, mouseY, mouseButton);
-        serverNameTextField.mouseClicked(mouseX, mouseY, mouseButton);
+        super.mouseClicked(mx, my, buttonNum);
+        ipTextField.mouseClicked(mx, my, buttonNum);
+        serverNameTextField.mouseClicked(mx, my, buttonNum);
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
         I18n stringtranslate = I18n.getInstance();
-        drawDefaultBackground();
-        drawStringCentered(fontRenderer, stringtranslate.translateKey("gui.add_server.label.title"), width / 2, (height / 4 - 60) + 20, 0xffffff);
-        drawString(fontRenderer, stringtranslate.translateKey("gui.add_server.label.server_name"), serverNameTextField.xPosition, serverNameTextField.yPosition - 14, 0xa0a0a0);
-        drawString(fontRenderer, stringtranslate.translateKey("gui.add_server.label.ip_address"), ipTextField.xPosition, ipTextField.yPosition - 14, 0xa0a0a0);
+        renderBackground();
+        drawStringCentered(font, stringtranslate.translateKey("gui.add_server.label.title"), width / 2, (height / 4 - 60) + 20, 0xffffff);
+        drawString(font, stringtranslate.translateKey("gui.add_server.label.server_name"), serverNameTextField.xPosition, serverNameTextField.yPosition - 14, 0xa0a0a0);
+        drawString(font, stringtranslate.translateKey("gui.add_server.label.ip_address"), ipTextField.xPosition, ipTextField.yPosition - 14, 0xa0a0a0);
         ipTextField.drawTextBox();
         serverNameTextField.drawTextBox();
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/BadJavaArchScreen.java b/src/main/java/net/minecraft/client/gui/BadJavaArchScreen.java
new file mode 100644
index 000000000..e58f226f4
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/BadJavaArchScreen.java
@@ -0,0 +1,72 @@
+package net.minecraft.client.gui;
+
+// Referenced classes of package net.minecraft.src:
+//            GuiScreen, GuiButton, GuiMainMenu
+
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.lang.I18n;
+import org.slf4j.Logger;
+
+import java.awt.*;
+import java.net.URI;
+
+public class BadJavaArchScreen extends Screen
+{
+    private static final Logger LOGGER = LogUtils.getLogger();
+
+    public BadJavaArchScreen()
+    {
+    }
+
+    @Override
+	public void init()
+    {
+        I18n i = I18n.getInstance();
+        buttons.clear();
+        String downloadString = i.translateKey("gui.bad_java_arch.button.download");
+        buttons.add(new ButtonElement(0, width / 2 - 100, height / 4 + 120 + 12, i.translateKey("gui.bad_java_arch.button.continue")));
+        buttons.add(new ClickableLabelElement(1, width / 2 - 170 - font.getStringWidth(downloadString) / 2, (height / 4 - 60) + 60 + 64, downloadString, 0x7C99EA));
+    }
+
+    @Override
+	protected void buttonClicked(ButtonElement button)
+    {
+        if(!button.enabled)
+        {
+            return;
+        }
+        if(button.id == 0)
+        {
+            mc.displayScreen(new MainMenuScreen());
+        }
+        Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
+        if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE))
+        {
+            if (button.id == 1)
+            {
+                try
+                {
+                    desktop.browse(URI.create("https://adoptium.net/en-GB/temurin/releases/?version=8"));
+                }
+                catch (Exception e)
+                {
+                    LOGGER.error("Exception occurred when attempting to open URL 'https://adoptium.net/en-GB/temurin/releases/?version=8'!", e);
+                }
+            }
+        }
+    }
+
+    @Override
+	public void render(int xm, int ym, float partialTick)
+    {
+        I18n i = I18n.getInstance();
+        renderBackground();
+        drawStringCentered(font, i.translateKey("gui.bad_java_arch.label.title"), width / 2, (height / 4 - 60) + 20, 0xffffff);
+        drawString(font, i.translateKey("gui.bad_java_arch.label.body.1"), width / 2 - 170, (height / 4 - 60) + 60 + 0, 0xa0a0a0);
+        drawString(font, i.translateKey("gui.bad_java_arch.label.body.2"), width / 2 - 170, (height / 4 - 60) + 60 + 18, 0xa0a0a0);
+        drawString(font, i.translateKey("gui.bad_java_arch.label.body.3"), width / 2 - 170, (height / 4 - 60) + 60 + 27, 0xa0a0a0);
+        drawString(font, i.translateKey("gui.bad_java_arch.label.body.4"), width / 2 - 170, (height / 4 - 60) + 60 + 45, 0xa0a0a0);
+        super.render(xm, ym, partialTick);
+    }
+
+}
diff --git a/src/main/java/net/minecraft/client/gui/BlankScreen.java b/src/main/java/net/minecraft/client/gui/BlankScreen.java
new file mode 100644
index 000000000..ba5337189
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/BlankScreen.java
@@ -0,0 +1,9 @@
+package net.minecraft.client.gui;
+
+public class BlankScreen extends Screen
+{
+    @Override
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
+    {
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/GuiButton.java b/src/main/java/net/minecraft/client/gui/ButtonElement.java
similarity index 86%
rename from src/main/java/net/minecraft/client/gui/GuiButton.java
rename to src/main/java/net/minecraft/client/gui/ButtonElement.java
index 971d65a90..0230f3e2c 100644
--- a/src/main/java/net/minecraft/client/gui/GuiButton.java
+++ b/src/main/java/net/minecraft/client/gui/ButtonElement.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import org.lwjgl.opengl.GL11;
@@ -11,7 +11,7 @@ import net.minecraft.core.util.helper.Listener;
 // Referenced classes of package net.minecraft.src:
 //            Gui, RenderEngine
 
-public class GuiButton extends Gui implements GuiElement
+public class ButtonElement extends Gui implements GuiElement
 {
     public static final int STATE_DISABLED = 0;
     public static final int STATE_DEFAULT = 1;
@@ -29,14 +29,14 @@ public class GuiButton extends Gui implements GuiElement
     public boolean enabled;
     public boolean visible;
     public boolean playSound = true;
-    public Listener<GuiButton> listener;
+    public Listener<ButtonElement> listener;
 
-    public GuiButton(int id, int xPosition, int yPosition, String text)
+    public ButtonElement(int id, int xPosition, int yPosition, String text)
     {
         this(id, xPosition, yPosition, 200, 20, text);
     }
 
-    public GuiButton(int id, int xPosition, int yPosition, int width, int height, String text)
+    public ButtonElement(int id, int xPosition, int yPosition, int width, int height, String text)
     {
         enabled = true;
         visible = true;
@@ -48,7 +48,7 @@ public class GuiButton extends Gui implements GuiElement
         displayString = text;
     }
 
-    public GuiButton setTextures(String defaultTexture, String hoveredTexture, String disabledTexture) {
+    public ButtonElement setTextures(String defaultTexture, String hoveredTexture, String disabledTexture) {
         this.defaultTexture = TextureRegistry.getTexture(defaultTexture);
         this.hoveredTexture = TextureRegistry.getTexture(hoveredTexture);
         this.disabledTexture = TextureRegistry.getTexture(disabledTexture);
@@ -73,7 +73,7 @@ public class GuiButton extends Gui implements GuiElement
     {
         if (!visible) return;
 
-        FontRenderer fontrenderer = mc.fontRenderer;
+        Font font = mc.font;
         boolean mouseOver = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height;
         int state = getButtonState(mouseOver);
 
@@ -106,7 +106,7 @@ public class GuiButton extends Gui implements GuiElement
                 textColor = 0xFFFFA0;
                 break;
         }
-        drawStringCentered(fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, textColor);
+        drawStringCentered(font, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, textColor);
     }
 
     public boolean isHovered(int mouseX, int mouseY)
@@ -127,7 +127,7 @@ public class GuiButton extends Gui implements GuiElement
         return enabled && mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height;
     }
     
-    public GuiButton setListener(Listener<GuiButton> listener) {
+    public ButtonElement setListener(Listener<ButtonElement> listener) {
     	this.listener = listener;
     	return this;
     }
diff --git a/src/main/java/net/minecraft/client/gui/GuiChatEmotePicker.java b/src/main/java/net/minecraft/client/gui/ChatEmotePickerElement.java
similarity index 92%
rename from src/main/java/net/minecraft/client/gui/GuiChatEmotePicker.java
rename to src/main/java/net/minecraft/client/gui/ChatEmotePickerElement.java
index cfa9db3b0..69cecf1cc 100644
--- a/src/main/java/net/minecraft/client/gui/GuiChatEmotePicker.java
+++ b/src/main/java/net/minecraft/client/gui/ChatEmotePickerElement.java
@@ -7,13 +7,12 @@ import net.minecraft.core.net.ChatEmotes;
 
 import java.util.Map;
 
-public class GuiChatEmotePicker
-    extends Gui {
+public class ChatEmotePickerElement extends Gui {
     private static final int CELL_WIDTH = 16;
     private static final int CELL_HEIGHT = 16;
 
     private final Minecraft mc;
-    private final GuiChat parent;
+    private final ChatScreen parent;
 
     private final int width;
     private final int height;
@@ -26,7 +25,7 @@ public class GuiChatEmotePicker
 
     private int scroll = 0;
 
-    public GuiChatEmotePicker(Minecraft mc, GuiChat parent, int xCells, int yCells) {
+    public ChatEmotePickerElement(Minecraft mc, ChatScreen parent, int xCells, int yCells) {
         this.mc = mc;
         this.parent = parent;
 
@@ -125,6 +124,6 @@ public class GuiChatEmotePicker
             color = 0xffffffa0;
         }
 
-        drawStringCentered(mc.fontRenderer, String.valueOf(c), x + CELL_WIDTH / 2, y + (CELL_HEIGHT / 2 - 4), color);
+        drawStringCentered(mc.font, String.valueOf(c), x + CELL_WIDTH / 2, y + (CELL_HEIGHT / 2 - 4), color);
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/GuiChat.java b/src/main/java/net/minecraft/client/gui/ChatScreen.java
similarity index 63%
rename from src/main/java/net/minecraft/client/gui/GuiChat.java
rename to src/main/java/net/minecraft/client/gui/ChatScreen.java
index 5a17db6d0..51462267d 100644
--- a/src/main/java/net/minecraft/client/gui/GuiChat.java
+++ b/src/main/java/net/minecraft/client/gui/ChatScreen.java
@@ -8,21 +8,21 @@ import org.lwjgl.input.Keyboard;
 import net.minecraft.client.gui.text.ITextField;
 import org.lwjgl.input.Mouse;
 
-public class GuiChat extends GuiScreen implements ITextField {
+public class ChatScreen extends Screen implements ITextField {
 
 	protected String message;
 	private int currentIndex = 0;
 	private String originalMessage;
 	private int updateCounter;
 	private final TextFieldEditor editor;
-	protected GuiChatEmotePicker emotePicker;
+	protected ChatEmotePickerElement emotePicker;
 	protected boolean showEmotePicker = false;
 
-	public GuiChat() {
+	public ChatScreen() {
 		this("");
 	}
 
-	public GuiChat(String initialMessage) {
+	public ChatScreen(String initialMessage) {
 		message = initialMessage;
 		updateCounter = 0;
 		editor = new TextFieldEditor(this);
@@ -33,14 +33,14 @@ public class GuiChat extends GuiScreen implements ITextField {
 	public void init() {
 		Keyboard.enableRepeatEvents(true);
 		int emotePickerYCells = (int)MathHelper.clamp(Math.ceil(ChatEmotes.getEmotes().size() / 5.0), 0, 4);
-		emotePicker = new GuiChatEmotePicker(mc, this, 5, emotePickerYCells);
+		emotePicker = new ChatEmotePickerElement(mc, this, 5, emotePickerYCells);
 		showEmotePicker = false;
 	}
 
 	@Override
-	public void onClosed() {
+	public void removed() {
 		Keyboard.enableRepeatEvents(false);
-		mc.ingameGUI.chatScroll = 0;
+		mc.ingameHud.chatScroll = 0;
 	}
 
 	@Override
@@ -53,14 +53,14 @@ public class GuiChat extends GuiScreen implements ITextField {
 			if (showEmotePicker) {
 				emotePicker.scrollOffset((int)(-dWheel / 0.1f));
 			} else {
-				mc.ingameGUI.chatScroll += dWheel / 1;
+				mc.ingameHud.chatScroll += dWheel / 1;
 			}
 		}
 	}
 
 	@Override
-	public void keyTyped(char c, int key, int mouseX, int mouseY) {
-		if (key == Keyboard.KEY_UP && mc.thePlayer.messageHistory.size() > 0) {
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
+		if (eventKey == Keyboard.KEY_UP && mc.thePlayer.messageHistory.size() > 0) {
 			if (currentIndex == 0)
 			{
 				originalMessage = getText();
@@ -74,7 +74,7 @@ public class GuiChat extends GuiScreen implements ITextField {
 			editor.setCursor(10000);
 			return;
 		}
-		if (key == Keyboard.KEY_DOWN && currentIndex > 0)
+		if (eventKey == Keyboard.KEY_DOWN && currentIndex > 0)
 		{
 			if (currentIndex-1 == 0)
 			{
@@ -92,67 +92,67 @@ public class GuiChat extends GuiScreen implements ITextField {
 			editor.setCursor(10000);
 			return;
 		}
-		if (key == Keyboard.KEY_ESCAPE && !(this instanceof GuiSleepMP)) {
-			mc.displayGuiScreen(null);
+		if (eventKey == Keyboard.KEY_ESCAPE && !(this instanceof SleepScreenMP)) {
+			mc.displayScreen(null);
 			return;
 		}
-		if (key == Keyboard.KEY_RETURN) {
+		if (eventKey == Keyboard.KEY_RETURN) {
 			String s = message.trim();
 			if (s.length() > 0) {
 				String s1 = message.trim();
 				mc.thePlayer.sendChatMessage(s1);
 			}
-			mc.displayGuiScreen(null);
+			mc.displayScreen(null);
 			return;
 		}
-		editor.handleInput(key, c);
+		editor.handleInput(eventKey, eventCharacter);
 	}
 
 	@Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick) {
+	public void render(int xm, int ym, float partialTick) {
 		// Draw emote picker button
 		int emotePickerButtonColor = 0x80000000;
 		int emotePickerTextColor = 0xE0E0E0;
-		if (mouseX >= 2 && mouseX < 14 && mouseY >= height - 14 && mouseY < height - 2)
+		if (xm >= 2 && xm < 14 && ym >= height - 14 && ym < height - 2)
 		{
 			emotePickerButtonColor = 0x80ffffff;
 			emotePickerTextColor = 0xffffffa0;
 		}
 		drawRect(2, height - 14, 14, height - 2, emotePickerButtonColor);
-		drawStringCentered(fontRenderer, Character.toString('\u263a'), 2 + 6, height - 12, emotePickerTextColor);
+		drawStringCentered(font, Character.toString('\u263a'), 2 + 6, height - 12, emotePickerTextColor);
 
 		drawRect(16, height - 14, width - 2, height - 2, 0x80000000);
 
 		boolean drawCursor = (updateCounter / 6) % 2 == 0;
 		int cursor = editor.getCursor();
-		drawString(fontRenderer, message, 18, height - 12, 0xE0E0E0);
+		drawString(font, message, 18, height - 12, 0xE0E0E0);
 		if (drawCursor)
 		{
-			int width = fontRenderer.getStringWidth(message);
+			int width = font.getStringWidth(message);
 			if (cursor < message.length())
 			{
-				width = fontRenderer.getStringWidth(message.substring(0, cursor));
+				width = font.getStringWidth(message.substring(0, cursor));
 			}
-			drawString(fontRenderer, "_", 18 + width, height - 12, 0xE0E0E0);
+			drawString(font, "_", 18 + width, height - 12, 0xE0E0E0);
 		}
 
 		if (showEmotePicker) {
-			emotePicker.draw(2, height - 16 - emotePicker.getHeight(), mouseX, mouseY);
+			emotePicker.draw(2, height - 16 - emotePicker.getHeight(), xm, ym);
 		}
 
-		super.drawScreen(mouseX, mouseY, partialTick);
+		super.render(xm, ym, partialTick);
 	}
 
 	@Override
-	public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
-		super.mouseClicked(mouseX, mouseY, mouseButton);
-		if (mouseButton == 0) {
-			if (mouseX >= 2 && mouseX < 14 && mouseY >= height - 14 && mouseY < height - 2) {
+	public void mouseClicked(int mx, int my, int buttonNum) {
+		super.mouseClicked(mx, my, buttonNum);
+		if (buttonNum == 0) {
+			if (mx >= 2 && mx < 14 && my >= height - 14 && my < height - 2) {
 				showEmotePicker = !showEmotePicker;
 				return;
 			}
 			if (showEmotePicker) {
-				Character c = emotePicker.click(mouseX - 2, mouseY - (height - 16 - emotePicker.getHeight()));
+				Character c = emotePicker.click(mx - 2, my - (height - 16 - emotePicker.getHeight()));
 				if (c != null) {
 					editor.handleInput(0, c);
 					if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) showEmotePicker = false;
diff --git a/src/main/java/net/minecraft/client/gui/ClickableLabelElement.java b/src/main/java/net/minecraft/client/gui/ClickableLabelElement.java
new file mode 100644
index 000000000..d634da271
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/ClickableLabelElement.java
@@ -0,0 +1,71 @@
+package net.minecraft.client.gui;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.render.Font;
+import org.lwjgl.opengl.GL11;
+
+public class ClickableLabelElement extends ButtonElement
+{
+    private int textColor;
+    private int bgColor;
+    private boolean shadow = true;
+
+    public ClickableLabelElement(int id, int xPosition, int yPosition, String s, int textColor, int bgColor)
+    {
+        super(id, xPosition, yPosition, s);
+        this.textColor = textColor;
+        this.bgColor = bgColor;
+        height = 12;
+        width = 0;
+    }
+
+    public ClickableLabelElement(int id, int xPosition, int yPosition, String s, int textColor)
+    {
+        this(id, xPosition, yPosition, s, textColor, 0x7F000000);
+    }
+
+    public int getTextColor() {
+        return textColor;
+    }
+
+    public void setTextColor(int textColor) {
+        this.textColor = textColor;
+    }
+
+    public int getBgColor() {
+        return bgColor;
+    }
+
+    public void setBgColor(int bgColor) {
+        this.bgColor = bgColor;
+    }
+
+    public boolean isShadow() {
+        return shadow;
+    }
+
+    public void setShadow(boolean shadow) {
+        this.shadow = shadow;
+    }
+
+    @Override
+    public void drawButton(Minecraft mc, int mouseX, int mouseY)
+    {
+        if(!visible)
+        {
+            return;
+        }
+        Font font = mc.font;
+        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+        boolean hovered = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height;
+        width = font.getStringWidth(displayString) + 4;
+        drawRect(xPosition, yPosition, xPosition + width, yPosition + height, enabled ? (hovered ? 0x7F8080C0 : bgColor) : 0x00000000);
+        if (enabled && (shadow || hovered)) {
+            font.drawStringWithShadow(displayString, xPosition + 2, yPosition + 2, hovered ? 0xFFFFA0 : textColor);
+        } else {
+            font.drawString(displayString, xPosition + 2, yPosition + 2, 0x7F7F7F);
+        }
+        mouseDragged(mc, mouseX, mouseY);
+    }
+
+}
diff --git a/src/main/java/net/minecraft/client/gui/ConflictWarningScreen.java b/src/main/java/net/minecraft/client/gui/ConflictWarningScreen.java
new file mode 100644
index 000000000..016739dda
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/ConflictWarningScreen.java
@@ -0,0 +1,47 @@
+package net.minecraft.client.gui;
+
+// Referenced classes of package net.minecraft.src:
+//            GuiScreen, GuiButton, GuiMainMenu
+
+import net.minecraft.core.lang.I18n;
+
+public class ConflictWarningScreen extends Screen
+{
+
+    public ConflictWarningScreen()
+    {
+    }
+
+    @Override
+	public void init()
+    {
+        buttons.clear();
+        buttons.add(new ButtonElement(0, width / 2 - 100, height / 4 + 120 + 12, I18n.getInstance().translateKey("gui.conflict_warning.button.back")));
+    }
+
+    @Override
+	protected void buttonClicked(ButtonElement button)
+    {
+        if(!button.enabled)
+        {
+            return;
+        }
+        if(button.id == 0)
+        {
+            mc.displayScreen(new MainMenuScreen());
+        }
+    }
+
+    @Override
+	public void render(int xm, int ym, float partialTick)
+    {
+        I18n i = I18n.getInstance();
+        renderBackground();
+        drawStringCentered(font, i.translateKey("gui.conflict_warning.label.title"), width / 2, (height / 4 - 60) + 20, 0xffffff);
+        drawString(font, i.translateKey("gui.conflict_warning.label.body.1"), width / 2 - 140, (height / 4 - 60) + 60 + 0, 0xa0a0a0);
+        drawString(font, i.translateKey("gui.conflict_warning.label.body.2"), width / 2 - 140, (height / 4 - 60) + 60 + 18, 0xa0a0a0);
+        drawString(font, i.translateKey("gui.conflict_warning.label.body.3"), width / 2 - 140, (height / 4 - 60) + 60 + 27, 0xa0a0a0);
+        drawString(font, i.translateKey("gui.conflict_warning.label.body.4"), width / 2 - 140, (height / 4 - 60) + 60 + 45, 0xa0a0a0);
+        super.render(xm, ym, partialTick);
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/GuiConnectFailed.java b/src/main/java/net/minecraft/client/gui/ConnectFailedScreen.java
similarity index 63%
rename from src/main/java/net/minecraft/client/gui/GuiConnectFailed.java
rename to src/main/java/net/minecraft/client/gui/ConnectFailedScreen.java
index 94d6f7c1b..31b388655 100644
--- a/src/main/java/net/minecraft/client/gui/GuiConnectFailed.java
+++ b/src/main/java/net/minecraft/client/gui/ConnectFailedScreen.java
@@ -7,10 +7,10 @@ import net.minecraft.client.Minecraft;
 
 import net.minecraft.core.lang.I18n;
 
-public class GuiConnectFailed extends GuiScreen
+public class ConnectFailedScreen extends Screen
 {
 
-	public GuiConnectFailed(String s, String s1, Object aobj[]) {
+	public ConnectFailedScreen(String s, String s1, Object aobj[]) {
 		I18n stringtranslate = I18n.getInstance();
 		this.errorMessage = stringtranslate.translateKey(s);
 		
@@ -35,7 +35,7 @@ public class GuiConnectFailed extends GuiScreen
     }
 
     @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
     }
 
@@ -43,26 +43,26 @@ public class GuiConnectFailed extends GuiScreen
 	public void init()
     {
         I18n stringtranslate = I18n.getInstance();
-        controlList.clear();
-        controlList.add(new GuiButton(0, width / 2 - 100, height / 4 + 120 + 12, stringtranslate.translateKey("gui.connect_failed.button.back")));
+        buttons.clear();
+        buttons.add(new ButtonElement(0, width / 2 - 100, height / 4 + 120 + 12, stringtranslate.translateKey("gui.connect_failed.button.back")));
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
         if(button.id == 0)
         {
-            mc.displayGuiScreen(new GuiMainMenu());
+            mc.displayScreen(new MainMenuScreen());
         }
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
-        drawDefaultBackground();
-        drawStringCentered(fontRenderer, errorMessage, width / 2, height / 2 - 50, 0xffffff);
-        drawStringCentered(fontRenderer, errorDetail, width / 2, height / 2 - 10, 0xffffff);
-        super.drawScreen(mouseX, mouseY, partialTick);
+        renderBackground();
+        drawStringCentered(font, errorMessage, width / 2, height / 2 - 50, 0xffffff);
+        drawStringCentered(font, errorDetail, width / 2, height / 2 - 10, 0xffffff);
+        super.render(xm, ym, partialTick);
     }
 
     private String errorMessage;
diff --git a/src/main/java/net/minecraft/client/gui/ConnectToIpScreen.java b/src/main/java/net/minecraft/client/gui/ConnectToIpScreen.java
new file mode 100644
index 000000000..88b74b202
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/ConnectToIpScreen.java
@@ -0,0 +1,98 @@
+package net.minecraft.client.gui;
+
+import net.minecraft.core.lang.I18n;
+import net.minecraft.core.net.ServerAddress;
+import org.lwjgl.input.Keyboard;
+
+// Referenced classes of package net.minecraft.src:
+//            GuiScreen, GuiTextField, StringTranslate, GuiButton, 
+//            gGameSettings, GuiConnecting
+
+public class ConnectToIpScreen extends Screen
+{
+
+    public ConnectToIpScreen(Screen parent)
+    {
+        super(parent);
+    }
+
+    @Override
+	public void tick()
+    {
+        textField.updateCursorCounter();
+    }
+
+    @Override
+	public void init()
+    {
+        I18n stringtranslate = I18n.getInstance();
+        Keyboard.enableRepeatEvents(true);
+        buttons.clear();
+        buttons.add(new ButtonElement(0, width / 2 - 100, height / 4 + 96 + 12, stringtranslate.translateKey("gui.connect_to_ip.button.connect")));
+        buttons.add(new ButtonElement(1, width / 2 - 100, height / 4 + 120 + 12, stringtranslate.translateKey("gui.connect_to_ip.button.cancel")));
+        String s = mc.gameSettings.lastServer.value.replaceAll("_", ":");
+        buttons.get(0).enabled = s.length() > 0;
+        textField = new TextFieldElement(this, font, width / 2 - 100, (height / 4 - 10) + 50 + 18, 200, 20, s, "");
+        textField.isFocused = true;
+        textField.setMaxStringLength(128);
+    }
+
+    @Override
+	public void removed()
+    {
+        Keyboard.enableRepeatEvents(false);
+    }
+
+    @Override
+	protected void buttonClicked(ButtonElement button)
+    {
+        if(!button.enabled)
+        {
+            return;
+        }
+        if(button.id == 1)
+        {
+            mc.displayScreen(parentScreen);
+        } else
+        if(button.id == 0)
+        {
+            String serverUrl = textField.getText().trim();
+            mc.gameSettings.lastServer.value = serverUrl.replaceAll(":", "_");
+            mc.gameSettings.saveOptions();
+            ServerAddress address = ServerAddress.resolveServerIP(serverUrl);
+            mc.displayScreen(new ConnectingScreen(mc, address.getIP(), address.getPort()));
+        }
+    }
+
+    @Override
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
+    {
+        if(eventKey != Keyboard.KEY_BACK) super.keyPressed(eventCharacter, eventKey, mx, my);
+        textField.textboxKeyTyped(eventCharacter, eventKey);
+        if(eventCharacter == '\r')
+        {
+            buttonClicked((ButtonElement) buttons.get(0));
+        }
+        ((ButtonElement) buttons.get(0)).enabled = textField.getText().length() > 0;
+    }
+
+    @Override
+	public void mouseClicked(int mx, int my, int buttonNum)
+    {
+        super.mouseClicked(mx, my, buttonNum);
+        textField.mouseClicked(mx, my, buttonNum);
+    }
+
+    @Override
+	public void render(int xm, int ym, float partialTick)
+    {
+        I18n i18n = I18n.getInstance();
+        renderBackground();
+        drawStringCentered(font, i18n.translateKey("gui.connect_to_ip.label.title"), width / 2, (height / 4 - 60) + 20, 0xffffff);
+        drawString(font, i18n.translateKey("gui.connect_to_ip.label.enter_ip"), width / 2 - 140, (height / 4 - 60) + 60 + 36, 0xa0a0a0);
+        textField.drawTextBox();
+        super.render(xm, ym, partialTick);
+    }
+
+    private TextFieldElement textField;
+}
diff --git a/src/main/java/net/minecraft/client/gui/GuiConnecting.java b/src/main/java/net/minecraft/client/gui/ConnectingScreen.java
similarity index 63%
rename from src/main/java/net/minecraft/client/gui/GuiConnecting.java
rename to src/main/java/net/minecraft/client/gui/ConnectingScreen.java
index 1a5263144..b0752f6dd 100644
--- a/src/main/java/net/minecraft/client/gui/GuiConnecting.java
+++ b/src/main/java/net/minecraft/client/gui/ConnectingScreen.java
@@ -1,9 +1,11 @@
 package net.minecraft.client.gui;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.net.handler.ClientPacketHandler;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.net.packet.PreLoginPacket;
+import org.slf4j.Logger;
 
 import java.net.ConnectException;
 import java.net.UnknownHostException;
@@ -12,13 +14,14 @@ import java.net.UnknownHostException;
 //            GuiScreen, ThreadConnectToServer, ClientPacketHandler, StringTranslate,
 //            GuiButton, GuiMainMenu
 
-public class GuiConnecting extends GuiScreen
+public class ConnectingScreen extends Screen
 {
-
-    public GuiConnecting(Minecraft minecraft, String hostName, int port)
+    private static final Logger LOGGER = LogUtils.getLogger();
+    public ConnectingScreen(Minecraft minecraft, String hostName, int port)
     {
+        mc = minecraft;
         cancelled = false;
-        System.out.println("Connecting to " + hostName + ", " + port);
+        LOGGER.info("Connecting to {}, {}", hostName, port);
         minecraft.changeWorld(null);
         new Thread(() -> {
             try
@@ -36,7 +39,7 @@ public class GuiConnecting extends GuiScreen
                 {
                     return;
                 }
-                mc.displayGuiScreen(new GuiConnectFailed("connect.failed", "disconnect.genericReason", new Object[] {
+                mc.displayScreen(new ConnectFailedScreen("connect.failed", "disconnect.genericReason", new Object[] {
                     "Unknown host '" + hostName + "'"
                 }));
             }
@@ -46,7 +49,7 @@ public class GuiConnecting extends GuiScreen
                 {
                     return;
                 }
-                mc.displayGuiScreen(new GuiConnectFailed("connect.failed", "disconnect.genericReason", new Object[] {
+                mc.displayScreen(new ConnectFailedScreen("connect.failed", "disconnect.genericReason", new Object[] {
                     connectexception.getMessage()
                 }));
             }
@@ -56,8 +59,8 @@ public class GuiConnecting extends GuiScreen
                 {
                     return;
                 }
-                exception.printStackTrace();
-                mc.displayGuiScreen(new GuiConnectFailed("connect.failed", "disconnect.genericReason", new Object[] {
+                LOGGER.error("Unexpected Exception when trying to join server!", exception);
+                mc.displayScreen(new ConnectFailedScreen("connect.failed", "disconnect.genericReason", new Object[] {
                     exception.toString()
                 }));
             }
@@ -75,7 +78,7 @@ public class GuiConnecting extends GuiScreen
     }
 
     @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
     }
 
@@ -83,12 +86,12 @@ public class GuiConnecting extends GuiScreen
 	public void init()
     {
         I18n stringtranslate = I18n.getInstance();
-        controlList.clear();
-        controlList.add(new GuiButton(0, width / 2 - 100, height / 4 + 120 + 12, stringtranslate.translateKey("gui.connecting.button.cancel")));
+        buttons.clear();
+        buttons.add(new ButtonElement(0, width / 2 - 100, height / 4 + 120 + 12, stringtranslate.translateKey("gui.connecting.button.cancel")));
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
         if(button.id == 0)
         {
@@ -97,25 +100,25 @@ public class GuiConnecting extends GuiScreen
             {
                 clientHandler.disconnect();
             }
-            mc.displayGuiScreen(new GuiSelectServer(new GuiMainMenu()));
+            mc.displayScreen(new SelectServerScreen(new MainMenuScreen()));
         }
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
-        drawDefaultBackground();
+        renderBackground();
         I18n stringtranslate = I18n.getInstance();
         if(clientHandler == null)
         {
-            drawStringCentered(fontRenderer, stringtranslate.translateKey("gui.connecting.label.connecting"), width / 2, height / 2 - 50, 0xffffff);
-            drawStringCentered(fontRenderer, "", width / 2, height / 2 - 10, 0xffffff);
+            drawStringCentered(font, stringtranslate.translateKey("gui.connecting.label.connecting"), width / 2, height / 2 - 50, 0xffffff);
+            drawStringCentered(font, "", width / 2, height / 2 - 10, 0xffffff);
         } else
         {
-            drawStringCentered(fontRenderer, stringtranslate.translateKey("gui.connecting.label.logging_in"), width / 2, height / 2 - 50, 0xffffff);
-            drawStringCentered(fontRenderer, clientHandler.message, width / 2, height / 2 - 10, 0xffffff);
+            drawStringCentered(font, stringtranslate.translateKey("gui.connecting.label.logging_in"), width / 2, height / 2 - 50, 0xffffff);
+            drawStringCentered(font, clientHandler.message, width / 2, height / 2 - 10, 0xffffff);
         }
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
     }
 
     private ClientPacketHandler clientHandler;
diff --git a/src/main/java/net/minecraft/client/gui/ControllerGlyphRenderer.java b/src/main/java/net/minecraft/client/gui/ControllerGlyphElement.java
similarity index 92%
rename from src/main/java/net/minecraft/client/gui/ControllerGlyphRenderer.java
rename to src/main/java/net/minecraft/client/gui/ControllerGlyphElement.java
index a6f630e3d..636f9046e 100644
--- a/src/main/java/net/minecraft/client/gui/ControllerGlyphRenderer.java
+++ b/src/main/java/net/minecraft/client/gui/ControllerGlyphElement.java
@@ -4,10 +4,10 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.client.input.controller.Button;
 import net.minecraft.client.input.controller.ControllerInput;
 
-public class ControllerGlyphRenderer extends Gui {
+public class ControllerGlyphElement extends Gui {
     private final Minecraft minecraft;
 
-    public ControllerGlyphRenderer(Minecraft minecraft) {
+    public ControllerGlyphElement(Minecraft minecraft) {
         this.minecraft = minecraft;
     }
 
@@ -22,7 +22,7 @@ public class ControllerGlyphRenderer extends Gui {
         }
 
 
-        minecraft.renderEngine.loadTexture("/assets/minecraft/textures/gui/controller/" + controller.getType().getAssetName() + ".png").bind();
+        minecraft.textureManager.loadTexture("/assets/minecraft/textures/gui/controller/" + controller.getType().getAssetName() + ".png").bind();
 
         drawTexturedModalRect(x, y, u, v + vOffset, sizeU, sizeV);
     }
@@ -33,7 +33,7 @@ public class ControllerGlyphRenderer extends Gui {
         int sizeU = 46;
         int sizeV = 46;
 
-        minecraft.renderEngine.loadTexture("/assets/minecraft/textures/gui/controller/" + controllerInput.getType().getAssetName() + ".png").bind();
+        minecraft.textureManager.loadTexture("/assets/minecraft/textures/gui/controller/" + controllerInput.getType().getAssetName() + ".png").bind();
 
         drawTexturedModalRect(x, y, u, v, sizeU, sizeV);
 
diff --git a/src/main/java/net/minecraft/client/gui/GuiControllerSetup.java b/src/main/java/net/minecraft/client/gui/ControllerSetupScreen.java
similarity index 87%
rename from src/main/java/net/minecraft/client/gui/GuiControllerSetup.java
rename to src/main/java/net/minecraft/client/gui/ControllerSetupScreen.java
index 0f0b320b0..23279b1f1 100644
--- a/src/main/java/net/minecraft/client/gui/GuiControllerSetup.java
+++ b/src/main/java/net/minecraft/client/gui/ControllerSetupScreen.java
@@ -12,28 +12,28 @@ import java.util.Arrays;
 
 import static org.lwjgl.opengl.GL11.*;
 
-public class GuiControllerSetup extends GuiScreen {
+public class ControllerSetupScreen extends Screen {
     private ControllerInput lastController = null;
-    private GuiButton controllerButton;
-    private ControllerGlyphRenderer glyphRenderer;
+    private ButtonElement controllerButton;
+    private ControllerGlyphElement glyphRenderer;
 
-    public GuiControllerSetup(GuiScreen parentScreen) {
+    public ControllerSetupScreen(Screen parentScreen) {
         super(parentScreen);
     }
 
     @Override
     public void init() {
-        controllerButton = new GuiButton(0, 0, 0, "");
+        controllerButton = new ButtonElement(0, 0, 0, "");
         controllerButton.xPosition = width / 2 - 100;
         controllerButton.yPosition = 16;
         controllerButton.width = 200;
         controllerButton.height = 20;
 
-        controlList.add(controllerButton);
+        buttons.add(controllerButton);
 
-        controlList.add(new GuiButton(-1, width / 2 - 100, height - 40, I18n.getInstance().translateKey("gui.controller_setup.button.back")).setListener((e) -> mc.displayGuiScreen(parentScreen)));
+        buttons.add(new ButtonElement(-1, width / 2 - 100, height - 40, I18n.getInstance().translateKey("gui.controller_setup.button.back")).setListener((e) -> mc.displayScreen(parentScreen)));
 
-        this.glyphRenderer = new ControllerGlyphRenderer(mc);
+        this.glyphRenderer = new ControllerGlyphElement(mc);
 
         updateDisplay();
     }
@@ -48,9 +48,9 @@ public class GuiControllerSetup extends GuiScreen {
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick) {
-        drawDefaultBackground();
-        super.drawScreen(mouseX, mouseY, partialTick);
+    public void render(int xm, int ym, float partialTick) {
+        renderBackground();
+        super.render(xm, ym, partialTick);
 
         ControllerInput controller = mc.controllerInput;
 
@@ -71,7 +71,7 @@ public class GuiControllerSetup extends GuiScreen {
             drawJoystick(controller.joyRight, x1 - 48 + 64, y + 96);
 
             GL11.glEnable(GL_TEXTURE_2D);
-            fontRenderer.drawCenteredString("(" + controller.getType().getPrintableName() + ")", width / 2, 40, 0xFFFFFF);
+            font.drawCenteredString("(" + controller.getType().getPrintableName() + ")", width / 2, 40, 0xFFFFFF);
 
             int w = glyphRenderer.getButtonSizeU(controller, controller.buttonLeftTrigger);
             glyphRenderer.drawButton(controller, controller.buttonLeftTrigger, x1 - 65 - w, y, controller.buttonLeftTrigger.isPressed());
@@ -106,7 +106,7 @@ public class GuiControllerSetup extends GuiScreen {
     }
 
     @Override
-    public void keyTyped(char c, int i, int mouseX, int mouseY) {
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
 
     }
 
@@ -132,8 +132,8 @@ public class GuiControllerSetup extends GuiScreen {
     }
 
     @Override
-    protected void buttonPressed(GuiButton button) {
-        super.buttonPressed(button);
+    protected void buttonClicked(ButtonElement button) {
+        super.buttonClicked(button);
 
         if (button.id == 0) {
             int index;
@@ -162,7 +162,7 @@ public class GuiControllerSetup extends GuiScreen {
     }
 
     @Override
-    public void onClosed() {
+    public void removed() {
         if (mc.inputType == InputType.CONTROLLER) {
             mc.mouseInput.grabCursor();
         }
diff --git a/src/main/java/net/minecraft/client/gui/GuiCreateWorld.java b/src/main/java/net/minecraft/client/gui/CreateWorldScreen.java
similarity index 75%
rename from src/main/java/net/minecraft/client/gui/GuiCreateWorld.java
rename to src/main/java/net/minecraft/client/gui/CreateWorldScreen.java
index d247c645f..c7247209f 100644
--- a/src/main/java/net/minecraft/client/gui/GuiCreateWorld.java
+++ b/src/main/java/net/minecraft/client/gui/CreateWorldScreen.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.popup.GuiPopup;
+import net.minecraft.client.gui.popup.PopupScreen;
 import net.minecraft.client.gui.popup.PopupBuilder;
 import net.minecraft.client.player.controller.PlayerControllerSP;
 import net.minecraft.core.data.registry.Registries;
@@ -18,19 +18,19 @@ import org.lwjgl.input.Keyboard;
 import java.util.List;
 import java.util.Random;
 
-public class GuiCreateWorld extends GuiScreen {
+public class CreateWorldScreen extends Screen {
     private int overrideSpawnX;
     private int overrideSpawnY;
     private int overrideSpawnZ;
-    private GuiScreen textField;
-    private GuiTextField textboxWorldName;
-    private GuiTextField textboxSeed;
-    private GuiButton createWorldButton;
-    private GuiButton gamemodeButton;
-    private GuiButton cheatsButton;
-    private GuiButton worldTypeButton;
-    private GuiButton buttonRandomWorldName;
-    private GuiButton buttonRandomSeed;
+    private Screen textField;
+    private TextFieldElement textboxWorldName;
+    private TextFieldElement textboxSeed;
+    private ButtonElement createWorldButton;
+    private ButtonElement gamemodeButton;
+    private ButtonElement cheatsButton;
+    private ButtonElement worldTypeButton;
+    private ButtonElement buttonRandomWorldName;
+    private ButtonElement buttonRandomSeed;
     private String folderName;
     private boolean createClicked;
     private Gamemode selectedGamemode = Gamemode.survival;
@@ -38,7 +38,7 @@ public class GuiCreateWorld extends GuiScreen {
     private WorldTypeGroups.Group worldTypeGroup = WorldTypeGroups.DEFAULT;
     private long seed = (new Random()).nextLong();
 
-    public GuiCreateWorld(GuiScreen guiscreen) {
+    public CreateWorldScreen(Screen guiscreen) {
         textField = guiscreen;
     }
 
@@ -52,21 +52,21 @@ public class GuiCreateWorld extends GuiScreen {
     public void init() {
         I18n i18n = I18n.getInstance();
         Keyboard.enableRepeatEvents(true);
-        controlList.clear();
-        controlList.add(createWorldButton = new GuiButton(0, width / 2 - 100, height / 4 + 104 + 12,
+        buttons.clear();
+        buttons.add(createWorldButton = new ButtonElement(0, width / 2 - 100, height / 4 + 104 + 12,
             i18n.translateKey("gui.create_world.button.create_new_world")));
-        controlList.add(new GuiButton(1, width / 2 - 100, height / 4 + 128 + 12,
+        buttons.add(new ButtonElement(1, width / 2 - 100, height / 4 + 128 + 12,
             i18n.translateKey("gui.create_world.button.cancel")));
-        textboxWorldName = new GuiTextField(this, fontRenderer, width / 2 - 100, 60, 200 - 24, 20,
+        textboxWorldName = new TextFieldElement(this, font, width / 2 - 100, 60, 200 - 24, 20,
             "", i18n.translateKey("gui.create_world.label.new_world"));
         textboxWorldName.setMaxStringLength(32);
-        textboxSeed = new GuiTextField(this, fontRenderer, width / 2 - 100, 100, 200 - 24, 20, "", Long.toString(seed));
-        controlList.add(gamemodeButton = new GuiButton(2, width / 2 - 100, 100 + 20 + 4, 98, 20, ""));
-        controlList.add(cheatsButton = new GuiButton(3, width / 2 - 100 + 102, 100 + 20 + 4, 98, 20, ""));
-        controlList.add(worldTypeButton = new GuiButton(4, width / 2 - 100, 100 + 20 + 20 + 4 + 4, ""));
-        controlList.add(buttonRandomWorldName = new GuiButton(5, width / 2 + 100 - 20, 60, 20, 20, "")
+        textboxSeed = new TextFieldElement(this, font, width / 2 - 100, 100, 200 - 24, 20, "", Long.toString(seed));
+        buttons.add(gamemodeButton = new ButtonElement(2, width / 2 - 100, 100 + 20 + 4, 98, 20, ""));
+        buttons.add(cheatsButton = new ButtonElement(3, width / 2 - 100 + 102, 100 + 20 + 4, 98, 20, ""));
+        buttons.add(worldTypeButton = new ButtonElement(4, width / 2 - 100, 100 + 20 + 20 + 4 + 4, ""));
+        buttons.add(buttonRandomWorldName = new ButtonElement(5, width / 2 + 100 - 20, 60, 20, 20, "")
             .setTextures("minecraft:gui/misc/button_random", "minecraft:gui/misc/button_random_highlighted", "minecraft:gui/misc/button_random"));
-        controlList.add(buttonRandomSeed = new GuiButton(6, width / 2 + 100 - 20, 100, 20, 20, "")
+        buttons.add(buttonRandomSeed = new ButtonElement(6, width / 2 + 100 - 20, 100, 20, 20, "")
             .setTextures("minecraft:gui/misc/button_random", "minecraft:gui/misc/button_random_highlighted", "minecraft:gui/misc/button_random"));
         updateButtons();
         updateFolderName();
@@ -95,19 +95,19 @@ public class GuiCreateWorld extends GuiScreen {
     }
 
     @Override
-    public void onClosed() {
+    public void removed() {
         Keyboard.enableRepeatEvents(false);
     }
 
     @Override
-    protected void buttonPressed(GuiButton button) {
+    protected void buttonClicked(ButtonElement button) {
         if (!button.enabled) {
             return;
         }
         if (button.id == 1) {
-            mc.displayGuiScreen(textField);
+            mc.displayScreen(textField);
         } else if (button.id == 0) {
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
             if (createClicked) {
                 return;
             }
@@ -136,7 +136,7 @@ public class GuiCreateWorld extends GuiScreen {
             }
             if (mc.worldPresetName != null) mc.thePlayer.setPos(overrideSpawnX, overrideSpawnY, overrideSpawnZ);
             mc.theWorld.getLevelData().setCheatsEnabled(cheatsEnabled);
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
         } else if (button == gamemodeButton) {
             I18n i18n = I18n.getInstance();
             List<Gamemode> gamemodeList = Gamemode.getPublicGamemodes();
@@ -157,7 +157,7 @@ public class GuiCreateWorld extends GuiScreen {
                     TextFormatting.GRAY + Registries.WORLD_TYPES.getKey(WorldTypeGroups.GROUPS.get(i).get(Dimension.overworld));
             }
 
-            GuiPopup popup = new PopupBuilder(this, 150)
+            PopupScreen popup = new PopupBuilder(this, 150)
                 .closeOnEsc(0)
                 .closeOnClickOut(0)
                 .withLabel("gui.create_world.label.select_world_type")
@@ -169,7 +169,7 @@ public class GuiCreateWorld extends GuiScreen {
                     }
                 })
                 .build();
-            mc.displayGuiScreen(popup);
+            mc.displayScreen(popup);
         } else if (button == buttonRandomWorldName) {
             textboxWorldName.setText(I18n.getInstance().getCurrentLanguage().getRandomWorldName());
             updateFolderName();
@@ -188,36 +188,36 @@ public class GuiCreateWorld extends GuiScreen {
     }
 
     @Override
-    public void keyTyped(char c, int i, int mouseX, int mouseY) {
-        if (i != Keyboard.KEY_BACK) super.keyTyped(c, i, mouseX, mouseY);
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
+        if (eventKey != Keyboard.KEY_BACK) super.keyPressed(eventCharacter, eventKey, mx, my);
         if (textboxWorldName.isFocused) {
-            textboxWorldName.textboxKeyTyped(c, i);
+            textboxWorldName.textboxKeyTyped(eventCharacter, eventKey);
         } else if (textboxSeed.isFocused) {
-            textboxSeed.textboxKeyTyped(c, i);
+            textboxSeed.textboxKeyTyped(eventCharacter, eventKey);
         }
-        if (c == '\r') {
-            buttonPressed(controlList.get(0));
+        if (eventCharacter == '\r') {
+            buttonClicked(buttons.get(0));
         }
         updateFolderName();
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
-        textboxWorldName.mouseClicked(mouseX, mouseY, mouseButton);
-        textboxSeed.mouseClicked(mouseX, mouseY, mouseButton);
+    public void mouseClicked(int mx, int my, int buttonNum) {
+        super.mouseClicked(mx, my, buttonNum);
+        textboxWorldName.mouseClicked(mx, my, buttonNum);
+        textboxSeed.mouseClicked(mx, my, buttonNum);
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick) {
+    public void render(int xm, int ym, float partialTick) {
         I18n stringtranslate = I18n.getInstance();
-        drawDefaultBackground();
-        drawStringCentered(fontRenderer, stringtranslate.translateKey("gui.create_world.label.title"), width / 2, 20, 0xffffff);
-        drawString(fontRenderer, stringtranslate.translateKey("gui.create_world.label.world_name"), width / 2 - 100, 47, 0xa0a0a0);
-        drawString(fontRenderer, stringtranslate.translateKey("gui.create_world.label.seed"), width / 2 - 100, 88, 0xa0a0a0);
+        renderBackground();
+        drawStringCentered(font, stringtranslate.translateKey("gui.create_world.label.title"), width / 2, 20, 0xffffff);
+        drawString(font, stringtranslate.translateKey("gui.create_world.label.world_name"), width / 2 - 100, 47, 0xa0a0a0);
+        drawString(font, stringtranslate.translateKey("gui.create_world.label.seed"), width / 2 - 100, 88, 0xa0a0a0);
         textboxWorldName.drawTextBox();
         textboxSeed.drawTextBox();
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
     }
 
     @Override
@@ -239,6 +239,6 @@ public class GuiCreateWorld extends GuiScreen {
         textboxSeed.setText(seed);
         updateFolderName();
         selectedGamemode = Gamemode.creative;
-        buttonPressed(createWorldButton);
+        buttonClicked(createWorldButton);
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/GuiCredits.java b/src/main/java/net/minecraft/client/gui/CreditsScreen.java
similarity index 76%
rename from src/main/java/net/minecraft/client/gui/GuiCredits.java
rename to src/main/java/net/minecraft/client/gui/CreditsScreen.java
index 2b3d24f7c..5a711e93b 100644
--- a/src/main/java/net/minecraft/client/gui/GuiCredits.java
+++ b/src/main/java/net/minecraft/client/gui/CreditsScreen.java
@@ -1,15 +1,15 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
+import com.mojang.logging.LogUtils;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.client.render.Scissor;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.net.command.TextFormatting;
-import net.minecraft.core.sound.SoundCategory;
-import net.minecraft.core.util.helper.MathHelper;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.GL11;
+import org.slf4j.Logger;
 
 import java.awt.*;
 import java.io.BufferedReader;
@@ -21,7 +21,8 @@ import java.util.List;
 
 import static org.lwjgl.opengl.GL11.*;
 
-public class GuiCredits extends GuiScreen {
+public class CreditsScreen extends Screen {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private static final int TOP_SPACING = 24;
     private static final int BUTTON_SPACING = 4;
 
@@ -52,10 +53,10 @@ public class GuiCredits extends GuiScreen {
 
     private float hue = 0;
 
-    public GuiCredits(GuiScreen parent) {
+    public CreditsScreen(Screen parent) {
         super(parent);
 
-        try (InputStream stream = GuiMainMenu.class.getResourceAsStream("/credits.txt")) {
+        try (InputStream stream = MainMenuScreen.class.getResourceAsStream("/credits.txt")) {
 
             List<String> lines = new ArrayList<>();
             BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
@@ -70,7 +71,7 @@ public class GuiCredits extends GuiScreen {
             }
             this.lines = lines;
         } catch (Exception e) {
-            e.printStackTrace();
+            LOGGER.error("Exception when trying to load 'credits.txt'", e);
             this.lines = new ArrayList<>();
             this.lines.add("An error occurred while loading the credits.");
         }
@@ -81,9 +82,9 @@ public class GuiCredits extends GuiScreen {
         top = TOP_SPACING;
         bottom = height - (BUTTON_SPACING + 20 + BUTTON_SPACING);
         scrollRegionHeight = bottom - top;
-        add(new GuiListenerButton(0, width / 2 - 100, height - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.credits.button.done")).setActionListener(() -> {
-            onClosed();
-            mc.displayGuiScreen(null);
+        add(new ListenerButtonElement(0, width / 2 - 100, height - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.credits.button.done")).setActionListener(() -> {
+            removed();
+            mc.displayScreen(null);
         }));
 
         onScroll();
@@ -98,12 +99,12 @@ public class GuiCredits extends GuiScreen {
     }
 
     @Override
-    public void onClosed() {
+    public void removed() {
         mc.sndManager.stopMusic();
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick) {
+    public void render(int xm, int ym, float partialTick) {
         // Handle scrolling
         if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) {
             scroll(Mouse.getDWheel() * -0.01f);
@@ -111,15 +112,15 @@ public class GuiCredits extends GuiScreen {
             scroll(Mouse.getDWheel() / -0.05f);
         }
 
-        drawDefaultBackground();
+        renderBackground();
         overlayBackground(0, width, 0, top);
         overlayBackground(0, width, bottom, height);
 
-        drawScrollBar(mouseX, mouseY);
+        drawScrollBar(xm, ym);
 
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
 
-        fontRenderer.drawCenteredString(I18n.getInstance().translateKey("gui.credits.label.title"), width / 2, 5, 0xFFFFFF);
+        font.drawCenteredString(I18n.getInstance().translateKey("gui.credits.label.title"), width / 2, 5, 0xFFFFFF);
 
         Scissor.enable(0, top, width, bottom - top);
         drawContent();
@@ -129,7 +130,7 @@ public class GuiCredits extends GuiScreen {
     }
 
     private void drawContent() {
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/title/mclogo.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/title/mclogo.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         drawTexturedModalRect(width / 2 - 274 / 2, 30 - (int)scrollAmount, 0, 0, 274, 50, 1d/274, 1d/50);
 
@@ -137,15 +138,15 @@ public class GuiCredits extends GuiScreen {
             String line = lines.get(i);
             if (line.startsWith("*")) {
                 line = TextFormatting.BOLD + line.substring(1);
-                int lineWidth = fontRenderer.getStringWidth(line) + line.length();
-                fontRenderer.drawString(line, width / 2 - lineWidth / 2, 100 + i * 12 - (int)scrollAmount, 0xFFFFFF);
+                int lineWidth = font.getStringWidth(line) + line.length();
+                font.drawString(line, width / 2 - lineWidth / 2, 100 + i * 12 - (int)scrollAmount, 0xFFFFFF);
             } else if (line.startsWith("!")) {
                 int rgb = Color.HSBtoRGB(hue / 360f, 1.0f, 1.0f);
                 line = TextFormatting.BOLD + line.substring(1);
-                int lineWidth = fontRenderer.getStringWidth(line) + line.length();
-                fontRenderer.drawString(line, width / 2 - lineWidth / 2, 100 + i * 12 - (int)scrollAmount, rgb);
+                int lineWidth = font.getStringWidth(line) + line.length();
+                font.drawString(line, width / 2 - lineWidth / 2, 100 + i * 12 - (int)scrollAmount, rgb);
             } else {
-                fontRenderer.drawString(line, width / 2 - fontRenderer.getStringWidth(line) / 2, 100 + i * 12 - (int) scrollAmount, 0x7F7F7F);
+                font.drawString(line, width / 2 - font.getStringWidth(line) / 2, 100 + i * 12 - (int) scrollAmount, 0x7F7F7F);
             }
         }
     }
@@ -196,19 +197,19 @@ public class GuiCredits extends GuiScreen {
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
+    public void mouseClicked(int mx, int my, int buttonNum) {
+        super.mouseClicked(mx, my, buttonNum);
 
-        clickX = mouseX;
-        clickY = mouseY;
+        clickX = mx;
+        clickY = my;
     }
 
     @Override
-    public void drawDefaultBackground() {
-        super.drawDefaultBackground();
+    public void renderBackground() {
+        super.renderBackground();
 
         Tessellator tessellator = Tessellator.instance;
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         float scale = 32F;
         tessellator.startDrawingQuads();
@@ -225,7 +226,7 @@ public class GuiCredits extends GuiScreen {
     private void overlayBackground(int minX, int maxX, int minY, int maxY) {
         if (mc.theWorld == null) {
             Tessellator tessellator = Tessellator.instance;
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
             float scale = 32F;
             tessellator.startDrawingQuads();
@@ -259,10 +260,10 @@ public class GuiCredits extends GuiScreen {
     }
 
     @Override
-    public void mouseMovedOrButtonReleased(int mouseX, int mouseY, int mouseButton) {
-        super.mouseMovedOrButtonReleased(mouseX, mouseY, mouseButton);
+    public void mouseReleased(int mx, int my, int buttonNum) {
+        super.mouseReleased(mx, my, buttonNum);
 
-        if (mouseButton >= 0) {
+        if (buttonNum >= 0) {
             clickX = null;
             clickY = null;
         }
diff --git a/src/main/java/net/minecraft/client/gui/GuiDownloadTerrain.java b/src/main/java/net/minecraft/client/gui/DownloadTerrainScreen.java
similarity index 63%
rename from src/main/java/net/minecraft/client/gui/GuiDownloadTerrain.java
rename to src/main/java/net/minecraft/client/gui/DownloadTerrainScreen.java
index 4ee1d3c2d..02c672600 100644
--- a/src/main/java/net/minecraft/client/gui/GuiDownloadTerrain.java
+++ b/src/main/java/net/minecraft/client/gui/DownloadTerrainScreen.java
@@ -8,24 +8,24 @@ import net.minecraft.client.net.handler.ClientPacketHandler;
 import net.minecraft.core.net.packet.KeepAlivePacket;
 import net.minecraft.core.lang.I18n;
 
-public class GuiDownloadTerrain extends GuiScreen
+public class DownloadTerrainScreen extends Screen
 {
 
-    public GuiDownloadTerrain(ClientPacketHandler netclienthandler)
+    public DownloadTerrainScreen(ClientPacketHandler netclienthandler)
     {
         updateCounter = 0;
         netHandler = netclienthandler;
     }
 
     @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
     }
 
     @Override
 	public void init()
     {
-        controlList.clear();
+        buttons.clear();
     }
 
     @Override
@@ -43,18 +43,18 @@ public class GuiDownloadTerrain extends GuiScreen
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
     }
 
     @Override
 
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
-        drawBackground();
+        renderTexturedBackground();
         I18n i18n = I18n.getInstance();
-        drawStringCentered(fontRenderer, i18n.translateKey("gui.downloading_terrain.label.title"), width / 2, height / 2 - 50, 0xffffff);
-        super.drawScreen(mouseX, mouseY, partialTick);
+        drawStringCentered(font, i18n.translateKey("gui.downloading_terrain.label.title"), width / 2, height / 2 - 50, 0xffffff);
+        super.render(xm, ym, partialTick);
     }
 
     private ClientPacketHandler netHandler;
diff --git a/src/main/java/net/minecraft/client/gui/GuiSurface.java b/src/main/java/net/minecraft/client/gui/DrawableSurfaceElement.java
similarity index 89%
rename from src/main/java/net/minecraft/client/gui/GuiSurface.java
rename to src/main/java/net/minecraft/client/gui/DrawableSurfaceElement.java
index a17b0e219..ae3754886 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSurface.java
+++ b/src/main/java/net/minecraft/client/gui/DrawableSurfaceElement.java
@@ -1,92 +1,92 @@
-package net.minecraft.client.gui;
-
-import net.minecraft.client.gui.drawing.IDrawableSurface;
-
-public class GuiSurface
-    extends Gui
-    implements IDrawableSurface<Byte>
-{
-    private final int canvasWidth;
-    private final int canvasHeight;
-    private final int canvasScale;
-    private final byte[] surfaceData;
-    public int[] colors = new int[0];
-
-    public GuiSurface(int width, int height, int scale)
-    {
-        this(width, height, scale, new byte[width * height]);
-    }
-
-    public GuiSurface(int width, int height, int scale, byte[] surfaceData)
-    {
-        this.canvasWidth = width;
-        this.canvasHeight = height;
-        this.canvasScale = scale;
-        this.surfaceData = surfaceData;
-    }
-
-    public void render(int x, int y)
-    {
-        for (int dx = 0; dx < canvasWidth; dx++)
-        {
-            for (int dy = 0; dy < canvasHeight; dy++)
-            {
-                drawRectNoBlend(x + dx * canvasScale, y + dy * canvasScale, x + dx * canvasScale + canvasScale, y + dy * canvasScale + canvasScale, getColor(getPixelValue(dx, dy)));
-            }
-        }
-    }
-
-    private int getColor(byte val)
-    {
-        if (val < 0 || val >= colors.length)
-        {
-            return 0x00000000;
-        }
-        else
-        {
-            return colors[val];
-        }
-    }
-
-    public void clear()
-    {
-        for (int dx = 0; dx < canvasWidth; dx++)
-        {
-            for (int dy = 0; dy < canvasHeight; dy++)
-            {
-                setPixelValue(dx, dy, (byte)0);
-            }
-        }
-    }
-
-    @Override
-    public int getWidth()
-    {
-        return canvasWidth;
-    }
-
-    @Override
-    public int getHeight()
-    {
-        return canvasHeight;
-    }
-
-    @Override
-    public Byte getPixelValue(int x, int y)
-    {
-        if (x < 0 || x >= canvasWidth) return 0;
-        if (y < 0 || y >= canvasHeight) return 0;
-
-        return surfaceData[x + canvasWidth * y];
-    }
-
-    @Override
-    public boolean setPixelValue(int x, int y, Byte value)
-    {
-        if (x < 0 || x >= canvasWidth) return false;
-        if (y < 0 || y >= canvasHeight) return false;
-
-        surfaceData[x + canvasWidth * y] = value;
-        return true;
-    }
-}
+package net.minecraft.client.gui;
+
+import net.minecraft.client.gui.drawing.IDrawableSurface;
+
+public class DrawableSurfaceElement
+    extends Gui
+    implements IDrawableSurface<Byte>
+{
+    private final int canvasWidth;
+    private final int canvasHeight;
+    private final int canvasScale;
+    private final byte[] surfaceData;
+    public int[] colors = new int[0];
+
+    public DrawableSurfaceElement(int width, int height, int scale)
+    {
+        this(width, height, scale, new byte[width * height]);
+    }
+
+    public DrawableSurfaceElement(int width, int height, int scale, byte[] surfaceData)
+    {
+        this.canvasWidth = width;
+        this.canvasHeight = height;
+        this.canvasScale = scale;
+        this.surfaceData = surfaceData;
+    }
+
+    public void render(int x, int y)
+    {
+        for (int dx = 0; dx < canvasWidth; dx++)
+        {
+            for (int dy = 0; dy < canvasHeight; dy++)
+            {
+                drawRectNoBlend(x + dx * canvasScale, y + dy * canvasScale, x + dx * canvasScale + canvasScale, y + dy * canvasScale + canvasScale, getColor(getPixelValue(dx, dy)));
+            }
+        }
+    }
+
+    private int getColor(byte val)
+    {
+        if (val < 0 || val >= colors.length)
+        {
+            return 0x00000000;
+        }
+        else
+        {
+            return colors[val];
+        }
+    }
+
+    public void clear()
+    {
+        for (int dx = 0; dx < canvasWidth; dx++)
+        {
+            for (int dy = 0; dy < canvasHeight; dy++)
+            {
+                setPixelValue(dx, dy, (byte)0);
+            }
+        }
+    }
+
+    @Override
+    public int getWidth()
+    {
+        return canvasWidth;
+    }
+
+    @Override
+    public int getHeight()
+    {
+        return canvasHeight;
+    }
+
+    @Override
+    public Byte getPixelValue(int x, int y)
+    {
+        if (x < 0 || x >= canvasWidth) return 0;
+        if (y < 0 || y >= canvasHeight) return 0;
+
+        return surfaceData[x + canvasWidth * y];
+    }
+
+    @Override
+    public boolean setPixelValue(int x, int y, Byte value)
+    {
+        if (x < 0 || x >= canvasWidth) return false;
+        if (y < 0 || y >= canvasHeight) return false;
+
+        surfaceData[x + canvasWidth * y] = value;
+        return true;
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/GuiException.java b/src/main/java/net/minecraft/client/gui/ExceptionPopupElement.java
similarity index 91%
rename from src/main/java/net/minecraft/client/gui/GuiException.java
rename to src/main/java/net/minecraft/client/gui/ExceptionPopupElement.java
index 71de3b752..81b614e77 100644
--- a/src/main/java/net/minecraft/client/gui/GuiException.java
+++ b/src/main/java/net/minecraft/client/gui/ExceptionPopupElement.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.popup.GuiPopup;
+import net.minecraft.client.gui.popup.PopupScreen;
 import net.minecraft.client.gui.popup.PopupBuilder;
 import net.minecraft.client.gui.popup.PopupCloseListener;
 import net.minecraft.core.net.command.TextFormatting;
@@ -14,9 +14,9 @@ import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Map;
 
-public class GuiException {
+public class ExceptionPopupElement {
 
-    public static GuiPopup create(GuiScreen parent, Throwable e, Minecraft mc){
+    public static PopupScreen create(Screen parent, Throwable e, Minecraft mc){
         int scale = Math.max(mc.resolution.scale,1);
         StringBuilder s = new StringBuilder("Minecraft ran into an unexpected problem!\n\n");
         s.append("To prevent more problems, the current game has quit, but you can try to keep playing.\n\n");
@@ -51,15 +51,15 @@ public class GuiException {
         s.append(TextFormatting.WHITE);
 
 
-        GuiPopup popup = new PopupBuilder(parent,860/scale).withLabel("gui.exception.label.exception_occurred")
-                .withMessageBox("gui.exception.list",400/scale,s.toString(),(860/scale) / mc.fontRenderer.getCharWidth('m'))
+        PopupScreen popup = new PopupBuilder(parent,860/scale).withLabel("gui.exception.label.exception_occurred")
+                .withMessageBox("gui.exception.list",400/scale,s.toString(),(860/scale) / mc.font.getCharWidth('m'))
                 .withButtonGroup("gui.exception.choice",new String[]{"gui.exception.button.back","gui.exception.button.copy_error"},new int[]{0,1})
                 .withOnCloseListener(new PopupListener(mc,s.toString().replaceAll("§[0-9a-f|klmnor]","")))
                 .build();
         return popup;
     }
 
-    public static GuiPopup createFatal(Throwable e, Minecraft mc){
+    public static PopupScreen createFatal(Throwable e, Minecraft mc){
         int scale = Math.max(mc.resolution.scale,1);
         StringBuilder s = new StringBuilder("Minecraft ran into an unexpected problem that it cannot recover from!\n\n");
         s.append("The current game has quit, please restart the game.\n\n");
@@ -93,10 +93,10 @@ public class GuiException {
         }
         s.append(TextFormatting.WHITE);
 
-        GuiBlank gui = new GuiBlank();
-        mc.displayGuiScreen(gui);
-        GuiPopup popup = new PopupBuilder(gui,860/scale).withLabel("gui.exception.label.fatal_error")
-                .withMessageBox("gui.exception.list",400/scale,s.toString(),(860/scale) / mc.fontRenderer.getCharWidth('m'))
+        BlankScreen screen = new BlankScreen();
+        mc.displayScreen(screen);
+        PopupScreen popup = new PopupBuilder(screen,860/scale).withLabel("gui.exception.label.fatal_error")
+                .withMessageBox("gui.exception.list",400/scale,s.toString(),(860/scale) / mc.font.getCharWidth('m'))
                 .withButtonGroup("gui.exception.choice",new String[]{"gui.exception.button.copy_error","gui.exception.button.copy_error_and_quit"},new int[]{0,2},new boolean[]{false,true})
                 .withBackgroundColor(0xff402020, 0xff501010)
                 .withOnCloseListener(new PopupListener(mc,s.toString().replaceAll("§[0-9a-f|klmnor]","")))
@@ -104,7 +104,7 @@ public class GuiException {
         return popup;
     }
 
-    public static GuiPopup createStartupError(Throwable e, Minecraft mc){
+    public static PopupScreen createStartupError(Throwable e, Minecraft mc){
         int scale = Math.max(mc.resolution.scale,1);
         StringBuilder s = new StringBuilder("An error has prevented Minecraft from starting up correctly!\n\n");
         s.append("The game cannot continue, please restart the game.\n\n");
@@ -138,10 +138,10 @@ public class GuiException {
         }
         s.append(TextFormatting.WHITE);
 
-        GuiBlank gui = new GuiBlank();
-        mc.displayGuiScreen(gui);
-        GuiPopup popup = new PopupBuilder(gui,860/scale).withLabel("gui.exception.label.startup_error")
-                .withMessageBox("gui.exception.list",400/scale,s.toString(),(860/scale) / mc.fontRenderer.getCharWidth('m'))
+        BlankScreen screen = new BlankScreen();
+        mc.displayScreen(screen);
+        PopupScreen popup = new PopupBuilder(screen,860/scale).withLabel("gui.exception.label.startup_error")
+                .withMessageBox("gui.exception.list",400/scale,s.toString(),(860/scale) / mc.font.getCharWidth('m'))
                 .withButtonGroup("gui.exception.choice",new String[]{"gui.exception.button.copy_error","gui.exception.button.copy_error_and_quit"},new int[]{0,2},new boolean[]{false,true})
                 .withBackgroundColor(0xff402020, 0xff501010)
                 .withOnCloseListener(new PopupListener(mc,s.toString().replaceAll("§[0-9a-f|klmnor]","")))
diff --git a/src/main/java/net/minecraft/client/gui/GuiGameOver.java b/src/main/java/net/minecraft/client/gui/GameOverScreen.java
similarity index 66%
rename from src/main/java/net/minecraft/client/gui/GuiGameOver.java
rename to src/main/java/net/minecraft/client/gui/GameOverScreen.java
index ee948cfb7..0faff9750 100644
--- a/src/main/java/net/minecraft/client/gui/GuiGameOver.java
+++ b/src/main/java/net/minecraft/client/gui/GameOverScreen.java
@@ -11,11 +11,11 @@ import net.minecraft.core.net.command.TextFormatting;
 // Referenced classes of package net.minecraft.src:
 //            GuiScreen, GuiButton, LocalPlayer, GuiMainMenu
 
-public class GuiGameOver extends GuiScreen
+public class GameOverScreen extends Screen
 {
     protected int tickCount = 0;
 
-    public GuiGameOver()
+    public GameOverScreen()
     {
     }
     @Override
@@ -31,51 +31,51 @@ public class GuiGameOver extends GuiScreen
 	public void init()
     {
         I18n i18n = I18n.getInstance();
-        controlList.clear();
+        buttons.clear();
         String respawnKey = (mc.thePlayer.getGamemode() == Gamemode.hardcore || mc.thePlayer.getGamemode() == Gamemode.spectator) ? "gui.game_over.button.respawn.spectator" : "gui.game_over.button.respawn";
-        controlList.add(new GuiButton(1, width / 2 - 100, height / 4 + 72, i18n.translateKey(respawnKey)));
-        controlList.add(new GuiButton(2, width / 2 - 100, height / 4 + 96, i18n.translateKey("gui.game_over.button.title_screen")));
+        buttons.add(new ButtonElement(1, width / 2 - 100, height / 4 + 72, i18n.translateKey(respawnKey)));
+        buttons.add(new ButtonElement(2, width / 2 - 100, height / 4 + 96, i18n.translateKey("gui.game_over.button.title_screen")));
         if(mc.session == null)
         {
-            controlList.get(1).enabled = false;
+            buttons.get(1).enabled = false;
         }
     }
 
     @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
         if(button.id == 1)
         {
             mc.thePlayer.respawnPlayer();
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
         }
         if(button.id == 2)
         {
             mc.changeWorld(null);
-            mc.displayGuiScreen(new GuiMainMenu());
+            mc.displayScreen(new MainMenuScreen());
         }
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
         I18n i18n = I18n.getInstance();
         drawGradientRect(0, 0, width, height, 0x60500000, 0xa0803030);
         GL11.glPushMatrix();
         GL11.glScalef(2.0F, 2.0F, 2.0F);
-        drawStringCentered(fontRenderer, i18n.translateKey("gui.game_over.label.title"), width / 2 / 2, 30, 0xffffff);
+        drawStringCentered(font, i18n.translateKey("gui.game_over.label.title"), width / 2 / 2, 30, 0xffffff);
         GL11.glPopMatrix();
-        drawStringCentered(fontRenderer, i18n.translateKeyAndFormat("gui.game_over.label.score", TextFormatting.YELLOW.toString() + mc.thePlayer.getScore()), width / 2, 100, 0xffffff);
-        super.drawScreen(mouseX, mouseY, partialTick);
+        drawStringCentered(font, i18n.translateKeyAndFormat("gui.game_over.label.score", TextFormatting.YELLOW.toString() + mc.thePlayer.getScore()), width / 2, 100, 0xffffff);
+        super.render(xm, ym, partialTick);
     }
 
     @Override
-	public boolean pausesGame()
+	public boolean isPauseScreen()
     {
         return false;
     }
diff --git a/src/main/java/net/minecraft/client/gui/Gui.java b/src/main/java/net/minecraft/client/gui/Gui.java
index f7256c09a..8fb5e1005 100644
--- a/src/main/java/net/minecraft/client/gui/Gui.java
+++ b/src/main/java/net/minecraft/client/gui/Gui.java
@@ -3,8 +3,8 @@ package net.minecraft.client.gui;
 import static org.lwjgl.opengl.GL11.*;
 
 import net.minecraft.client.lang.text.Text;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.texture.Texture;
 import net.minecraft.client.render.texture.meta.gui.GuiTextureProperties;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
@@ -69,7 +69,7 @@ public class Gui
         drawRectDouble(minX, minY + 1, minX + 1, maxY, argb);
     }
 
-    protected void drawRect(int minX, int minY, int maxX, int maxY, int argb)
+    public void drawRect(int minX, int minY, int maxX, int maxY, int argb)
     {
         if(minX < maxX)
         {
@@ -218,42 +218,42 @@ public class Gui
         GL11.glEnable(GL_TEXTURE_2D);
     }
 
-    public void drawTextCentered(FontRenderer fr, Text text, int x, int y, int argb)
+    public void drawTextCentered(Font fr, Text text, int x, int y, int argb)
     {
         fr.drawTextWithShadow(text, x - fr.getTextWidth(text) / 2, y, argb);
     }
 
-    public void drawTextCenteredNoShadow(FontRenderer fr, Text text, int x, int y, int argb)
+    public void drawTextCenteredNoShadow(Font fr, Text text, int x, int y, int argb)
     {
         fr.drawText(text, x - fr.getTextWidth(text) / 2, y, argb);
     }
 
-    public void drawText(FontRenderer fr, Text text, int x, int y, int argb)
+    public void drawText(Font fr, Text text, int x, int y, int argb)
     {
         fr.drawTextWithShadow(text, x, y, argb);
     }
 
-    public void drawTextNoShadow(FontRenderer fr, Text text, int x, int y, int argb)
+    public void drawTextNoShadow(Font fr, Text text, int x, int y, int argb)
     {
         fr.drawText(text, x, y, argb);
     }
 
-    public void drawStringCentered(FontRenderer fr, String string, int x, int y, int argb)
+    public void drawStringCentered(Font fr, String string, int x, int y, int argb)
     {
         fr.drawStringWithShadow(string, x - fr.getStringWidth(string) / 2, y, argb);
     }
     
-    public void drawStringCenteredNoShadow(FontRenderer fr, String string, int x, int y, int argb)
+    public void drawStringCenteredNoShadow(Font fr, String string, int x, int y, int argb)
     {
         fr.drawString(string, x - fr.getStringWidth(string) / 2, y, argb);
     }
 
-    public void drawString(FontRenderer fr, String string, int x, int y, int argb)
+    public void drawString(Font fr, String string, int x, int y, int argb)
     {
         fr.drawStringWithShadow(string, x, y, argb);
     }
     
-    public void drawStringNoShadow(FontRenderer fr, String string, int x, int y, int argb)
+    public void drawStringNoShadow(Font fr, String string, int x, int y, int argb)
     {
     	fr.drawString(string, x, y, argb);
     }
@@ -379,7 +379,7 @@ public class Gui
         drawGuiIcon(x, y, 18, 18, TextureRegistry.getTexture("minecraft:gui/slot"));
     }
 
-    public void drawGuiTexture(RenderEngine re, int x, int y, int width, int height, String texture) {
+    public void drawGuiTexture(TextureManager re, int x, int y, int width, int height, String texture) {
         Texture tex = re.loadTexture(texture);
         tex.bind();
 
diff --git a/src/main/java/net/minecraft/client/gui/GuiBadJavaArch.java b/src/main/java/net/minecraft/client/gui/GuiBadJavaArch.java
deleted file mode 100644
index 4e248013d..000000000
--- a/src/main/java/net/minecraft/client/gui/GuiBadJavaArch.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package net.minecraft.client.gui;
-
-// Referenced classes of package net.minecraft.src:
-//            GuiScreen, GuiButton, GuiMainMenu
-
-import net.minecraft.core.lang.I18n;
-
-import java.awt.*;
-import java.net.URI;
-
-public class GuiBadJavaArch extends GuiScreen
-{
-
-    public GuiBadJavaArch()
-    {
-        updateCounter = 0;
-    }
-
-    @Override
-	public void tick()
-    {
-        updateCounter++;
-    }
-
-    @Override
-	public void init()
-    {
-        I18n i = I18n.getInstance();
-        controlList.clear();
-        String downloadString = i.translateKey("gui.bad_java_arch.button.download");
-        controlList.add(new GuiButton(0, width / 2 - 100, height / 4 + 120 + 12, i.translateKey("gui.bad_java_arch.button.continue")));
-        controlList.add(new GuiClickableLabel(1, width / 2 - 170 - fontRenderer.getStringWidth(downloadString) / 2, (height / 4 - 60) + 60 + 64, downloadString, 0x7C99EA));
-    }
-
-    @Override
-	protected void buttonPressed(GuiButton button)
-    {
-        if(!button.enabled)
-        {
-            return;
-        }
-        if(button.id == 0)
-        {
-            mc.displayGuiScreen(new GuiMainMenu());
-        }
-        Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
-        if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE))
-        {
-            if (button.id == 1)
-            {
-                try
-                {
-                    desktop.browse(URI.create("https://adoptium.net/en-GB/temurin/releases/?version=8"));
-                }
-                catch (Exception e)
-                {
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-
-    @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
-    {
-        I18n i = I18n.getInstance();
-        drawDefaultBackground();
-        drawStringCentered(fontRenderer, i.translateKey("gui.bad_java_arch.label.title"), width / 2, (height / 4 - 60) + 20, 0xffffff);
-        drawString(fontRenderer, i.translateKey("gui.bad_java_arch.label.body.1"), width / 2 - 170, (height / 4 - 60) + 60 + 0, 0xa0a0a0);
-        drawString(fontRenderer, i.translateKey("gui.bad_java_arch.label.body.2"), width / 2 - 170, (height / 4 - 60) + 60 + 18, 0xa0a0a0);
-        drawString(fontRenderer, i.translateKey("gui.bad_java_arch.label.body.3"), width / 2 - 170, (height / 4 - 60) + 60 + 27, 0xa0a0a0);
-        drawString(fontRenderer, i.translateKey("gui.bad_java_arch.label.body.4"), width / 2 - 170, (height / 4 - 60) + 60 + 45, 0xa0a0a0);
-        super.drawScreen(mouseX, mouseY, partialTick);
-    }
-
-    private int updateCounter;
-}
diff --git a/src/main/java/net/minecraft/client/gui/GuiBlank.java b/src/main/java/net/minecraft/client/gui/GuiBlank.java
deleted file mode 100644
index 0ce0d6361..000000000
--- a/src/main/java/net/minecraft/client/gui/GuiBlank.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package net.minecraft.client.gui;
-
-public class GuiBlank extends GuiScreen
-{
-    @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
-    {
-    }
-}
diff --git a/src/main/java/net/minecraft/client/gui/GuiClickableLabel.java b/src/main/java/net/minecraft/client/gui/GuiClickableLabel.java
deleted file mode 100644
index 2a65551bf..000000000
--- a/src/main/java/net/minecraft/client/gui/GuiClickableLabel.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package net.minecraft.client.gui;
-
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
-import org.lwjgl.opengl.GL11;
-
-public class GuiClickableLabel extends GuiButton
-{
-    int textColor;
-    int bgColor;
-
-    public boolean shadow = true;
-
-    public GuiClickableLabel(int id, int xPosition, int yPosition, String s, int textColor, int bgColor)
-    {
-        super(id, xPosition, yPosition, s);
-        this.textColor = textColor;
-        this.bgColor = bgColor;
-        height = 12;
-        width = 0;
-    }
-
-    public GuiClickableLabel(int id, int xPosition, int yPosition, String s, int textColor)
-    {
-        this(id, xPosition, yPosition, s, textColor, 0x7F000000);
-    }
-
-    @Override
-    public void drawButton(Minecraft mc, int mouseX, int mouseY)
-    {
-        if(!visible)
-        {
-            return;
-        }
-        FontRenderer fontrenderer = mc.fontRenderer;
-        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        boolean hovered = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height;
-        width = fontrenderer.getStringWidth(displayString) + 4;
-        drawRect(xPosition, yPosition, xPosition + width, yPosition + height, enabled ? (hovered ? 0x7F8080C0 : bgColor) : 0x00000000);
-        if (enabled && (shadow || hovered)) {
-            fontrenderer.drawStringWithShadow(displayString, xPosition + 2, yPosition + 2, hovered ? 0xFFFFA0 : textColor);
-        } else {
-            fontrenderer.drawString(displayString, xPosition + 2, yPosition + 2, 0x7F7F7F);
-        }
-        mouseDragged(mc, mouseX, mouseY);
-    }
-
-}
diff --git a/src/main/java/net/minecraft/client/gui/GuiConflictWarning.java b/src/main/java/net/minecraft/client/gui/GuiConflictWarning.java
deleted file mode 100644
index d9a8a983e..000000000
--- a/src/main/java/net/minecraft/client/gui/GuiConflictWarning.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package net.minecraft.client.gui;
-
-// Referenced classes of package net.minecraft.src:
-//            GuiScreen, GuiButton, GuiMainMenu
-
-import net.minecraft.core.lang.I18n;
-
-public class GuiConflictWarning extends GuiScreen
-{
-
-    public GuiConflictWarning()
-    {
-    }
-
-    @Override
-	public void init()
-    {
-        controlList.clear();
-        controlList.add(new GuiButton(0, width / 2 - 100, height / 4 + 120 + 12, I18n.getInstance().translateKey("gui.conflict_warning.button.back")));
-    }
-
-    @Override
-	protected void buttonPressed(GuiButton button)
-    {
-        if(!button.enabled)
-        {
-            return;
-        }
-        if(button.id == 0)
-        {
-            mc.displayGuiScreen(new GuiMainMenu());
-        }
-    }
-
-    @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
-    {
-        I18n i = I18n.getInstance();
-        drawDefaultBackground();
-        drawStringCentered(fontRenderer, i.translateKey("gui.conflict_warning.label.title"), width / 2, (height / 4 - 60) + 20, 0xffffff);
-        drawString(fontRenderer, i.translateKey("gui.conflict_warning.label.body.1"), width / 2 - 140, (height / 4 - 60) + 60 + 0, 0xa0a0a0);
-        drawString(fontRenderer, i.translateKey("gui.conflict_warning.label.body.2"), width / 2 - 140, (height / 4 - 60) + 60 + 18, 0xa0a0a0);
-        drawString(fontRenderer, i.translateKey("gui.conflict_warning.label.body.3"), width / 2 - 140, (height / 4 - 60) + 60 + 27, 0xa0a0a0);
-        drawString(fontRenderer, i.translateKey("gui.conflict_warning.label.body.4"), width / 2 - 140, (height / 4 - 60) + 60 + 45, 0xa0a0a0);
-        super.drawScreen(mouseX, mouseY, partialTick);
-    }
-}
diff --git a/src/main/java/net/minecraft/client/gui/GuiConnectToIP.java b/src/main/java/net/minecraft/client/gui/GuiConnectToIP.java
deleted file mode 100644
index 00f25b96a..000000000
--- a/src/main/java/net/minecraft/client/gui/GuiConnectToIP.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package net.minecraft.client.gui;
-
-import net.minecraft.core.lang.I18n;
-import net.minecraft.core.net.ServerAddress;
-import org.lwjgl.input.Keyboard;
-
-// Referenced classes of package net.minecraft.src:
-//            GuiScreen, GuiTextField, StringTranslate, GuiButton, 
-//            gGameSettings, GuiConnecting
-
-public class GuiConnectToIP extends GuiScreen
-{
-
-    public GuiConnectToIP(GuiScreen guiscreen)
-    {
-        super(guiscreen);
-    }
-
-    @Override
-	public void tick()
-    {
-        textField.updateCursorCounter();
-    }
-
-    @Override
-	public void init()
-    {
-        I18n stringtranslate = I18n.getInstance();
-        Keyboard.enableRepeatEvents(true);
-        controlList.clear();
-        controlList.add(new GuiButton(0, width / 2 - 100, height / 4 + 96 + 12, stringtranslate.translateKey("gui.connect_to_ip.button.connect")));
-        controlList.add(new GuiButton(1, width / 2 - 100, height / 4 + 120 + 12, stringtranslate.translateKey("gui.connect_to_ip.button.cancel")));
-        String s = mc.gameSettings.lastServer.value.replaceAll("_", ":");
-        controlList.get(0).enabled = s.length() > 0;
-        textField = new GuiTextField(this, fontRenderer, width / 2 - 100, (height / 4 - 10) + 50 + 18, 200, 20, s, "");
-        textField.isFocused = true;
-        textField.setMaxStringLength(128);
-    }
-
-    @Override
-	public void onClosed()
-    {
-        Keyboard.enableRepeatEvents(false);
-    }
-
-    @Override
-	protected void buttonPressed(GuiButton button)
-    {
-        if(!button.enabled)
-        {
-            return;
-        }
-        if(button.id == 1)
-        {
-            mc.displayGuiScreen(parentScreen);
-        } else
-        if(button.id == 0)
-        {
-            String serverUrl = textField.getText().trim();
-            mc.gameSettings.lastServer.value = serverUrl.replaceAll(":", "_");
-            mc.gameSettings.saveOptions();
-            ServerAddress address = ServerAddress.resolveServerIP(serverUrl);
-            mc.displayGuiScreen(new GuiConnecting(mc, address.getIP(), address.getPort()));
-        }
-    }
-
-    @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
-    {
-        if(i != Keyboard.KEY_BACK) super.keyTyped(c, i, mouseX, mouseY);
-        textField.textboxKeyTyped(c, i);
-        if(c == '\r')
-        {
-            buttonPressed((GuiButton)controlList.get(0));
-        }
-        ((GuiButton)controlList.get(0)).enabled = textField.getText().length() > 0;
-    }
-
-    @Override
-	public void mouseClicked(int mouseX, int mouseY, int mouseButton)
-    {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
-        textField.mouseClicked(mouseX, mouseY, mouseButton);
-    }
-
-    @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
-    {
-        I18n i18n = I18n.getInstance();
-        drawDefaultBackground();
-        drawStringCentered(fontRenderer, i18n.translateKey("gui.connect_to_ip.label.title"), width / 2, (height / 4 - 60) + 20, 0xffffff);
-        drawString(fontRenderer, i18n.translateKey("gui.connect_to_ip.label.enter_ip"), width / 2 - 140, (height / 4 - 60) + 60 + 36, 0xa0a0a0);
-        textField.drawTextBox();
-        super.drawScreen(mouseX, mouseY, partialTick);
-    }
-
-    private GuiTextField textField;
-}
diff --git a/src/main/java/net/minecraft/client/gui/GuiOutOfMemory.java b/src/main/java/net/minecraft/client/gui/GuiOutOfMemory.java
deleted file mode 100644
index 8ceb51df8..000000000
--- a/src/main/java/net/minecraft/client/gui/GuiOutOfMemory.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package net.minecraft.client.gui;
-
-
-// Referenced classes of package net.minecraft.src:
-//            GuiScreen, GuiButton
-
-import net.minecraft.core.lang.I18n;
-
-public class GuiOutOfMemory extends GuiScreen
-{
-    @Override
-    public void keyTyped(char c, int key, int mouseX, int mouseY) {
-    }
-
-    @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
-    {
-        I18n i18n = I18n.getInstance();
-        drawDefaultBackground();
-        drawStringCentered(fontRenderer, i18n.translateKey("gui.out_of_memory.label.title"), width / 2, (height / 4 - 60) + 20, 0xFFFFFF);
-        drawString(fontRenderer, i18n.translateKey("gui.out_of_memory.label.body.1"), width / 2 - 140, (height / 4 - 60) + 60 + 0, 0xA0A0A0);
-        drawString(fontRenderer, i18n.translateKey("gui.out_of_memory.label.body.2"), width / 2 - 140, (height / 4 - 60) + 60 + 18, 0xA0A0A0);
-        drawString(fontRenderer, i18n.translateKey("gui.out_of_memory.label.body.3"), width / 2 - 140, (height / 4 - 60) + 60 + 27, 0xA0A0A0);
-        drawString(fontRenderer, i18n.translateKey("gui.out_of_memory.label.body.4"), width / 2 - 140, (height / 4 - 60) + 60 + 36, 0xA0A0A0);
-        drawString(fontRenderer, i18n.translateKey("gui.out_of_memory.label.body.5"), width / 2 - 140, (height / 4 - 60) + 60 + 45, 0xA0A0A0);
-        drawString(fontRenderer, i18n.translateKey("gui.out_of_memory.label.body.6"), width / 2 - 140, (height / 4 - 60) + 60 + 63, 0xA0A0A0);
-        super.drawScreen(mouseX, mouseY, partialTick);
-    }
-}
diff --git a/src/main/java/net/minecraft/client/gui/GuiScreen.java b/src/main/java/net/minecraft/client/gui/GuiScreen.java
deleted file mode 100644
index 5b4372aef..000000000
--- a/src/main/java/net/minecraft/client/gui/GuiScreen.java
+++ /dev/null
@@ -1,235 +0,0 @@
-package net.minecraft.client.gui;
-
-import static org.lwjgl.opengl.GL11.*;
-
-import java.util.ArrayList;
-import java.util.List;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.input.controller.ControllerInput;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.client.util.debug.DebugRender;
-import net.minecraft.client.input.InputType;
-
-import net.minecraft.core.sound.SoundCategory;
-import org.lwjgl.input.Keyboard;
-import org.lwjgl.input.Mouse;
-import org.lwjgl.opengl.GL11;
-
-public class GuiScreen extends Gui
-{
-    protected Minecraft mc;
-    public int width;
-    public int height;
-    public List<GuiButton> controlList;
-    public boolean allowIngameInput;
-    protected FontRenderer fontRenderer;
-    protected GuiButton selectedButton;
-    final GuiScreen parentScreen;
-
-    public GuiScreen(GuiScreen parent)
-    {
-        controlList = new ArrayList<>();
-        allowIngameInput = false;
-        selectedButton = null;
-        parentScreen = parent;
-    }
-
-    public GuiScreen()
-    {
-        this(null);
-    }
-
-    public GuiScreen getParentScreen()
-    {
-        return parentScreen;
-    }
-    
-    public <E extends GuiButton> E add(E button) {
-    	controlList.add(button);
-    	return button;
-    }
-
-    public void drawScreen(int mouseX, int mouseY, float partialTick)
-    {
-        for(int i = 0; i < controlList.size(); i++)
-        {
-            GuiButton guibutton = controlList.get(i);
-            guibutton.drawButton(mc, mouseX, mouseY);
-        }
-    }
-
-    public void keyTyped(char c, int key, int mouseX, int mouseY)
-    {
-        if(key == Keyboard.KEY_BACK){
-            mc.displayGuiScreen(parentScreen);
-        }
-        if(key == Keyboard.KEY_ESCAPE) {
-        	mc.displayGuiScreen(null);
-        }
-    }
-
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton)
-    {
-        if(mouseButton == 0)
-        {
-            for (GuiButton guiButton : controlList) {
-                if (guiButton.mouseClicked(mc, mouseX, mouseY) && guiButton.playSound) {
-                    selectedButton = guiButton;
-                    mc.sndManager.playSound("random.click", SoundCategory.GUI_SOUNDS, 1.0F, 1.0F);
-                    if (guiButton.listener != null) {
-                        guiButton.listener.listen(guiButton);
-                    } else {
-                        buttonPressed(guiButton);
-                    }
-                    return;
-                }
-            }
-
-        }
-    }
-
-    public void mouseMovedOrButtonReleased(int mouseX, int mouseY, int mouseButton)
-    {
-        if(selectedButton != null && mouseButton == 0)
-        {
-            buttonReleased(selectedButton);
-            selectedButton.mouseReleased(mouseX, mouseY);
-            selectedButton = null;
-        }
-    }
-
-    protected void buttonPressed(GuiButton button)
-    {
-    }
-
-    protected void buttonReleased(GuiButton button)
-    {
-    }
-
-    public void setWorldAndResolution(Minecraft mc, int width, int height)
-    {
-        this.mc = mc;
-        fontRenderer = mc.fontRenderer;
-        this.width = width;
-        this.height = height;
-        controlList.clear();
-        init();
-    }
-
-    public void init()
-    {
-    }
-
-	public void handleInput() {
-		int mouseX = (Mouse.getEventX() * width) / mc.resolution.width;
-		int mouseY = height - (Mouse.getEventY() * height) / mc.resolution.height - 1;
-
-		while (Mouse.next()) {
-			if (mc.inputType == InputType.CONTROLLER) break;
-
-			if (Mouse.getEventButtonState()) {
-				mouseClicked(mouseX, mouseY, Mouse.getEventButton());
-			} else {
-				mouseMovedOrButtonReleased(mouseX, mouseY, Mouse.getEventButton());
-			}
-		}
-		while (Keyboard.next()) {
-    		if(Keyboard.getEventKeyState() && mc.gameSettings.showFrameTimes.value && DebugRender.keyPressed(Keyboard.getEventKey())) {
-    			continue;
-    		}
-            int eventKey = Keyboard.getEventKey();
-            char eventChar = Keyboard.getEventCharacter();
-            if (eventKey == 0 && Character.isDefined(eventChar)){
-                keyTyped(eventChar, eventKey, mouseX, mouseY);
-                return;
-            }
-			if (Keyboard.getEventKeyState()) {
-				if (eventKey == Keyboard.KEY_F11) {
-					mc.gameWindow.toggleFullscreen();
-					return;
-				}
-				keyTyped(eventChar, eventKey, mouseX, mouseY);
-			}
-		}
-	}
-
-    public void tick()
-    {
-    }
-
-    public void onClosed()
-    {
-    }
-
-    public void drawDefaultBackground()
-    {
-        drawWorldBackground();
-    }
-
-    public void drawWorldBackground()
-    {
-        if(mc.theWorld != null)
-        {
-        	int color = mc.gameSettings.guiBackgroundColor.value.getARGB();
-            drawGradientRect(0, 0, width, height, color, color);
-        } else
-        {
-            drawBackground();
-        }
-    }
-
-    public void drawBackground()
-    {
-        GL11.glDisable(GL11.GL_LIGHTING);
-        GL11.glDisable(GL11.GL_FOG);
-        Tessellator tessellator = Tessellator.instance;
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
-        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        float f = 32F;
-        tessellator.startDrawingQuads();
-        tessellator.setColorOpaque_I(0x404040);
-        tessellator.addVertexWithUV(0.0D, height, 0.0D, 0.0D, (float)height / f);
-        tessellator.addVertexWithUV(width, height, 0.0D, (float)width / f, (float)height / f);
-        tessellator.addVertexWithUV(width, 0.0D, 0.0D, (float)width / f, 0);
-        tessellator.addVertexWithUV(0.0D, 0.0D, 0.0D, 0.0D, 0);
-        tessellator.draw();
-    }
-    
-    public void drawControllerCursor() {
-    	glDisable(GL_DEPTH_TEST);
-    	glEnable(GL_BLEND);
-    	glColor3d(1.0, 1.0, 1.0);
-        drawGuiTexture(mc.renderEngine, (int) (mc.controllerInput.cursorX - 8), (int) (mc.controllerInput.cursorY - 8), 16, 16, "/assets/minecraft/textures/gui/controller/cursor.png");
-    	glDisable(GL_BLEND);
-    }
-    public void controllerInput(ControllerInput controller){
-        guiSpecificControllerInput(controller);
-        playControllerButtonSound(controller);
-    }
-
-    public void playControllerButtonSound(ControllerInput controller){
-        if(controller.buttonA.pressedThisFrame() || controller.buttonX.pressedThisFrame() || controller.buttonY.pressedThisFrame()) {
-            mc.sndManager.playSound("random.ui_click", SoundCategory.GUI_SOUNDS, 1.0f, 1.0f);
-        }
-        if(controller.buttonB.pressedThisFrame()) {
-            mc.sndManager.playSound("random.ui_back", SoundCategory.GUI_SOUNDS, 1.0f, 1.0f);
-        }
-    }
-    public void guiSpecificControllerInput(ControllerInput controller){
-
-    }
-
-    public boolean pausesGame()
-    {
-        return true;
-    }
-
-    public void selectNextField()
-    {
-    }
-
-    public void refreshFontRenderer(){
-        this.fontRenderer = mc.fontRenderer;
-    }
-}
diff --git a/src/main/java/net/minecraft/client/gui/GuiToggleButton.java b/src/main/java/net/minecraft/client/gui/GuiToggleButton.java
deleted file mode 100644
index 1afdba9e0..000000000
--- a/src/main/java/net/minecraft/client/gui/GuiToggleButton.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package net.minecraft.client.gui;
-
-import net.minecraft.client.option.ToggleableOption;
-
-public class GuiToggleButton extends GuiButton{
-
-	private ToggleableOption<?> option;
-	
-	public GuiToggleButton(int id, int xPosition, int yPosition, int width, int height, ToggleableOption<?> option) {
-		super(id, xPosition, yPosition, width, height, option.getDisplayStringValue());
-		
-		this.option = option;
-	}
-	
-	public ToggleableOption<?> getOption() {
-		return option;
-	}
-	
-}
diff --git a/src/main/java/net/minecraft/client/gui/GuiHeldItemTooltip.java b/src/main/java/net/minecraft/client/gui/HeldItemTooltipElement.java
similarity index 93%
rename from src/main/java/net/minecraft/client/gui/GuiHeldItemTooltip.java
rename to src/main/java/net/minecraft/client/gui/HeldItemTooltipElement.java
index 4d4b2fbc7..32e54b30f 100644
--- a/src/main/java/net/minecraft/client/gui/GuiHeldItemTooltip.java
+++ b/src/main/java/net/minecraft/client/gui/HeldItemTooltipElement.java
@@ -8,7 +8,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.client.util.helper.Colors;
 import net.minecraft.core.util.helper.Time;
 
-public class GuiHeldItemTooltip extends Gui {
+public class HeldItemTooltipElement extends Gui {
 
 	private Minecraft mc;
 	
@@ -24,7 +24,7 @@ public class GuiHeldItemTooltip extends Gui {
 	private final double displayTime = 2.5;
 	private final double fadeTime = 0.5;
 	
-	public GuiHeldItemTooltip(Minecraft mc) {
+	public HeldItemTooltipElement(Minecraft mc) {
 		this.mc = mc;
 	}
 	
@@ -126,7 +126,7 @@ public class GuiHeldItemTooltip extends Gui {
 			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 		}
 
-		mc.fontRenderer.drawStringWithShadow(string, x - (mc.fontRenderer.getStringWidth(string)) / 2, y, rgb);
+		mc.font.drawStringWithShadow(string, x - (mc.font.getStringWidth(string)) / 2, y, rgb);
 
 		glDisable(GL_BLEND);
 		glEnable(GL_ALPHA_TEST);
diff --git a/src/main/java/net/minecraft/client/gui/GuiHudDesigner.java b/src/main/java/net/minecraft/client/gui/HudDesignerScreen.java
similarity index 89%
rename from src/main/java/net/minecraft/client/gui/GuiHudDesigner.java
rename to src/main/java/net/minecraft/client/gui/HudDesignerScreen.java
index 9c6dec263..905ffb6df 100644
--- a/src/main/java/net/minecraft/client/gui/GuiHudDesigner.java
+++ b/src/main/java/net/minecraft/client/gui/HudDesignerScreen.java
@@ -1,6 +1,12 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.hud.*;
+import net.minecraft.client.gui.hud.component.ComponentAnchor;
+import net.minecraft.client.gui.hud.component.HudComponent;
+import net.minecraft.client.gui.hud.component.HudComponents;
+import net.minecraft.client.gui.hud.component.MovableHudComponent;
+import net.minecraft.client.gui.hud.component.layout.AbsoluteLayout;
+import net.minecraft.client.gui.hud.component.layout.Layout;
+import net.minecraft.client.gui.hud.component.layout.SnapLayout;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.helper.MathHelper;
@@ -11,8 +17,8 @@ import java.util.List;
 
 import static org.lwjgl.opengl.GL11.*;
 
-public class GuiHudDesigner
-    extends GuiScreen {
+public class HudDesignerScreen
+    extends Screen {
     private static final int BOTTOM_SPACE = 28;
     private final List<HudComponent> componentsUnderMouse = new ArrayList<>();
     private HudComponent heldComponent = null;
@@ -20,9 +26,9 @@ public class GuiHudDesigner
     private HudComponent snappedComponent = null;
     private ComponentAnchor snappedAnchor = null;
     private float screenPadding = 0.0f;
-    private GuiButton resetButton;
+    private ButtonElement resetButton;
 
-    public GuiHudDesigner(GuiScreen parent) {
+    public HudDesignerScreen(Screen parent) {
         super(parent);
     }
 
@@ -32,22 +38,22 @@ public class GuiHudDesigner
         this.screenPadding = mc.gameSettings.screenPadding.value;
         mc.gameSettings.screenPadding.set(0.0f);
 
-        add(new GuiButton(0, width / 2 - 100, height - BOTTOM_SPACE + (BOTTOM_SPACE - 20) / 2, 178, 20, I18n.getInstance().translateKey("gui.hud_designer.button.done")));
-        add(resetButton = new GuiButton(1, width / 2 + 80, height - BOTTOM_SPACE + (BOTTOM_SPACE - 20) / 2, 20, 20, "")
+        add(new ButtonElement(0, width / 2 - 100, height - BOTTOM_SPACE + (BOTTOM_SPACE - 20) / 2, 178, 20, I18n.getInstance().translateKey("gui.hud_designer.button.done")));
+        add(resetButton = new ButtonElement(1, width / 2 + 80, height - BOTTOM_SPACE + (BOTTOM_SPACE - 20) / 2, 20, 20, "")
             .setTextures("minecraft:gui/misc/button_reset", "minecraft:gui/misc/button_reset_highlighted", "minecraft:gui/misc/button_reset"));
     }
 
     @Override
-    public void onClosed() {
-        super.onClosed();
+    public void removed() {
+        super.removed();
         mc.gameSettings.screenPadding.set(screenPadding);
     }
 
     @Override
-    protected void buttonPressed(GuiButton button) {
-        super.buttonPressed(button);
+    protected void buttonClicked(ButtonElement button) {
+        super.buttonClicked(button);
         if (button.id == 0) {
-            mc.displayGuiScreen(getParentScreen());
+            mc.displayScreen(getParentScreen());
         }
         if (button.id == 1) {
             HudComponents.INSTANCE.fromSettingsString(HudComponents.DEFAULT_LAYOUT);
@@ -55,10 +61,10 @@ public class GuiHudDesigner
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
-        updateComponentsUnderMouse(mouseX, mouseY);
+    public void mouseClicked(int mx, int my, int buttonNum) {
+        updateComponentsUnderMouse(mx, my);
         boolean clickedComponent = false;
-        if (mouseButton == 0) {
+        if (buttonNum == 0) {
             if (!componentsUnderMouse.isEmpty()) {
                 HudComponent componentUnderMouse = componentsUnderMouse.get(componentsUnderMouse.size() - 1);
                 if (componentUnderMouse instanceof MovableHudComponent) {
@@ -66,7 +72,7 @@ public class GuiHudDesigner
                     ComponentAnchor anchor = getClosestAnchor(
                         currentLayout.getComponentX(mc, componentUnderMouse, width),
                         currentLayout.getComponentY(mc, componentUnderMouse, height - BOTTOM_SPACE),
-                        componentUnderMouse, mouseX, mouseY);
+                        componentUnderMouse, mx, my);
                     Layout layout = new AbsoluteLayout(0, 0, anchor);
                     ((MovableHudComponent) componentUnderMouse).setLayout(layout);
 
@@ -79,7 +85,7 @@ public class GuiHudDesigner
 
         if (!clickedComponent) {
             heldComponent = null;
-            super.mouseClicked(mouseX, mouseY, mouseButton);
+            super.mouseClicked(mx, my, buttonNum);
         }
     }
 
@@ -217,27 +223,27 @@ public class GuiHudDesigner
     }
 
     @Override
-    public void mouseMovedOrButtonReleased(int mouseX, int mouseY, int mouseButton) {
-        if (mouseButton == 0) {
+    public void mouseReleased(int mx, int my, int buttonNum) {
+        if (buttonNum == 0) {
             heldComponent = null;
             heldAnchor = null;
             snappedComponent = null;
             snappedAnchor = null;
         }
-        super.mouseMovedOrButtonReleased(mouseX, mouseY, mouseButton);
+        super.mouseReleased(mx, my, buttonNum);
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick) {
-        updateComponentsUnderMouse(mouseX, mouseY);
+    public void render(int xm, int ym, float partialTick) {
+        updateComponentsUnderMouse(xm, ym);
 
         if (heldComponent != null) {
-            updateHeldComponent(mouseX, mouseY);
+            updateHeldComponent(xm, ym);
         }
 
-        drawBackground();
+        renderTexturedBackground();
 
-        drawHudComponents(mouseX, mouseY);
+        drawHudComponents(xm, ym);
 
         Tessellator tessellator = Tessellator.instance;
         GL11.glDisable(GL_DEPTH_TEST);
@@ -259,16 +265,16 @@ public class GuiHudDesigner
             }
         }
 
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
     }
 
     @Override
-    public void drawBackground() {
-        super.drawBackground();
+    public void renderTexturedBackground() {
+        super.renderTexturedBackground();
         GL11.glDisable(GL11.GL_LIGHTING);
         GL11.glDisable(GL11.GL_FOG);
         Tessellator tessellator = Tessellator.instance;
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/designer_bg.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/designer_bg.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         float scale = 32F;
         tessellator.startDrawingQuads();
diff --git a/src/main/java/net/minecraft/client/gui/GuiSliderInteger.java b/src/main/java/net/minecraft/client/gui/IntegerSliderElement.java
similarity index 88%
rename from src/main/java/net/minecraft/client/gui/GuiSliderInteger.java
rename to src/main/java/net/minecraft/client/gui/IntegerSliderElement.java
index c6d4ca21c..02cf45af5 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSliderInteger.java
+++ b/src/main/java/net/minecraft/client/gui/IntegerSliderElement.java
@@ -1,23 +1,23 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import org.lwjgl.opengl.GL11;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.option.ToggleableOption;
 
-public class GuiSliderInteger extends GuiButton {
+public class IntegerSliderElement extends ButtonElement {
 
 	public int sliderValue;
 	public boolean dragging;
 	private ToggleableOption<?> option;
 
-	public GuiSliderInteger(int id, int xPosition, int yPosition, ToggleableOption<?> option) {
+	public IntegerSliderElement(int id, int xPosition, int yPosition, ToggleableOption<?> option) {
 		this(id, xPosition, yPosition, 150, 20, option);
 	}
 
-	public GuiSliderInteger(int id, int xPosition, int yPosition, int width, int height, ToggleableOption<?> option) {
+	public IntegerSliderElement(int id, int xPosition, int yPosition, int width, int height, ToggleableOption<?> option) {
 		super(id, xPosition, yPosition, width, height, option.getDisplayStringValue());
 		
 		this.dragging = false;
@@ -56,7 +56,7 @@ public class GuiSliderInteger extends GuiButton {
 	public void drawButton(Minecraft mc, int mouseX, int mouseY) {
 		if (!visible) return;
 
-		FontRenderer fontrenderer = mc.fontRenderer;
+		Font font = mc.font;
 		boolean mouseOver = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height;
 		int state = getButtonState(mouseOver);
 
@@ -105,7 +105,7 @@ public class GuiSliderInteger extends GuiButton {
 				textColor = 0xFFFFA0;
 				break;
 		}
-		drawStringCentered(fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, textColor);
+		drawStringCentered(font, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, textColor);
 
 	}
 
diff --git a/src/main/java/net/minecraft/client/gui/GuiRenderItem.java b/src/main/java/net/minecraft/client/gui/ItemElement.java
similarity index 90%
rename from src/main/java/net/minecraft/client/gui/GuiRenderItem.java
rename to src/main/java/net/minecraft/client/gui/ItemElement.java
index 9be76dd78..c613e0079 100644
--- a/src/main/java/net/minecraft/client/gui/GuiRenderItem.java
+++ b/src/main/java/net/minecraft/client/gui/ItemElement.java
@@ -18,11 +18,11 @@ import net.minecraft.core.player.inventory.slot.GuidebookSlot;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
 
-public class GuiRenderItem extends Gui
+public class ItemElement extends Gui
 {
     Minecraft mc;
 
-    public GuiRenderItem(Minecraft mc)
+    public ItemElement(Minecraft mc)
     {
         this.mc = mc;
     }
@@ -60,7 +60,7 @@ public class GuiRenderItem extends Gui
             if (itemStack != null){
                 BlockModel.setRenderBlocks(EntityRenderDispatcher.instance.itemRenderer.renderBlocksInstance);
                 ItemModel itemModel = ItemModelDispatcher.getInstance().getDispatch(itemStack.getItem());
-                itemModel.renderItemIntoGui(Tessellator.instance, mc.fontRenderer, mc.renderEngine, itemStack, x, y, discovered ? 1.0f : 0.0f, 1.0f);
+                itemModel.renderItemIntoGui(Tessellator.instance, mc.font, mc.textureManager, itemStack, x, y, discovered ? 1.0f : 0.0f, 1.0f);
                 if(slot instanceof GuidebookSlot){
                     if(((GuidebookSlot) slot).recipe instanceof RecipeEntryTrommel && ((GuidebookSlot) slot).item != null && ((GuidebookSlot) slot).isOutput){
                         WeightedRandomBag<WeightedRandomLootObject> loot = ((RecipeEntryTrommel)((GuidebookSlot) slot).recipe).getOutput();
@@ -75,12 +75,12 @@ public class GuiRenderItem extends Gui
                         } else {
                             s = String.valueOf(lootObject.getFixedYield());
                         }
-                        itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.fontRenderer, mc.renderEngine, itemStack, x, y, discovered ? s : "?", 1.0f);
+                        itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.font, mc.textureManager, itemStack, x, y, discovered ? s : "?", 1.0f);
                     } else {
-                        itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.fontRenderer, mc.renderEngine, itemStack, x, y, discovered ? null : "?", 1.0f);
+                        itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.font, mc.textureManager, itemStack, x, y, discovered ? null : "?", 1.0f);
                     }
                 } else {
-                    itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.fontRenderer, mc.renderEngine, itemStack, x, y, discovered ? null : "?", 1.0f);
+                    itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.font, mc.textureManager, itemStack, x, y, discovered ? null : "?", 1.0f);
                 }
             }
             GL11.glDisable(GL11.GL_DEPTH_TEST);
diff --git a/src/main/java/net/minecraft/client/gui/GuiEditLabel.java b/src/main/java/net/minecraft/client/gui/LabelEditorScreen.java
similarity index 66%
rename from src/main/java/net/minecraft/client/gui/GuiEditLabel.java
rename to src/main/java/net/minecraft/client/gui/LabelEditorScreen.java
index b839adbf9..2625fce85 100644
--- a/src/main/java/net/minecraft/client/gui/GuiEditLabel.java
+++ b/src/main/java/net/minecraft/client/gui/LabelEditorScreen.java
@@ -13,7 +13,7 @@ import org.lwjgl.opengl.GL11;
 //            SignBlockEntity, ClientPacketHandler, Block, BlockEntityRenderer,
 //            ChatAllowedCharacters
 
-public class GuiEditLabel extends GuiScreen
+public class LabelEditorScreen extends Screen
 {
     private static final String allowedCharacters;
 
@@ -29,7 +29,7 @@ public class GuiEditLabel extends GuiScreen
     protected int ySize;
     protected int slot;
 
-    public GuiEditLabel(final ItemStack item, int slot)
+    public LabelEditorScreen(final ItemStack item, int slot)
     {
         screenTitle = I18n.getInstance().translateKey("gui.edit_label.label.title");
         this.item = item;
@@ -45,7 +45,7 @@ public class GuiEditLabel extends GuiScreen
     }
 
     @Override
-    protected void buttonPressed(final GuiButton button)
+    protected void buttonClicked(final ButtonElement button)
     {
         if (!button.enabled)
         {
@@ -54,7 +54,7 @@ public class GuiEditLabel extends GuiScreen
         if (button.id == 0)
         {
         	item.setCustomName(text);
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
 
             if (mc.theWorld.isClientSide)
             {
@@ -64,49 +64,49 @@ public class GuiEditLabel extends GuiScreen
     }
 
     @Override
-    public void drawScreen(final int mouseX, final int mouseY, final float f)
+    public void render(final int xm, final int ym, final float f)
     {
-        drawDefaultBackground();
+        renderBackground();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/scroll.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/scroll.png").bind();
         final int widthBG = width / 2 - 56;
         final int heightBG = 89;
         drawTexturedModalRect(widthBG, heightBG, 0, 0, 113, 34);
 
-        drawStringCentered(fontRenderer, screenTitle, width / 2, 40, 0xffffff);
+        drawStringCentered(font, screenTitle, width / 2, 40, 0xffffff);
 
-        drawStringCentered(fontRenderer, TextFormatting.get(color) + "> " + text + " <", width / 2, 100, 0xffffff);
+        drawStringCentered(font, TextFormatting.get(color) + "> " + text + " <", width / 2, 100, 0xffffff);
 
-        super.drawScreen(mouseX, mouseY, f);
+        super.render(xm, ym, f);
     }
 
     @Override
     public void init()
     {
-        controlList.clear();
+        buttons.clear();
         Keyboard.enableRepeatEvents(true);
-        controlList.add(new GuiButton(0, width / 2 - 100, height / 4 + 120, I18n.getInstance().translateKey("gui.edit_label.button.done")));
+        buttons.add(new ButtonElement(0, width / 2 - 100, height / 4 + 120, I18n.getInstance().translateKey("gui.edit_label.button.done")));
     }
 
     @Override
-	public void keyTyped(final char c, final int i, int mouseX, int mouseY)
+	public void keyPressed(final char eventCharacter, final int eventKey, int mx, int my)
     {
-        if (i == Keyboard.KEY_BACK && text.length() > 0)
+        if (eventKey == Keyboard.KEY_BACK && text.length() > 0)
         {
             text = text.substring(0, text.length() - 1);
         }
-        if (allowedCharacters.indexOf(c) >= 0 && text.length() < 15)
+        if (allowedCharacters.indexOf(eventCharacter) >= 0 && text.length() < 15)
         {
-            text += c;
+            text += eventCharacter;
         }
-        if (i == Keyboard.KEY_RETURN || i == Keyboard.KEY_ESCAPE)
+        if (eventKey == Keyboard.KEY_RETURN || eventKey == Keyboard.KEY_ESCAPE)
         {
-            buttonPressed(controlList.get(0));
+            buttonClicked(buttons.get(0));
         }
     }
 
     @Override
-    public void onClosed()
+    public void removed()
     {
         Keyboard.enableRepeatEvents(false);
     }
diff --git a/src/main/java/net/minecraft/client/gui/ListLayout.java b/src/main/java/net/minecraft/client/gui/ListLayout.java
index c581b9475..78e4bb70c 100644
--- a/src/main/java/net/minecraft/client/gui/ListLayout.java
+++ b/src/main/java/net/minecraft/client/gui/ListLayout.java
@@ -7,7 +7,7 @@ import java.util.List;
 
 public class ListLayout{
 	
-	public final GuiScreen screen;
+	public final Screen screen;
 	
 	public final List<GuiElement> elements = new ArrayList<>();
 	
@@ -33,7 +33,7 @@ public class ListLayout{
 	private int listWidth;
 	private int listHeight;
 	
-	public ListLayout(GuiScreen screen) {
+	public ListLayout(Screen screen) {
 		this.screen = screen;
 	}
 	
diff --git a/src/main/java/net/minecraft/client/gui/MainMenuBackground.java b/src/main/java/net/minecraft/client/gui/MainMenuBackground.java
index d193389e6..3758e1822 100644
--- a/src/main/java/net/minecraft/client/gui/MainMenuBackground.java
+++ b/src/main/java/net/minecraft/client/gui/MainMenuBackground.java
@@ -13,6 +13,7 @@ import javax.imageio.ImageIO;
 import com.b100.json.element.JsonArray;
 import com.b100.json.element.JsonObject;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.GLAllocation;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.OpenGLHelper;
@@ -21,13 +22,14 @@ import net.minecraft.client.render.texturepack.TexturePack;
 import net.minecraft.client.render.texturepack.TexturePackException;
 import net.minecraft.client.util.helper.TexturePackJsonHelper;
 import net.minecraft.core.util.helper.Buffer;
+import org.slf4j.Logger;
 
 public class MainMenuBackground {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public Minecraft mc;
 	
-	private List<BackgroundListEntry> backgroundList = new ArrayList<>();
-	private Random random = new Random();
+	private final List<BackgroundListEntry> backgroundList = new ArrayList<>();
+	private final Random random = new Random();
 	
 	public MainMenuBackground(Minecraft minecraft) {
 		this.mc = minecraft;
@@ -184,7 +186,7 @@ public class MainMenuBackground {
 	}
 	
 	public boolean isEnabled() {
-		return backgroundList.size() > 0;
+		return !backgroundList.isEmpty();
 	}
 	
 	public void refresh(List<Throwable> errors) {
@@ -216,7 +218,7 @@ public class MainMenuBackground {
 					String name = backgrounds.get(i).getAsString().value;
 					
 					if(!texturePack.hasFile("/bg/" + name + ".png")) {
-						System.out.println("Skipping background '" + name + "'");
+                        LOGGER.warn("Skipping background '{}'", name);
 						continue;
 					}
 					
@@ -232,9 +234,9 @@ public class MainMenuBackground {
 	}
 	
 	public void print() {
-		System.out.println("Backgrounds: ");
+		LOGGER.info("Backgrounds: ");
 		for(BackgroundListEntry bg : backgroundList) {
-			System.out.println("    " + bg);
+            LOGGER.info("    {}", bg);
 		}
 	}
 	
@@ -244,7 +246,7 @@ public class MainMenuBackground {
 		}
 	}
 	
-	class Background {
+	static class Background {
 		
 		public int texture;
 		public int width;
@@ -268,18 +270,11 @@ public class MainMenuBackground {
 		}
 		
 		public BufferedImage loadBackgroundImage() {
-			InputStream stream = null;
-			try {
-				stream = mc.texturePackList.getResourceAsStream("/bg/" + name + ".png");
-				
-				return ImageIO.read(stream);
-			}catch (Exception e) {
-				throw new RuntimeException(e);
-			}finally {
-				try {
-					stream.close();
-				}catch (Exception e) {}
-			}
+            try (InputStream stream = mc.texturePackList.getResourceAsStream("/bg/" + name + ".png")) {
+                return ImageIO.read(stream);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
 		}
 		
 		public String toString() {
diff --git a/src/main/java/net/minecraft/client/gui/GuiMainMenu.java b/src/main/java/net/minecraft/client/gui/MainMenuScreen.java
similarity index 74%
rename from src/main/java/net/minecraft/client/gui/GuiMainMenu.java
rename to src/main/java/net/minecraft/client/gui/MainMenuScreen.java
index 00d4ac2b6..c6b61ee89 100644
--- a/src/main/java/net/minecraft/client/gui/GuiMainMenu.java
+++ b/src/main/java/net/minecraft/client/gui/MainMenuScreen.java
@@ -15,6 +15,9 @@ import java.util.Random;
 
 import javax.imageio.ImageIO;
 
+import com.mojang.logging.LogUtils;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.DoomIngameHud;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
@@ -24,7 +27,7 @@ import org.lwjgl.opengl.GL11;
 import org.lwjgl.util.glu.GLU;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.options.GuiOptions;
+import net.minecraft.client.gui.options.OptionsScreen;
 import net.minecraft.client.gui.options.data.OptionsPages;
 import net.minecraft.client.render.RenderBlocks;
 import net.minecraft.core.block.Block;
@@ -32,9 +35,11 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.MathHelper;
+import org.slf4j.Logger;
 
-public class GuiMainMenu extends GuiScreen
+public class MainMenuScreen extends Screen
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
 
     private static final Block[] BLOCKS_TO_DRAW = {
     		Blocks.STONE, Blocks.DIRT, Blocks.PLANKS_OAK, Blocks.COBBLE_STONE, Blocks.COBBLE_STONE_MOSSY, Blocks.BASALT, Blocks.LIMESTONE,
@@ -50,7 +55,7 @@ public class GuiMainMenu extends GuiScreen
     private static final Random rand = new Random();
     
     private String splashText = "missingno";
-    private GuiButton multiplayerButton;
+    private ButtonElement multiplayerButton;
     private LogoBlock[][] logoBlocks;
     private int logoClickCounter = 0;
     private int indexToDraw = 0;
@@ -61,51 +66,49 @@ public class GuiMainMenu extends GuiScreen
     	loadLogo();
     }
 
-	public GuiMainMenu() {
-		GuiIngameMenu.photoModeDisabled = false;
-
-		InputStream stream = null;
-		try {
-			stream = GuiMainMenu.class.getResourceAsStream("/assets/minecraft/textures/gui/title/splashes.txt");
-
-			List<String> allSplashes = new ArrayList<>();
-			BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
-
-			while(true) {
-				String line = br.readLine();
-				if(line == null) {
-					break;
-				}
-				line = line.trim();
-				if(!line.isEmpty()) {
-					allSplashes.add(line);
-				}
-			}
-			splashText = allSplashes.get(rand.nextInt(allSplashes.size()));
-		}catch (Exception e) {
-
-		}finally {
-			try {
-				stream.close();
-			}catch (Exception e) {}
-		}
+	public MainMenuScreen() {
+		PauseScreen.photoModeDisabled = false;
+
+        try (InputStream stream = MainMenuScreen.class.getResourceAsStream("/assets/minecraft/textures/gui/title/splashes.txt")) {
+
+            if (stream == null) {
+                LOGGER.error("Could not locate 'splashes.txt'! Does the file exist!?");
+                return;
+            }
+            List<String> allSplashes = new ArrayList<>();
+            BufferedReader br = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
+
+            while (true) {
+                String line = br.readLine();
+                if (line == null) {
+                    break;
+                }
+                line = line.trim();
+                if (!line.isEmpty()) {
+                    allSplashes.add(line);
+                }
+            }
+            splashText = allSplashes.get(rand.nextInt(allSplashes.size()));
+        } catch (Exception e) {
+            LOGGER.error("Failed to load splash texts!", e);
+        }
 	}
 
     @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
-        if (i == KEY_CHAIN[codeProgress])
+        if (eventKey == KEY_CHAIN[codeProgress])
         {
             codeProgress++;
             if (codeProgress == KEY_CHAIN.length)
             {
-                if (mc.ingameGUI instanceof GuiIngameDoom)
+                if (mc.ingameHud instanceof DoomIngameHud)
                 {
-                    mc.ingameGUI = new GuiIngame(mc);
+                    mc.ingameHud = new IngameHud(mc);
                 }
                 else
                 {
-                    mc.ingameGUI = new GuiIngameDoom(mc);
+                    mc.ingameHud = new DoomIngameHud(mc);
                 }
                 mc.sndManager.playSound("mob.pig", SoundCategory.GUI_SOUNDS, 1.0F, 1.0F);
                 codeProgress = 0;
@@ -154,27 +157,27 @@ public class GuiMainMenu extends GuiScreen
         }
 
         int i = height / 4 + 48;
-        controlList.add(new GuiButton(1, width / 2 - 100, i, i18n.translateKey("gui.main_menu.button.singleplayer")));
-        controlList.add(multiplayerButton = new GuiButton(2, width / 2 - 100, i + 24, i18n.translateKey("gui.main_menu.button.multiplayer")));
-        controlList.add(new GuiButton(3, width / 2 - 100, i + 48, i18n.translateKey("gui.main_menu.button.texture_packs")));
+        buttons.add(new ButtonElement(1, width / 2 - 100, i, i18n.translateKey("gui.main_menu.button.singleplayer")));
+        buttons.add(multiplayerButton = new ButtonElement(2, width / 2 - 100, i + 24, i18n.translateKey("gui.main_menu.button.multiplayer")));
+        buttons.add(new ButtonElement(3, width / 2 - 100, i + 48, i18n.translateKey("gui.main_menu.button.texture_packs")));
         if(mc.hideQuitButton)
         {
-            controlList.add(new GuiButton(0, width / 2 - 100, i + 72, i18n.translateKey("gui.main_menu.button.options")));
+            buttons.add(new ButtonElement(0, width / 2 - 100, i + 72, i18n.translateKey("gui.main_menu.button.options")));
         } else
         {
-            controlList.add(new GuiButton(0, width / 2 - 100, i + 72 + 12, 98, 20, i18n.translateKey("gui.main_menu.button.options")));
-            controlList.add(new GuiButton(4, width / 2 + 2, i + 72 + 12, 98, 20, i18n.translateKey("gui.main_menu.button.quit_game")));
+            buttons.add(new ButtonElement(0, width / 2 - 100, i + 72 + 12, 98, 20, i18n.translateKey("gui.main_menu.button.options")));
+            buttons.add(new ButtonElement(4, width / 2 + 2, i + 72 + 12, 98, 20, i18n.translateKey("gui.main_menu.button.quit_game")));
         }
         int d = 1; // Move away from the edge of the screen to prevent unintentional activation because the cursor defaults to 0, 0
-        controlList.add(new GuiClickableLabel(5, d, height - 48 - d, i18n.translateKey("gui.main_menu.button.credits"), 0x9F9F9F));
-        controlList.add(new GuiClickableLabel(6, d, height - 36 - d, i18n.translateKey("gui.main_menu.button.website"), 0x5AA938));
-        controlList.add(new GuiClickableLabel(7, d, height - 24 - d, i18n.translateKey("gui.main_menu.button.discord"), 0x5865F2));
-        controlList.add(new GuiClickableLabel(8, d, height - 12 - d, i18n.translateKey("gui.main_menu.button.youtube"), 0xFF0000));
-        controlList.add(new GuiButton(9, width / 2 + 104, i + 72 + 12, 20, 20, "")
+        buttons.add(new ClickableLabelElement(5, d, height - 48 - d, i18n.translateKey("gui.main_menu.button.credits"), 0x9F9F9F));
+        buttons.add(new ClickableLabelElement(6, d, height - 36 - d, i18n.translateKey("gui.main_menu.button.website"), 0x5AA938));
+        buttons.add(new ClickableLabelElement(7, d, height - 24 - d, i18n.translateKey("gui.main_menu.button.discord"), 0x5865F2));
+        buttons.add(new ClickableLabelElement(8, d, height - 12 - d, i18n.translateKey("gui.main_menu.button.youtube"), 0xFF0000));
+        buttons.add(new ButtonElement(9, width / 2 + 104, i + 72 + 12, 20, 20, "")
             .setTextures("minecraft:gui/misc/button_language", "minecraft:gui/misc/button_language_highlighted", "minecraft:gui/misc/button_language"));
-        GuiButton debugButton = new GuiButton(10, width - 8, height - 8, 8, 8, "");
+        ButtonElement debugButton = new ButtonElement(10, width - 8, height - 8, 8, 8, "");
         debugButton.visible = false;
-        controlList.add(debugButton);
+        buttons.add(debugButton);
         if(mc.session == null)
         {
             multiplayerButton.enabled = false;
@@ -187,23 +190,23 @@ public class GuiMainMenu extends GuiScreen
     }
 
     @Override
-    protected void buttonPressed(GuiButton button)
+    protected void buttonClicked(ButtonElement button)
     {
         if(button.id == 0)
         {
-            mc.displayGuiScreen(new GuiOptions(this));
+            mc.displayScreen(new OptionsScreen(this));
         }
         if(button.id == 1)
         {
-            mc.displayGuiScreen(new GuiSelectWorld(this));
+            mc.displayScreen(new SelectWorldScreen(this));
         }
         if(button.id == 2)
         {
-            mc.displayGuiScreen(new GuiSelectServer(this));
+            mc.displayScreen(new SelectServerScreen(this));
         }
         if(button.id == 3)
         {
-            mc.displayGuiScreen(new GuiOptions(this, OptionsPages.TEXTURE_PACKS));
+            mc.displayScreen(new OptionsScreen(this, OptionsPages.TEXTURE_PACKS));
         }
         if(button.id == 4)
         {
@@ -211,14 +214,14 @@ public class GuiMainMenu extends GuiScreen
         }
         if(button.id == 5)
         {
-            mc.displayGuiScreen(new GuiCredits(this));
+            mc.displayScreen(new CreditsScreen(this));
         }
         if(button.id == 9)
         {
-            mc.displayGuiScreen(new GuiOptions(this, OptionsPages.LANGUAGE));
+            mc.displayScreen(new OptionsScreen(this, OptionsPages.LANGUAGE));
         }
         if(button.id == 10){
-            mc.displayGuiScreen(new GuiOptions(this, OptionsPages.DEBUG));
+            mc.displayScreen(new OptionsScreen(this, OptionsPages.DEBUG));
         }
         Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
         if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE))
@@ -230,7 +233,7 @@ public class GuiMainMenu extends GuiScreen
                     desktop.browse(URI.create("https://betterthanadventure.net"));
                 } catch (Exception e)
                 {
-                    e.printStackTrace();
+                    LOGGER.error("Exception occurred when attempting to open URL 'https://betterthanadventure.net'!", e);
                 }
             }
             if (button.id == 7) // Discord
@@ -240,7 +243,7 @@ public class GuiMainMenu extends GuiScreen
                     desktop.browse(URI.create("https://betterthanadventure.net/discord"));
                 } catch (Exception e)
                 {
-                    e.printStackTrace();
+                    LOGGER.error("Exception occurred when attempting to open URL 'https://betterthanadventure.net/discord'!", e);
                 }
             }
             if (button.id == 8) // YouTube
@@ -250,18 +253,18 @@ public class GuiMainMenu extends GuiScreen
                     desktop.browse(URI.create("https://www.youtube.com/channel/UC_GT4t8Io87-UTzaGNnsuMg"));
                 } catch (Exception e)
                 {
-                    e.printStackTrace();
+                    LOGGER.error("Exception occurred when attempting to open URL 'https://www.youtube.com/channel/UC_GT4t8Io87-UTzaGNnsuMg'!", e);
                 }
             }
         }
     }
 
 	@Override
-	public void drawBackground() {
+	public void renderTexturedBackground() {
 		if(mc.mainMenuBackground.isEnabled() && !mc.gameSettings.alphaMenu.value) {
 			mc.mainMenuBackground.draw();
 		}else {
-			super.drawBackground();
+			super.renderTexturedBackground();
 		}
 	}
 
@@ -270,11 +273,9 @@ public class GuiMainMenu extends GuiScreen
     {
         if(this.logoBlocks != null)
         {
-            for(int var1 = 0; var1 < this.logoBlocks.length; ++var1)
-            {
-                for(int var2 = 0; var2 < this.logoBlocks[var1].length; ++var2)
-                {
-                    this.logoBlocks[var1][var2].updateLogoEffects();
+            for (LogoBlock[] logoBlock : this.logoBlocks) {
+                for (LogoBlock block : logoBlock) {
+                    block.updateLogoEffects();
                 }
             }
         }
@@ -282,15 +283,15 @@ public class GuiMainMenu extends GuiScreen
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton)
+    public void mouseClicked(int mx, int my, int buttonNum)
     {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
+        super.mouseClicked(mx, my, buttonNum);
 
-        int logoWidth = '\u0112';
+        int logoWidth = 274;
         int logoX = width / 2 - logoWidth / 2;
         int logoHeight = 30;
         int p = 8;
-        if (mouseX >= logoX + p && mouseX <= logoX + 270 - p && mouseY >= logoHeight + p && mouseY <= logoHeight + 48 - p)
+        if (mx >= logoX + p && mx <= logoX + 270 - p && my >= logoHeight + p && my <= logoHeight + 48 - p)
         {
             if (logoClickCounter >= 0)
             {
@@ -304,9 +305,9 @@ public class GuiMainMenu extends GuiScreen
                 logoClickCounter++;
             }
         }
-        if (mouseY >= 2 && mouseY <= 12)
+        if (my >= 2 && my <= 12)
         {
-            if (mouseX >= 2 && mouseX <= 40)
+            if (mx >= 2 && mx <= 40)
             {
                 showBuildTime = !showBuildTime;
             }
@@ -314,18 +315,18 @@ public class GuiMainMenu extends GuiScreen
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick)
+    public void render(int xm, int ym, float partialTick)
     {
         I18n i18n = I18n.getInstance();
-        drawDefaultBackground();
-        char c = '\u0112';
+        renderBackground();
+        int c = 274;
         int k = width / 2 - c / 2;
         byte byte0 = 30;
         if (!mc.gameSettings.alphaMenu.value)
         {
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/title/mclogo.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/title/mclogo.png").bind();
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-            drawTexturedModalRect(k + 0, byte0 + 0, 0, 0, 274, 50, 1d/274, 1d/50);
+            drawTexturedModalRect(k, byte0, 0, 0, 274, 50, 1d/274, 1d/50);
         }
         else
         {
@@ -335,28 +336,28 @@ public class GuiMainMenu extends GuiScreen
         GL11.glTranslatef(width / 2 + 140, 80F, 0.0F);
         GL11.glRotatef(-20F, 0.0F, 0.0F, 1.0F);
         float f1 = 1.8F - MathHelper.abs(MathHelper.sin(((float)(System.currentTimeMillis() % 1000L) / 1000F) * MathHelper.PI * 2.0F) * 0.1F);
-        f1 = (f1 * 100F) / (float)(fontRenderer.getStringWidth(splashText) + 32);
+        f1 = (f1 * 100F) / (float)(font.getStringWidth(splashText) + 32);
         GL11.glScalef(f1, f1, f1);
-        drawStringCentered(fontRenderer, splashText, 0, -8, 0xffff00);
+        drawStringCentered(font, splashText, 0, -8, 0xffff00);
         GL11.glPopMatrix();
         int versionTextColor = mc.gameSettings.alphaMenu.value || !mc.mainMenuBackground.isEnabled() ? 0x505050 : 0xFFFFFF;
         if (showBuildTime) {
-            drawString(fontRenderer, Global.BUILD_TIME, 2, 2, versionTextColor);
+            drawString(font, Global.BUILD_TIME, 2, 2, versionTextColor);
         } else {
-            drawString(fontRenderer, "Better than Adventure! " + Minecraft.VERSION, 2, 2, versionTextColor);
+            drawString(font, "Better than Adventure! " + Minecraft.VERSION, 2, 2, versionTextColor);
         }
         String disclaimer1 = i18n.translateKey("gui.main_menu.label.disclaimer.1");
-        drawString(fontRenderer, disclaimer1, width - fontRenderer.getStringWidth(disclaimer1) - 2, height - 20, 0xffffff);
+        drawString(font, disclaimer1, width - font.getStringWidth(disclaimer1) - 2, height - 20, 0xffffff);
         String disclaimer2 = i18n.translateKey("gui.main_menu.label.disclaimer.2");
-        drawString(fontRenderer, disclaimer2, width - fontRenderer.getStringWidth(disclaimer2) - 2, height - 10, 0xffffff);
-        super.drawScreen(mouseX, mouseY, partialTick);
+        drawString(font, disclaimer2, width - font.getStringWidth(disclaimer2) - 2, height - 10, 0xffffff);
+        super.render(xm, ym, partialTick);
         
     	if(mc.downloadResourcesThread.downloading) {
     		double b = java.lang.Math.sin((System.currentTimeMillis() / 1000.0) * 4);
     		b = b * 0.2 + 0.8;
     		int ib = (int) java.lang.Math.round(b * 255);
     		int color = 0xFF000000 + (ib << 16) + (ib << 8) + (ib);
-    		mc.fontRenderer.drawCenteredString(
+    		mc.font.drawCenteredString(
                 i18n.translateKeyAndFormat("gui.main_menu.label.downloading_resources", mc.downloadResourcesThread.downloadProgress.get(), mc.downloadResourcesThread.toDownload),
                 width / 2, 16, color);
     	}
@@ -415,7 +416,7 @@ public class GuiMainMenu extends GuiScreen
             GL11.glTranslatef((float)(-logoBlockLayers[0].length()) * 0.5F, (float)(-logoBlockLayers.length) * 0.5F, 0.0F);
             TextureRegistry.blockAtlas.bind();
             if(var4 == 0) {
-                this.mc.renderEngine.loadTexture("/title/black.png").bind();
+                this.mc.textureManager.loadTexture("/title/black.png").bind();
             }
 
             RenderBlocks var5 = new RenderBlocks();
@@ -462,10 +463,10 @@ public class GuiMainMenu extends GuiScreen
     
     public static void loadLogo() {
     	try {
-    		InputStream inputStream = GuiMainMenu.class.getResourceAsStream("/assets/minecraft/textures/gui/title/retrologo.png");
+    		InputStream inputStream = MainMenuScreen.class.getResourceAsStream("/assets/minecraft/textures/gui/title/retrologo.png");
     		BufferedImage image = ImageIO.read(inputStream);
     		inputStream.close();
-    		
+
     		logoBlockLayers = new String[image.getHeight()];
     		
     		for(int i=0; i < image.getHeight(); i++) {
@@ -484,11 +485,11 @@ public class GuiMainMenu extends GuiScreen
     			logoBlockLayers[i] = builder.toString();
     		}
     	}catch (Exception e) {
-    		e.printStackTrace();
+            LOGGER.error("Exception while loading retro logo!", e);
 		}
     }
     
-    class LogoBlock {
+    static class LogoBlock {
     	
         public double height;
         public double prevHeight;
diff --git a/src/main/java/net/minecraft/client/gui/GuiMissingMinecraft.java b/src/main/java/net/minecraft/client/gui/MissingMinecraftScreen.java
similarity index 60%
rename from src/main/java/net/minecraft/client/gui/GuiMissingMinecraft.java
rename to src/main/java/net/minecraft/client/gui/MissingMinecraftScreen.java
index 8d649f6ea..4efb5c71e 100644
--- a/src/main/java/net/minecraft/client/gui/GuiMissingMinecraft.java
+++ b/src/main/java/net/minecraft/client/gui/MissingMinecraftScreen.java
@@ -1,41 +1,44 @@
 package net.minecraft.client.gui;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.helper.MathHelper;
 import org.lwjgl.opengl.GL11;
+import org.slf4j.Logger;
 
 import java.awt.*;
 import java.net.URI;
 
-public class GuiMissingMinecraft extends GuiScreen{
+public class MissingMinecraftScreen extends Screen {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public int ticks = 0;
     @Override
     public void init()
     {
         I18n i = I18n.getInstance();
-        controlList.clear();
+        buttons.clear();
         String downloadString = i.translateKey("gui.no_minecraft.button.guide");
-        controlList.add(new GuiButton(0, width / 2 - 100, height / 4 + 120 + 12, i.translateKey("gui.no_minecraft.button.quit")));
-        GuiClickableLabel installLabel = new GuiClickableLabel(1, width / 2 - 170, (height / 4 - 60) + 60 + 64, downloadString, 0x7C99EA);
-        controlList.add(installLabel);
-        controlList.add(new GuiClickableLabel(2, 0,  height - fontRenderer.fontHeight - 4, i.translateKey("gui.main_menu.button.discord"), 0x5865F2));
+        buttons.add(new ButtonElement(0, width / 2 - 100, height / 4 + 120 + 12, i.translateKey("gui.no_minecraft.button.quit")));
+        ClickableLabelElement installLabel = new ClickableLabelElement(1, width / 2 - 170, (height / 4 - 60) + 60 + 64, downloadString, 0x7C99EA);
+        buttons.add(installLabel);
+        buttons.add(new ClickableLabelElement(2, 0,  height - font.fontHeight - 4, i.translateKey("gui.main_menu.button.discord"), 0x5865F2));
     }
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick)
+    public void render(int xm, int ym, float partialTick)
     {
         I18n i = I18n.getInstance();
         drawBackground(partialTick);
-        drawStringCentered(fontRenderer, i.translateKey("gui.no_minecraft.label.title"), width / 2, (height / 4 - 60) + 20, 0xffff60);
-        drawString(fontRenderer, i.translateKey("gui.no_minecraft.label.body.1"), width / 2 - 170, (height / 4 - 60) + 60 + 0, 0xdedede);
-        drawString(fontRenderer, i.translateKey("gui.no_minecraft.label.body.2"), width / 2 - 170, (height / 4 - 60) + 60 + 18, 0xdedede);
-        drawString(fontRenderer, i.translateKey("gui.no_minecraft.label.body.3"), width / 2 - 170, (height / 4 - 60) + 60 + 27, 0xdedede);
-        drawString(fontRenderer, i.translateKey("gui.no_minecraft.label.body.4"), width / 2 - 170, (height / 4 - 60) + 60 + 45, 0xdedede);
-        drawString(fontRenderer, i.translateKey("gui.no_minecraft.label.body.5"), width / 2 - 170, (height / 4 - 60) + 60 + 54, 0xdedede);
-        super.drawScreen(mouseX, mouseY, partialTick);
+        drawStringCentered(font, i.translateKey("gui.no_minecraft.label.title"), width / 2, (height / 4 - 60) + 20, 0xffff60);
+        drawString(font, i.translateKey("gui.no_minecraft.label.body.1"), width / 2 - 170, (height / 4 - 60) + 60 + 0, 0xdedede);
+        drawString(font, i.translateKey("gui.no_minecraft.label.body.2"), width / 2 - 170, (height / 4 - 60) + 60 + 18, 0xdedede);
+        drawString(font, i.translateKey("gui.no_minecraft.label.body.3"), width / 2 - 170, (height / 4 - 60) + 60 + 27, 0xdedede);
+        drawString(font, i.translateKey("gui.no_minecraft.label.body.4"), width / 2 - 170, (height / 4 - 60) + 60 + 45, 0xdedede);
+        drawString(font, i.translateKey("gui.no_minecraft.label.body.5"), width / 2 - 170, (height / 4 - 60) + 60 + 54, 0xdedede);
+        super.render(xm, ym, partialTick);
     }
     @Override
-    protected void buttonPressed(GuiButton button)
+    protected void buttonClicked(ButtonElement button)
     {
         if(!button.enabled)
         {
@@ -56,13 +59,13 @@ public class GuiMissingMinecraft extends GuiScreen{
                 }
                 catch (Exception e)
                 {
-                    e.printStackTrace();
+                    LOGGER.error("Exception occurred when attempting to open URL 'https://www.betterthanadventure.net/installation-guide/'!", e);
                 }
             } else if (button.id == 2) {
                 try {
                     desktop.browse(URI.create("https://betterthanadventure.net/discord"));
                 } catch (Exception e){
-                    e.printStackTrace();
+                    LOGGER.error("Exception occurred when attempting to open URL 'https://betterthanadventure.net/discord'!", e);
                 }
             }
         }
@@ -78,7 +81,7 @@ public class GuiMissingMinecraft extends GuiScreen{
         GL11.glDisable(GL11.GL_FOG);
 
         Tessellator tessellator = Tessellator.instance;
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/block/netherrack_mossy.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/block/netherrack_mossy.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         GL11.glEnable(GL11.GL_BLEND);
 
@@ -92,7 +95,7 @@ public class GuiMissingMinecraft extends GuiScreen{
         tessellator.addVertexWithUV(0.0D, 0.0D, 0.0D, 0.0D, 0);
         tessellator.draw();
 
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/block/dirt.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/block/dirt.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0f);
 
         // Then Draw dirt texture
diff --git a/src/main/java/net/minecraft/client/gui/GuiPickMonster.java b/src/main/java/net/minecraft/client/gui/MobPickerScreen.java
similarity index 90%
rename from src/main/java/net/minecraft/client/gui/GuiPickMonster.java
rename to src/main/java/net/minecraft/client/gui/MobPickerScreen.java
index 807b4c278..e7090be26 100644
--- a/src/main/java/net/minecraft/client/gui/GuiPickMonster.java
+++ b/src/main/java/net/minecraft/client/gui/MobPickerScreen.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.popup.GuiPopup;
+import net.minecraft.client.gui.popup.PopupScreen;
 import net.minecraft.client.gui.popup.PopupBuilder;
 import net.minecraft.core.block.entity.MobSpawnerBlockEntity;
 import net.minecraft.core.entity.Entity;
@@ -14,8 +14,8 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-public class GuiPickMonster
-    extends GuiScreen {
+public class MobPickerScreen
+    extends Screen {
     private final int x;
     private final int y;
     private final int z;
@@ -23,7 +23,7 @@ public class GuiPickMonster
     private boolean shouldClose = false;
 
 
-    public GuiPickMonster(String mobId, int x, int y, int z) {
+    public MobPickerScreen(String mobId, int x, int y, int z) {
         this.mobId = mobId;
         this.x = x;
         this.y = y;
@@ -52,7 +52,7 @@ public class GuiPickMonster
             prettyMonsters.add(sb.toString());
         }
 
-        GuiPopup popup = new PopupBuilder(this, 150)
+        PopupScreen popup = new PopupBuilder(this, 150)
             .withLabel("gui.pick_monster.label.title")
             .withList("list", 140, prettyMonsters.toArray(new String[0]), null, -1, true)
             .closeOnEsc(0)
@@ -73,14 +73,14 @@ public class GuiPickMonster
                 shouldClose = true;
             })
             .build();
-        mc.displayGuiScreen(popup);
+        mc.displayScreen(popup);
     }
 
     @Override
     public void tick() {
         super.tick();
         if (shouldClose) {
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
         }
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/OutOfMemoryScreen.java b/src/main/java/net/minecraft/client/gui/OutOfMemoryScreen.java
new file mode 100644
index 000000000..480703a70
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/OutOfMemoryScreen.java
@@ -0,0 +1,29 @@
+package net.minecraft.client.gui;
+
+
+// Referenced classes of package net.minecraft.src:
+//            GuiScreen, GuiButton
+
+import net.minecraft.core.lang.I18n;
+
+public class OutOfMemoryScreen extends Screen
+{
+    @Override
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
+    }
+
+    @Override
+	public void render(int xm, int ym, float partialTick)
+    {
+        I18n i18n = I18n.getInstance();
+        renderBackground();
+        drawStringCentered(font, i18n.translateKey("gui.out_of_memory.label.title"), width / 2, (height / 4 - 60) + 20, 0xFFFFFF);
+        drawString(font, i18n.translateKey("gui.out_of_memory.label.body.1"), width / 2 - 140, (height / 4 - 60) + 60 + 0, 0xA0A0A0);
+        drawString(font, i18n.translateKey("gui.out_of_memory.label.body.2"), width / 2 - 140, (height / 4 - 60) + 60 + 18, 0xA0A0A0);
+        drawString(font, i18n.translateKey("gui.out_of_memory.label.body.3"), width / 2 - 140, (height / 4 - 60) + 60 + 27, 0xA0A0A0);
+        drawString(font, i18n.translateKey("gui.out_of_memory.label.body.4"), width / 2 - 140, (height / 4 - 60) + 60 + 36, 0xA0A0A0);
+        drawString(font, i18n.translateKey("gui.out_of_memory.label.body.5"), width / 2 - 140, (height / 4 - 60) + 60 + 45, 0xA0A0A0);
+        drawString(font, i18n.translateKey("gui.out_of_memory.label.body.6"), width / 2 - 140, (height / 4 - 60) + 60 + 63, 0xA0A0A0);
+        super.render(xm, ym, partialTick);
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/GuiPaintingPicker.java b/src/main/java/net/minecraft/client/gui/PaintingPickerScreen.java
similarity index 86%
rename from src/main/java/net/minecraft/client/gui/GuiPaintingPicker.java
rename to src/main/java/net/minecraft/client/gui/PaintingPickerScreen.java
index 11cae75ca..3361b836f 100644
--- a/src/main/java/net/minecraft/client/gui/GuiPaintingPicker.java
+++ b/src/main/java/net/minecraft/client/gui/PaintingPickerScreen.java
@@ -14,15 +14,15 @@ import java.util.List;
 import static org.lwjgl.opengl.GL11.*;
 import static org.lwjgl.opengl.GL11.GL_BLEND;
 
-public class GuiPaintingPicker
-    extends GuiScreen
+public class PaintingPickerScreen
+    extends Screen
 {
     private final Player player;
     private final List<ArtEntry> artEntries = new ArrayList<>();
     private ArtType centerArt = ArtType.Kebab;
     private int tallestSize = 0;
 
-    public GuiPaintingPicker(Player player)
+    public PaintingPickerScreen(Player player)
     {
         this.player = player;
         for (ArtType art : ArtType.values){
@@ -38,9 +38,9 @@ public class GuiPaintingPicker
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick)
+    public void render(int xm, int ym, float partialTick)
     {
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
 
         float dWheel = Mouse.getDWheel();
         if (dWheel < 0)
@@ -54,23 +54,23 @@ public class GuiPaintingPicker
             updateArtEntries();
         }
 
-        drawPaintings(width, height, mouseX, mouseY);
+        drawPaintings(width, height, xm, ym);
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton)
+    public void mouseClicked(int mx, int my, int buttonNum)
     {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
+        super.mouseClicked(mx, my, buttonNum);
         int scale = getScale(width, height);
 
-        if (mouseButton == 0)
+        if (buttonNum == 0)
         {
             for (ArtEntry artEntry : artEntries)
             {
-                if (mouseX >= artEntry.x && mouseX <= artEntry.x + artEntry.art.sizeX * scale && mouseY >= artEntry.y && mouseY <= artEntry.y + artEntry.art.sizeY * scale)
+                if (mx >= artEntry.x && mx <= artEntry.x + artEntry.art.sizeX * scale && my >= artEntry.y && my <= artEntry.y + artEntry.art.sizeY * scale)
                 {
                     mc.playerController.setPaintingType(artEntry.art);
-                    mc.displayGuiScreen(null);
+                    mc.displayScreen(null);
                     break;
                 }
             }
@@ -126,8 +126,8 @@ public class GuiPaintingPicker
 
         glEnable(GL_TEXTURE_2D);
 
-        drawString(fontRenderer, centerArt.title, centerX - offsetX, centerY + (centerArt.sizeY / 2) * scale + 4, 0xFFFFFFFF);
-        drawString(fontRenderer, centerArt.artist, centerX - offsetX, centerY + (centerArt.sizeY / 2) * scale + 16, 0x7F7F7F7F);
+        drawString(font, centerArt.title, centerX - offsetX, centerY + (centerArt.sizeY / 2) * scale + 4, 0xFFFFFFFF);
+        drawString(font, centerArt.artist, centerX - offsetX, centerY + (centerArt.sizeY / 2) * scale + 16, 0x7F7F7F7F);
 
         glEnable(GL_BLEND);
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
diff --git a/src/main/java/net/minecraft/client/gui/GuiIngameMenu.java b/src/main/java/net/minecraft/client/gui/PauseScreen.java
similarity index 62%
rename from src/main/java/net/minecraft/client/gui/GuiIngameMenu.java
rename to src/main/java/net/minecraft/client/gui/PauseScreen.java
index 42bdf4baf..deb18a47e 100644
--- a/src/main/java/net/minecraft/client/gui/GuiIngameMenu.java
+++ b/src/main/java/net/minecraft/client/gui/PauseScreen.java
@@ -1,10 +1,10 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.achievements.GuiAchievements;
-import net.minecraft.client.gui.guidebook.GuiGuidebook;
+import net.minecraft.client.gui.achievements.AchievementsScreen;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.gui.guidebook.PageManager;
 import net.minecraft.client.gui.guidebook.search.SearchPage;
-import net.minecraft.client.gui.options.GuiOptions;
+import net.minecraft.client.gui.options.OptionsScreen;
 import net.minecraft.client.gui.options.data.OptionsPages;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.data.registry.recipe.SearchQuery;
@@ -19,10 +19,10 @@ import net.minecraft.client.input.InputType;
 //            StatList, StatFileWriter, World, GuiMainMenu, 
 //            GuiAchievements, GuiStats, MathHelper
 
-public class GuiIngameMenu extends GuiScreen
+public class PauseScreen extends Screen
 {
 
-    public GuiIngameMenu()
+    public PauseScreen()
     {
         updateCounter2 = 0;
         updateCounter = 0;
@@ -33,34 +33,34 @@ public class GuiIngameMenu extends GuiScreen
     {
         I18n i = I18n.getInstance();
         updateCounter2 = 0;
-        controlList.clear();
+        buttons.clear();
         byte byte0 = -16;
-        controlList.add(new GuiButton(1, width / 2 - 100, height / 4 + 120 + byte0, i.translateKey("gui.ingame_menu.button.save_and_quit")));
+        buttons.add(new ButtonElement(1, width / 2 - 100, height / 4 + 120 + byte0, i.translateKey("gui.ingame_menu.button.save_and_quit")));
         if(mc.isMultiplayerWorld())
         {
-            controlList.get(0).displayString = i.translateKey("gui.ingame_menu.button.disconnect");
+            buttons.get(0).displayString = i.translateKey("gui.ingame_menu.button.disconnect");
         }
-        controlList.add(new GuiButton(4, width / 2 - 100, height / 4 + 24 + byte0, i.translateKey("gui.ingame_menu.button.back_to_game")));
-        controlList.add(new GuiButton(0, width / 2 - 100, height / 4 + 96 + byte0, 98, 20, i.translateKey("gui.ingame_menu.button.options")));
-        GuiButton photoModeButton = new GuiButton(7, width / 2 + 2, height / 4 + 96 + byte0, 98, 20, i.translateKey("gui.ingame_menu.button.photo_mode"));
-        controlList.add(photoModeButton);
+        buttons.add(new ButtonElement(4, width / 2 - 100, height / 4 + 24 + byte0, i.translateKey("gui.ingame_menu.button.back_to_game")));
+        buttons.add(new ButtonElement(0, width / 2 - 100, height / 4 + 96 + byte0, 98, 20, i.translateKey("gui.ingame_menu.button.options")));
+        ButtonElement photoModeButton = new ButtonElement(7, width / 2 + 2, height / 4 + 96 + byte0, 98, 20, i.translateKey("gui.ingame_menu.button.photo_mode"));
+        buttons.add(photoModeButton);
         if (photoModeDisabled)
         {
             photoModeButton.enabled = false;
         }
-        controlList.add(new GuiButton(5, width / 2 - 100, height / 4 + 48 + byte0, 98, 20, I18n.getInstance().translateKey("gui.ingame_menu.button.achievements")));
-        controlList.add(new GuiButton(6, width / 2 + 2, height / 4 + 48 + byte0, 98, 20, I18n.getInstance().translateKey("gui.ingame_menu.button.statistics")));
-        GuiButton debugButton = new GuiButton(9, width - 8, height - 8, 8, 8, "");
+        buttons.add(new ButtonElement(5, width / 2 - 100, height / 4 + 48 + byte0, 98, 20, I18n.getInstance().translateKey("gui.ingame_menu.button.achievements")));
+        buttons.add(new ButtonElement(6, width / 2 + 2, height / 4 + 48 + byte0, 98, 20, I18n.getInstance().translateKey("gui.ingame_menu.button.statistics")));
+        ButtonElement debugButton = new ButtonElement(9, width - 8, height - 8, 8, 8, "");
         debugButton.visible = false;
-        controlList.add(debugButton);
+        buttons.add(debugButton);
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
         if(button.id == 0)
         {
-            mc.displayGuiScreen(new GuiOptions(this));
+            mc.displayScreen(new OptionsScreen(this));
         }
         if(button.id == 1)
         {
@@ -71,14 +71,14 @@ public class GuiIngameMenu extends GuiScreen
                 Registries.RECIPES = Registries.RECIPES_LOCAL_COPY;
                 SearchPage.searchField.setText("");
                 PageManager.searchQuery = SearchQuery.resolve(SearchPage.searchField.getText());
-                GuiGuidebook.getPageManager().updatePages();
+                GuidebookScreen.getPageManager().updatePages();
             }
             mc.changeWorld(null);
-            mc.displayGuiScreen(new GuiMainMenu());
+            mc.displayScreen(new MainMenuScreen());
         }
         if(button.id == 4)
         {
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
             mc.setIngameFocus();
             
             //Cancel A press so you dont jump because you hold the jump button
@@ -87,18 +87,18 @@ public class GuiIngameMenu extends GuiScreen
         }
         if(button.id == 5)
         {
-            mc.displayGuiScreen(new GuiAchievements(this, mc.statsCounter));
+            mc.displayScreen(new AchievementsScreen(this, mc.statsCounter));
         }
         if(button.id == 6)
         {
-            mc.displayGuiScreen(new GuiStats(this, mc.statsCounter));
+            mc.displayScreen(new StatsScreen(this, mc.statsCounter));
         }
         if (button.id == 7)
         {
-            mc.displayGuiScreen(new GuiPhotoMode());
+            mc.displayScreen(new PhotoModeScreen());
         }
         if(button.id == 9){
-            mc.displayGuiScreen(new GuiOptions(this, OptionsPages.DEBUG));
+            mc.displayScreen(new OptionsScreen(this, OptionsPages.DEBUG));
         }
     }
 
@@ -110,12 +110,12 @@ public class GuiIngameMenu extends GuiScreen
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
         I18n i = I18n.getInstance();
-        drawDefaultBackground();
+        renderBackground();
         if(mc == null || mc.theWorld == null) {
-        	mc.displayGuiScreen(null);
+        	mc.displayScreen(null);
         	return;
         }
         boolean isSaving = !mc.theWorld.pauseScreenSave(updateCounter2++);
@@ -124,12 +124,12 @@ public class GuiIngameMenu extends GuiScreen
             float f1 = ((float)(updateCounter % 10) + partialTick) / 10F;
             f1 = MathHelper.sin(f1 * MathHelper.PI * 2.0F) * 0.2F + 0.8F;
             int k = (int)(255F * f1);
-            drawString(fontRenderer, i.translateKey("gui.ingame_menu.label.saving"), 8, height - 16, k << 16 | k << 8 | k);
+            drawString(font, i.translateKey("gui.ingame_menu.label.saving"), 8, height - 16, k << 16 | k << 8 | k);
         }
-        drawStringCentered(fontRenderer, i.translateKey("gui.ingame_menu.label.title"), width / 2, 40, 0xffffff);
+        drawStringCentered(font, i.translateKey("gui.ingame_menu.label.title"), width / 2, 40, 0xffffff);
         String score = TextFormatting.YELLOW.toString() + mc.thePlayer.getScore();
-        drawStringCentered(fontRenderer, i.translateKeyAndFormat("gui.ingame_menu.label.score", score), width / 2, 56, 0xfefefe);
-        super.drawScreen(mouseX, mouseY, partialTick);
+        drawStringCentered(font, i.translateKeyAndFormat("gui.ingame_menu.label.score", score), width / 2, 56, 0xfefefe);
+        super.render(xm, ym, partialTick);
     }
 
     private int updateCounter2;
diff --git a/src/main/java/net/minecraft/client/gui/GuiPhotoMode.java b/src/main/java/net/minecraft/client/gui/PhotoModeScreen.java
similarity index 78%
rename from src/main/java/net/minecraft/client/gui/GuiPhotoMode.java
rename to src/main/java/net/minecraft/client/gui/PhotoModeScreen.java
index b79ddf22d..ec048745e 100644
--- a/src/main/java/net/minecraft/client/gui/GuiPhotoMode.java
+++ b/src/main/java/net/minecraft/client/gui/PhotoModeScreen.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.core.Global;
 import net.minecraft.core.util.helper.Utils;
 import net.minecraft.core.world.season.Season;
@@ -19,21 +19,21 @@ import net.minecraft.core.util.helper.ScreenShot;
 import java.io.File;
 import java.util.Locale;
 
-public class GuiPhotoMode extends GuiScreen
+public class PhotoModeScreen extends Screen
 {
-    private GuiButton buttonRotateLeft;
-    private GuiButton buttonRotateRight;
-    private GuiButton buttonCenterScreen;
-    private GuiSlider sliderTimeOfDay;
-    private GuiButton buttonSeason;
-    private GuiButton buttonTakeScreenshot;
-    private GuiListenerButton buttonOpenScreenshotFolder;
-    private GuiButton buttonExit;
-    private GuiSlider sliderFog;
-    private GuiSlider sliderTilt;
-    private GuiButton buttonShaders;
-    private GuiSlider sliderIntensity;
-    private GuiButton buttonShowPlayer;
+    private ButtonElement buttonRotateLeft;
+    private ButtonElement buttonRotateRight;
+    private ButtonElement buttonCenterScreen;
+    private SliderElement sliderTimeOfDay;
+    private ButtonElement buttonSeason;
+    private ButtonElement buttonTakeScreenshot;
+    private ListenerButtonElement buttonOpenScreenshotFolder;
+    private ButtonElement buttonExit;
+    private SliderElement sliderFog;
+    private SliderElement sliderTilt;
+    private ButtonElement buttonShaders;
+    private SliderElement sliderIntensity;
+    private ButtonElement buttonShowPlayer;
 
     private final long originalTOD;
     private long desiredTOD = -1;
@@ -79,7 +79,7 @@ public class GuiPhotoMode extends GuiScreen
     
     protected boolean showHelpText = true;
 
-    public GuiPhotoMode()
+    public PhotoModeScreen()
     {
         Minecraft mc = Minecraft.getMinecraft(this);
 
@@ -129,12 +129,12 @@ public class GuiPhotoMode extends GuiScreen
 
         I18n i18n = I18n.getInstance();
 
-        buttonExit = new GuiButton(5, 0, 0, 20, 20, "X");
+        buttonExit = new ButtonElement(5, 0, 0, 20, 20, "X");
 
-        buttonRotateLeft = new GuiButton(0, width / 2 - 59 - 2 - 20, height - 20, 20, 20, "<");
-        buttonRotateRight = new GuiButton(1, width / 2 + 59 + 2 + 1, height - 20, 20, 20, ">");
-        buttonTakeScreenshot = new GuiButton(4, width / 2 - 59, height - 20, 98, 20, i18n.translateKey("gui.photo_mode.button.take_screenshot"));
-        buttonOpenScreenshotFolder = (GuiListenerButton) new GuiListenerButton(30, buttonTakeScreenshot.getWidth() + buttonTakeScreenshot.getX() + 1, buttonTakeScreenshot.getY(), 20, 20, "")
+        buttonRotateLeft = new ButtonElement(0, width / 2 - 59 - 2 - 20, height - 20, 20, 20, "<");
+        buttonRotateRight = new ButtonElement(1, width / 2 + 59 + 2 + 1, height - 20, 20, 20, ">");
+        buttonTakeScreenshot = new ButtonElement(4, width / 2 - 59, height - 20, 98, 20, i18n.translateKey("gui.photo_mode.button.take_screenshot"));
+        buttonOpenScreenshotFolder = (ListenerButtonElement) new ListenerButtonElement(30, buttonTakeScreenshot.getWidth() + buttonTakeScreenshot.getX() + 1, buttonTakeScreenshot.getY(), 20, 20, "")
             .setTextures("minecraft:gui/misc/button_folder", "minecraft:gui/misc/button_folder_highlighted", "minecraft:gui/misc/button_folder");
         buttonOpenScreenshotFolder.setActionListener(() -> {
             File f = new File(mc.getMinecraftDir(), "screenshots");
@@ -142,50 +142,50 @@ public class GuiPhotoMode extends GuiScreen
             Utils.openDirectory(f);
         });
 
-        buttonCenterScreen = new GuiButton(10, width - 120, 0, 120, 20, i18n.translateKey("gui.photo_mode.button.center_camera"));
-        buttonShowPlayer = new GuiButton(11, width - 120, 0, 120, 20, "");
-        sliderTimeOfDay = new GuiSlider(2, width - 120, 0, 120, 20, "", 0.0f);
-        buttonSeason = new GuiButton(3, width - 120, 0, 120, 20, "");
-        sliderFog = new GuiSlider(6, width - 120, 0, 120, 20, "", 1.0f);
-        sliderTilt = new GuiSlider(7, width - 120, 0, 120, 20, "", 30f / 90f);
+        buttonCenterScreen = new ButtonElement(10, width - 120, 0, 120, 20, i18n.translateKey("gui.photo_mode.button.center_camera"));
+        buttonShowPlayer = new ButtonElement(11, width - 120, 0, 120, 20, "");
+        sliderTimeOfDay = new SliderElement(2, width - 120, 0, 120, 20, "", 0.0f);
+        buttonSeason = new ButtonElement(3, width - 120, 0, 120, 20, "");
+        sliderFog = new SliderElement(6, width - 120, 0, 120, 20, "", 1.0f);
+        sliderTilt = new SliderElement(7, width - 120, 0, 120, 20, "", 30f / 90f);
         if(Shaders.enableShaders) {
-            buttonShaders = new GuiButton(8, width - 120, 0, 120, 20, "");
-            sliderIntensity = new GuiSlider(9, width - 120, 0, 120, 20, "", intensityValue);
+            buttonShaders = new ButtonElement(8, width - 120, 0, 120, 20, "");
+            sliderIntensity = new SliderElement(9, width - 120, 0, 120, 20, "", intensityValue);
             
             if (photoModeRenderer.getActiveShader() == null) {
                 sliderIntensity.enabled = false;
             }
         }
 
-        controlList.add(buttonCenterScreen);
-        controlList.add(buttonShowPlayer);
-        controlList.add(sliderTilt);
+        buttons.add(buttonCenterScreen);
+        buttons.add(buttonShowPlayer);
+        buttons.add(sliderTilt);
         
         if(Shaders.enableShaders) {
             mc.setRenderer(photoModeRenderer);
         }
 
         if (!mc.theWorld.isClientSide) {
-            controlList.add(sliderTimeOfDay);
-            controlList.add(sliderFog);
-            controlList.add(buttonSeason);
+            buttons.add(sliderTimeOfDay);
+            buttons.add(sliderFog);
+            buttons.add(buttonSeason);
         }
         
         if(Shaders.enableShaders) {
-            controlList.add(buttonShaders);
-            controlList.add(sliderIntensity);
+            buttons.add(buttonShaders);
+            buttons.add(sliderIntensity);
         }
 
         int i=0;
-        for(GuiButton button : controlList) {
+        for(ButtonElement button : buttons) {
             button.yPosition = i++ * 21;
         }
 
-        controlList.add(buttonRotateLeft);
-        controlList.add(buttonRotateRight);
-        controlList.add(buttonTakeScreenshot);
-        controlList.add(buttonOpenScreenshotFolder);
-        controlList.add(buttonExit);
+        buttons.add(buttonRotateLeft);
+        buttons.add(buttonRotateRight);
+        buttons.add(buttonTakeScreenshot);
+        buttons.add(buttonOpenScreenshotFolder);
+        buttons.add(buttonExit);
 
         if (desiredTOD == -1)
         {
@@ -202,7 +202,7 @@ public class GuiPhotoMode extends GuiScreen
     }
 
     @Override
-    public void onClosed()
+    public void removed()
     {
         mc.theWorld.setWorldTimeUpdateTicks(originalTOD);
         
@@ -214,7 +214,7 @@ public class GuiPhotoMode extends GuiScreen
     }
 
     @Override
-    protected void buttonPressed(GuiButton button)
+    protected void buttonClicked(ButtonElement button)
     {
         if (button == buttonRotateLeft)
         {
@@ -249,7 +249,7 @@ public class GuiPhotoMode extends GuiScreen
         }
         else if (button == buttonExit)
         {
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
         }
         else if (button == buttonShaders)
         {
@@ -277,29 +277,29 @@ public class GuiPhotoMode extends GuiScreen
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton)
+    public void mouseClicked(int mx, int my, int buttonNum)
     {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
+        super.mouseClicked(mx, my, buttonNum);
 
-        if (!isMouseDown && selectedButton == null)
+        if (!isMouseDown && clickedButton == null)
         {
             showHelpText = false;
             isMouseDown = true;
-            mouseDownX = mouseX;
-            mouseDownY = mouseY;
+            mouseDownX = mx;
+            mouseDownY = my;
             lastEndPanX = iPanX;
             lastEndPanY = iPanY;
             lastEndRotation = iRotation;
-            this.mouseButton = mouseButton;
+            this.mouseButton = buttonNum;
         }
     }
 
     @Override
-    public void mouseMovedOrButtonReleased(int mouseX, int mouseY, int mouseButton)
+    public void mouseReleased(int mx, int my, int buttonNum)
     {
-        super.mouseMovedOrButtonReleased(mouseX, mouseY, mouseButton);
+        super.mouseReleased(mx, my, buttonNum);
 
-        if (isMouseDown && mouseButton != -1)
+        if (isMouseDown && buttonNum != -1)
         {
             isMouseDown = false;
         }
@@ -308,19 +308,19 @@ public class GuiPhotoMode extends GuiScreen
             if (this.mouseButton == 0)
             {
                 float div = (float)Math.pow(2, iZoom) / 3;
-                iPanXGoal = lastEndPanX + (mouseX - mouseDownX) / div;
-                iPanYGoal = lastEndPanY + (mouseY - mouseDownY) / div;
+                iPanXGoal = lastEndPanX + (mx - mouseDownX) / div;
+                iPanYGoal = lastEndPanY + (my - mouseDownY) / div;
             }
             else
             {
-                iRotationGoal = lastEndRotation + (mouseX - mouseDownX) / 128f;
+                iRotationGoal = lastEndRotation + (mx - mouseDownX) / 128f;
             }
         }
     }
 
     protected long lastUpdateTime = 0;
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick)
+    public void render(int xm, int ym, float partialTick)
     {
         GL11.glViewport(0, 0, mc.resolution.width, mc.resolution.height);
         GL11.glMatrixMode(GL11.GL_PROJECTION);
@@ -386,7 +386,7 @@ public class GuiPhotoMode extends GuiScreen
 
         if (!shouldScreenshot)
         {
-            super.drawScreen(mouseX, mouseY, partialTick);
+            super.render(xm, ym, partialTick);
         }
         else
         {
@@ -432,7 +432,7 @@ public class GuiPhotoMode extends GuiScreen
             }
         }
         
-        if (showHelpText) drawStringCentered(fontRenderer, I18n.getInstance().translateKey("gui.photo_mode.label.mouse_hint"), width / 2, height - 36, 0xFFFFFF);
+        if (showHelpText) drawStringCentered(font, I18n.getInstance().translateKey("gui.photo_mode.label.mouse_hint"), width / 2, height - 36, 0xFFFFFF);
     }
 
     private void updateButtonsText()
diff --git a/src/main/java/net/minecraft/client/gui/Screen.java b/src/main/java/net/minecraft/client/gui/Screen.java
new file mode 100644
index 000000000..154e71dc7
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/Screen.java
@@ -0,0 +1,210 @@
+package net.minecraft.client.gui;
+
+import static org.lwjgl.opengl.GL11.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.input.controller.ControllerInput;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.client.util.debug.DebugRender;
+import net.minecraft.client.input.InputType;
+
+import net.minecraft.core.sound.SoundCategory;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+public abstract class Screen extends Gui {
+    protected Minecraft mc;
+    public int width;
+    public int height;
+    public List<ButtonElement> buttons;
+    public boolean passEvents;
+    protected Font font;
+    protected ButtonElement clickedButton;
+    final Screen parentScreen;
+
+    public Screen(Screen parent) {
+        buttons = new ArrayList<>();
+        passEvents = false;
+        clickedButton = null;
+        parentScreen = parent;
+    }
+
+    public Screen() {
+        this(null);
+    }
+
+    public Screen getParentScreen() {
+        return parentScreen;
+    }
+
+    public <E extends ButtonElement> E add(E button) {
+        buttons.add(button);
+        return button;
+    }
+
+    public void render(int xm, int ym, float partialTick) {
+        for (int i = 0; i < buttons.size(); i++) {
+            ButtonElement button = buttons.get(i);
+            button.drawButton(mc, xm, ym);
+        }
+    }
+
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
+        if (eventKey == Keyboard.KEY_BACK) {
+            mc.displayScreen(parentScreen);
+        }
+        if (eventKey == Keyboard.KEY_ESCAPE) {
+            mc.displayScreen(null);
+        }
+    }
+
+    public void mouseClicked(int mx, int my, int buttonNum) {
+        if (buttonNum == 0) {
+            for (ButtonElement button : buttons) {
+                if (button.mouseClicked(mc, mx, my) && button.playSound) {
+                    clickedButton = button;
+                    mc.sndManager.playSound("random.click", SoundCategory.GUI_SOUNDS, 1.0F, 1.0F);
+                    if (button.listener != null) {
+                        button.listener.listen(button);
+                    } else {
+                        buttonClicked(button);
+                    }
+                    return;
+                }
+            }
+
+        }
+    }
+
+    public void mouseReleased(int mx, int my, int buttonNum) {
+        if (clickedButton != null && buttonNum == 0) {
+            buttonReleased(clickedButton);
+            clickedButton.mouseReleased(mx, my);
+            clickedButton = null;
+        }
+    }
+
+    protected void buttonClicked(ButtonElement button) {
+    }
+
+    protected void buttonReleased(ButtonElement button) {
+    }
+
+    public void init(Minecraft mc, int width, int height) {
+        this.mc = mc;
+        font = mc.font;
+        this.width = width;
+        this.height = height;
+        buttons.clear();
+        init();
+    }
+
+    public void init() {
+    }
+
+    public void updateEvents() {
+        int mouseX = (Mouse.getEventX() * width) / mc.resolution.width;
+        int mouseY = height - (Mouse.getEventY() * height) / mc.resolution.height - 1;
+
+        while (Mouse.next()) {
+            if (mc.inputType == InputType.CONTROLLER) break;
+
+            if (Mouse.getEventButtonState()) {
+                mouseClicked(mouseX, mouseY, Mouse.getEventButton());
+            } else {
+                mouseReleased(mouseX, mouseY, Mouse.getEventButton());
+            }
+        }
+        while (Keyboard.next()) {
+            if (Keyboard.getEventKeyState() && mc.gameSettings.showFrameTimes.value && DebugRender.keyPressed(Keyboard.getEventKey())) {
+                continue;
+            }
+            int eventKey = Keyboard.getEventKey();
+            char eventChar = Keyboard.getEventCharacter();
+            if (eventKey == 0 && Character.isDefined(eventChar)) {
+                keyPressed(eventChar, eventKey, mouseX, mouseY);
+                return;
+            }
+            if (Keyboard.getEventKeyState()) {
+                if (eventKey == Keyboard.KEY_F11) {
+                    mc.gameWindow.toggleFullscreen();
+                    return;
+                }
+                keyPressed(eventChar, eventKey, mouseX, mouseY);
+            }
+        }
+    }
+
+    public void tick() {
+    }
+
+    public void removed() {
+    }
+
+    public void renderBackground() {
+        if (mc.theWorld != null) {
+            int color = mc.gameSettings.guiBackgroundColor.value.getARGB();
+            drawGradientRect(0, 0, width, height, color, color);
+        } else {
+            renderTexturedBackground();
+        }
+    }
+
+    public void renderTexturedBackground() {
+        GL11.glDisable(GL11.GL_LIGHTING);
+        GL11.glDisable(GL11.GL_FOG);
+        Tessellator tessellator = Tessellator.instance;
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+        float f = 32F;
+        tessellator.startDrawingQuads();
+        tessellator.setColorOpaque_I(0x404040);
+        tessellator.addVertexWithUV(0.0D, height, 0.0D, 0.0D, (float) height / f);
+        tessellator.addVertexWithUV(width, height, 0.0D, (float) width / f, (float) height / f);
+        tessellator.addVertexWithUV(width, 0.0D, 0.0D, (float) width / f, 0);
+        tessellator.addVertexWithUV(0.0D, 0.0D, 0.0D, 0.0D, 0);
+        tessellator.draw();
+    }
+
+    public void drawControllerCursor() {
+        glDisable(GL_DEPTH_TEST);
+        glEnable(GL_BLEND);
+        glColor3d(1.0, 1.0, 1.0);
+        drawGuiTexture(mc.textureManager, (int) (mc.controllerInput.cursorX - 8), (int) (mc.controllerInput.cursorY - 8), 16, 16, "/assets/minecraft/textures/gui/controller/cursor.png");
+        glDisable(GL_BLEND);
+    }
+
+    public void controllerInput(ControllerInput controller) {
+        guiSpecificControllerInput(controller);
+        playControllerButtonSound(controller);
+    }
+
+    public void playControllerButtonSound(ControllerInput controller) {
+        if (controller.buttonA.pressedThisFrame() || controller.buttonX.pressedThisFrame() || controller.buttonY.pressedThisFrame()) {
+            mc.sndManager.playSound("random.ui_click", SoundCategory.GUI_SOUNDS, 1.0f, 1.0f);
+        }
+        if (controller.buttonB.pressedThisFrame()) {
+            mc.sndManager.playSound("random.ui_back", SoundCategory.GUI_SOUNDS, 1.0f, 1.0f);
+        }
+    }
+
+    public void guiSpecificControllerInput(ControllerInput controller) {
+
+    }
+
+    public boolean isPauseScreen() {
+        return true;
+    }
+
+    public void selectNextField() {
+    }
+
+    public void updateFont() {
+        this.font = mc.font;
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/ScrolledSelectionList.java b/src/main/java/net/minecraft/client/gui/ScrolledSelectionList.java
index ca81ae218..744dce911 100644
--- a/src/main/java/net/minecraft/client/gui/ScrolledSelectionList.java
+++ b/src/main/java/net/minecraft/client/gui/ScrolledSelectionList.java
@@ -156,7 +156,7 @@ public abstract class ScrolledSelectionList {
         GL11.glDisable(GL11.GL_LIGHTING);
         GL11.glDisable(GL11.GL_FOG);
         Tessellator tessellator = Tessellator.instance;
-        minecraft.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+        minecraft.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         float f1 = 32F;
         tessellator.startDrawingQuads();
@@ -268,7 +268,7 @@ public abstract class ScrolledSelectionList {
 
     private void renderHoleBackground(int y0, int y1, int a0, int a1) {
         Tessellator tessellator = Tessellator.instance;
-        minecraft.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+        minecraft.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         float f = 32F;
         tessellator.startDrawingQuads();
diff --git a/src/main/java/net/minecraft/client/gui/GuiSelectServer.java b/src/main/java/net/minecraft/client/gui/SelectServerScreen.java
similarity index 64%
rename from src/main/java/net/minecraft/client/gui/GuiSelectServer.java
rename to src/main/java/net/minecraft/client/gui/SelectServerScreen.java
index d360f3b1e..af952745d 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSelectServer.java
+++ b/src/main/java/net/minecraft/client/gui/SelectServerScreen.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.popup.GuiPopup;
+import net.minecraft.client.gui.popup.PopupScreen;
 import net.minecraft.client.gui.popup.PopupBuilder;
 import net.minecraft.client.net.thread.ThreadPingServer;
 import net.minecraft.client.render.tessellator.Tessellator;
@@ -15,30 +15,30 @@ import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
 
-public class GuiSelectServer extends GuiScreen {
+public class SelectServerScreen extends Screen {
 
 	protected String screenTitle = "Select server";
 	private boolean selected = false;
 	private int selectedServer;
 	private SavedServerList savedServerList;
-	private GuiServerSlot worldSlotContainer;
+	private ServerSlot worldSlotContainer;
 	private boolean deleting;
 	
-	public GuiButton buttonConnect;
-	public GuiButton buttonDirectConnect;
-	public GuiButton buttonAdd;
+	public ButtonElement buttonConnect;
+	public ButtonElement buttonDirectConnect;
+	public ButtonElement buttonAdd;
 	
-	public GuiButton buttonEdit;
-	public GuiButton buttonDelete;
-	public GuiButton buttonRefresh;
-	public GuiButton buttonCancel;
+	public ButtonElement buttonEdit;
+	public ButtonElement buttonDelete;
+	public ButtonElement buttonRefresh;
+	public ButtonElement buttonCancel;
 
-	GuiTooltip tooltip;
+	TooltipElement tooltip;
 
 	private Map<ServerData, ThreadPingServer> pingThreads = new HashMap<>();
 
-	public GuiSelectServer(GuiScreen guiscreen) {
-		super(guiscreen);
+	public SelectServerScreen(Screen parent) {
+		super(parent);
 	}
 
 	@Override
@@ -46,8 +46,8 @@ public class GuiSelectServer extends GuiScreen {
 		I18n stringtranslate = I18n.getInstance();
 		screenTitle = stringtranslate.translateKey("gui.select_server.label.title");
 		loadSavedServers();
-		worldSlotContainer = new GuiServerSlot(this);
-		tooltip = new GuiTooltip(mc);
+		worldSlotContainer = new ServerSlot();
+		tooltip = new TooltipElement(mc);
 		initButtons();
 		refresh();
 	}
@@ -64,20 +64,20 @@ public class GuiSelectServer extends GuiScreen {
 		int y1 = height - 52;
 		int y2 = height - 28;
 		
-		buttonConnect = add(new GuiButton(0, x1, y1, 100, 20, trans.translateKey("gui.select_server.button.join_server")));
-		buttonDirectConnect = add(new GuiButton(0, x1 + 104, y1, 100, 20, trans.translateKey("gui.select_server.button.direct_connect")));
-		buttonAdd = add(new GuiButton(0, x1 + 208, y1, 100, 20, trans.translateKey("gui.select_server.button.add_server")));
+		buttonConnect = add(new ButtonElement(0, x1, y1, 100, 20, trans.translateKey("gui.select_server.button.join_server")));
+		buttonDirectConnect = add(new ButtonElement(0, x1 + 104, y1, 100, 20, trans.translateKey("gui.select_server.button.direct_connect")));
+		buttonAdd = add(new ButtonElement(0, x1 + 208, y1, 100, 20, trans.translateKey("gui.select_server.button.add_server")));
 		
-		buttonEdit = add(new GuiButton(0, x1, y2, 74, 20, trans.translateKey("gui.select_server.button.edit")));
-		buttonDelete = add(new GuiButton(0, x1 + 78, y2, 74, 20, trans.translateKey("gui.select_server.button.delete")));
-		buttonRefresh = add(new GuiButton(0, x1 + 156, y2, 74, 20, trans.translateKey("gui.select_server.button.refresh")));
-		buttonCancel = add(new GuiButton(0, x1 + 234, y2, 74, 20, trans.translateKey("gui.select_server.button.cancel")));
+		buttonEdit = add(new ButtonElement(0, x1, y2, 74, 20, trans.translateKey("gui.select_server.button.edit")));
+		buttonDelete = add(new ButtonElement(0, x1 + 78, y2, 74, 20, trans.translateKey("gui.select_server.button.delete")));
+		buttonRefresh = add(new ButtonElement(0, x1 + 156, y2, 74, 20, trans.translateKey("gui.select_server.button.refresh")));
+		buttonCancel = add(new ButtonElement(0, x1 + 234, y2, 74, 20, trans.translateKey("gui.select_server.button.cancel")));
 		
 		setButtonsEnabled(false);
 	}
 
 	@Override
-	protected void buttonPressed(GuiButton button) {
+	protected void buttonClicked(ButtonElement button) {
 		if(!button.enabled) {
 			return;
 		}
@@ -86,7 +86,7 @@ public class GuiSelectServer extends GuiScreen {
 			if (serverName != null) {
 				deleting = true;
 				I18n i18n = I18n.getInstance();
-				GuiPopup popup = new PopupBuilder(this, 250)
+				PopupScreen popup = new PopupBuilder(this, 250)
 					.closeOnEsc(0)
 					.withLabel("gui.select_server.label.delete_title")
 					.withLabel("gui.select_server.label.delete_confirm.1")
@@ -100,24 +100,24 @@ public class GuiSelectServer extends GuiScreen {
 						}
 					})
 					.build();
-				mc.displayGuiScreen(popup);
+				mc.displayScreen(popup);
 			}
 		} else if(button == buttonConnect) {
 			selectServer(selectedServer);
 		} else if(button == buttonDirectConnect) {
-			mc.displayGuiScreen(new GuiConnectToIP(this));
+			mc.displayScreen(new ConnectToIpScreen(this));
 		} else if(button == buttonAdd) {
-			mc.displayGuiScreen(new GuiAddServer(this, savedServerList));
+			mc.displayScreen(new AddServerScreen(this, savedServerList));
 			savedServerList.writeToFile();
 		} else if(button == buttonCancel) {
-			mc.displayGuiScreen(parentScreen);
+			mc.displayScreen(parentScreen);
 		} else if(button == buttonRefresh) {
 			refresh();
 		} else if(button == buttonEdit) {
 			ServerData serverData = savedServerList.servers.get(selectedServer);
 			
 			if(serverData != null) {
-				GuiPopup popup = new PopupBuilder(this, 140)
+				PopupScreen popup = new PopupBuilder(this, 140)
 						.closeOnEsc(0).closeOnClickOut(0).closeOnEnter(1)
 						.withLabel("gui.select_server.label.edit.1")
 						.withLabel("gui.select_server.label.edit.2")
@@ -135,7 +135,7 @@ public class GuiSelectServer extends GuiScreen {
 								refresh();
 							}
 						}).build();
-				mc.displayGuiScreen(popup);
+				mc.displayScreen(popup);
 			}
 			
 		}
@@ -189,14 +189,14 @@ public class GuiSelectServer extends GuiScreen {
 	}
 
 	public void selectServer(int i) {
-		mc.displayGuiScreen(null);
+		mc.displayScreen(null);
 		if (selected) {
 			return;
 		}
 		selected = true;
 		ServerData server = savedServerList.servers.get(selectedServer);
 		ServerAddress address = server.getServerAddress();
-		mc.displayGuiScreen(new GuiConnecting(mc, address.getIP(), address.getPort()));
+		mc.displayScreen(new ConnectingScreen(mc, address.getIP(), address.getPort()));
 	}
 
 	public void deleteWorld(boolean flag, int i) {
@@ -206,24 +206,21 @@ public class GuiSelectServer extends GuiScreen {
 				savedServerList.servers.remove(i);
 				savedServerList.writeToFile();
 			}
-			mc.displayGuiScreen(this);
+			mc.displayScreen(this);
 		}
 	}
 
 	@Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick) {
-		worldSlotContainer.render(mouseX, mouseY, partialTick);
-		drawStringCentered(fontRenderer, screenTitle, width / 2, 20, 0xffffff);
-		super.drawScreen(mouseX, mouseY, partialTick);
+	public void render(int xm, int ym, float partialTick) {
+		worldSlotContainer.render(xm, ym, partialTick);
+		drawStringCentered(font, screenTitle, width / 2, 20, 0xffffff);
+		super.render(xm, ym, partialTick);
 	}
 	
-	class GuiServerSlot extends ScrolledSelectionList {
+	class ServerSlot extends ScrolledSelectionList {
 
-		final GuiSelectServer guiSelectServer;
-		
-		public GuiServerSlot(GuiSelectServer parent) {
-			super(parent.mc, parent.width, parent.height, 32, parent.height - 64, 36);
-			this.guiSelectServer = parent;
+		public ServerSlot() {
+			super(mc, width, height, 32, height - 64, 36);
 		}
 
 		@Override
@@ -244,7 +241,7 @@ public class GuiSelectServer extends GuiScreen {
 			}*/
 			
 			if (doubleClicked && enableButtons) {
-				guiSelectServer.selectServer(itemIndex);
+				selectServer(itemIndex);
 			}
 		}
 
@@ -260,7 +257,7 @@ public class GuiSelectServer extends GuiScreen {
 
 		@Override
 		protected void renderHoleBackground() {
-			guiSelectServer.drawDefaultBackground();
+			renderBackground();
 		}
 
 		@Override
@@ -269,31 +266,31 @@ public class GuiSelectServer extends GuiScreen {
 			String line1 = server.nickname;
 			String line2 = server.address;
 
-			guiSelectServer.drawString(guiSelectServer.fontRenderer, line1, x + 2, y + 1, 0xffffff);
-			if (server.showIp) guiSelectServer.drawString(guiSelectServer.fontRenderer, line2, x + 2, y + 12 + 10, 0x404040);
+			drawString(font, line1, x + 2, y + 1, 0xffffff);
+			if (server.showIp) drawString(font, line2, x + 2, y + 12 + 10, 0x404040);
 			if (server.isUp && server.protocolVersion != Global.MP_PROTOCOL_VERSION) {
 				String outdated = I18n.getInstance().translateKey("gui.select_server.label.outdated");
-				int width = guiSelectServer.fontRenderer.getStringWidth(outdated);
-				guiSelectServer.drawString(guiSelectServer.fontRenderer, outdated, x + 220 - width - 4, y + 1, 0xFF0000);
-				width = guiSelectServer.fontRenderer.getStringWidth(server.version);
-				guiSelectServer.drawString(guiSelectServer.fontRenderer, server.version, x + 220 - width - 4, y + 12, 0xFF0000);
-				guiSelectServer.drawString(guiSelectServer.fontRenderer, server.motd, x + 2, y + 12, 0x808080);
+				int width = font.getStringWidth(outdated);
+				drawString(font, outdated, x + 220 - width - 4, y + 1, 0xFF0000);
+				width = font.getStringWidth(server.version);
+				drawString(font, server.version, x + 220 - width - 4, y + 12, 0xFF0000);
+				drawString(font, server.motd, x + 2, y + 12, 0x808080);
 			} else if (server.isUp) {
 				String latency = server.latency + "ms";
-				int width = guiSelectServer.fontRenderer.getStringWidth(latency);
+				int width = font.getStringWidth(latency);
 				float green = 1.0f - MathHelper.clamp((float)server.latency / 500.0F, 0.0F, 1.0F);
 				float red = 1.0F - green;
 				int argb = 0xFF000000 | (int)(255.0F * red) << 16 | (int)(255.0F * green) << 8;
 
-				guiSelectServer.drawString(guiSelectServer.fontRenderer, latency, x + 220 - width - 4, y + 1, argb);
+				drawString(font, latency, x + 220 - width - 4, y + 1, argb);
 				String players = server.currentPlayers + "/" + server.maxPlayers;
-				width = guiSelectServer.fontRenderer.getStringWidth(players);
-				guiSelectServer.drawString(guiSelectServer.fontRenderer, players, x + 220 - width - 4, y + 12, 0x808080);
-				guiSelectServer.drawString(guiSelectServer.fontRenderer, server.motd, x + 2, y + 12, 0x808080);
+				width = font.getStringWidth(players);
+				drawString(font, players, x + 220 - width - 4, y + 12, 0x808080);
+				drawString(font, server.motd, x + 2, y + 12, 0x808080);
 			} else {
 				String down = I18n.getInstance().translateKey("gui.select_server.label.down");
-				int width = guiSelectServer.fontRenderer.getStringWidth(down);
-				guiSelectServer.drawString(guiSelectServer.fontRenderer, down, x + 220 - width - 4, y + 1, 0xFF0000);
+				int width = font.getStringWidth(down);
+				drawString(font, down, x + 220 - width - 4, y + 1, 0xFF0000);
 			}
 		}
 	}
diff --git a/src/main/java/net/minecraft/client/gui/GuiSelectWorld.java b/src/main/java/net/minecraft/client/gui/SelectWorldScreen.java
similarity index 83%
rename from src/main/java/net/minecraft/client/gui/GuiSelectWorld.java
rename to src/main/java/net/minecraft/client/gui/SelectWorldScreen.java
index 11037f723..bbef928fb 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSelectWorld.java
+++ b/src/main/java/net/minecraft/client/gui/SelectWorldScreen.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.popup.GuiPopup;
+import net.minecraft.client.gui.popup.PopupScreen;
 import net.minecraft.client.gui.popup.PopupBuilder;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.Global;
@@ -16,31 +16,30 @@ import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.type.WorldType;
 import org.lwjgl.input.Keyboard;
 
-import java.security.Key;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
-public class GuiSelectWorld extends GuiScreen
+public class SelectWorldScreen extends Screen
 {
     private final DateFormat dateFormatter = new SimpleDateFormat();
     protected String stringTitle;
     private boolean selected;
     private int selectedWorld;
     private List<SaveFile> saveList;
-    private GuiWorldSlot worldSlotContainer;
+    private WorldSlot worldSlotContainer;
     private String stringWorld;
     private String stringConversion;
     private boolean deleting;
-    private GuiButton buttonRename;
-    private GuiButton buttonSelect;
-    private GuiButton buttonDelete;
+    private ButtonElement buttonRename;
+    private ButtonElement buttonSelect;
+    private ButtonElement buttonDelete;
 
-    public GuiSelectWorld(GuiScreen guiscreen)
+    public SelectWorldScreen(Screen parent)
     {
-        super(guiscreen);
+        super(parent);
         stringTitle = "Select world";
         selected = false;
         selectedWorld = -1;
@@ -58,24 +57,24 @@ public class GuiSelectWorld extends GuiScreen
             stringConversion = i18n.translateKey("gui.select_world.label.outdated");
         }
         loadSaves();
-        worldSlotContainer = new GuiWorldSlot();
+        worldSlotContainer = new WorldSlot();
         initButtons();
     }
 
     @Override
-    public void keyTyped(char c, int key, int mouseX, int mouseY) {
-        super.keyTyped(c, key, mouseX, mouseY);
-        if (key == Keyboard.KEY_UP) {
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
+        super.keyPressed(eventCharacter, eventKey, mx, my);
+        if (eventKey == Keyboard.KEY_UP) {
             if (selectedWorld > 0) {
                 worldSlotContainer.selectItem(selectedWorld - 1, false);
             }
         }
-        if (key == Keyboard.KEY_DOWN) {
+        if (eventKey == Keyboard.KEY_DOWN) {
             if (selectedWorld < saveList.size() - 1) {
                 worldSlotContainer.selectItem(selectedWorld + 1, false);
             }
         }
-        if (key == Keyboard.KEY_DELETE) {
+        if (eventKey == Keyboard.KEY_DELETE) {
             tryDeleteWorld(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT));
         }
     }
@@ -110,11 +109,11 @@ public class GuiSelectWorld extends GuiScreen
     public void initButtons()
     {
         I18n i18n = I18n.getInstance();
-        controlList.add(buttonSelect = new GuiButton(1, width / 2 - 154, height - 52, 150, 20, i18n.translateKey("gui.select_world.button.play_selected_world")));
-        controlList.add(buttonRename = new GuiButton(6, width / 2 - 154, height - 28, 70, 20, i18n.translateKey("gui.select_world.button.rename")));
-        controlList.add(buttonDelete = new GuiButton(2, width / 2 - 74, height - 28, 70, 20, i18n.translateKey("gui.select_world.button.delete")));
-        controlList.add(new GuiButton(3, width / 2 + 4, height - 52, 150, 20, i18n.translateKey("gui.select_world.button.create_new_world")));
-        controlList.add(new GuiButton(0, width / 2 + 4, height - 28, 150, 20, i18n.translateKey("gui.select_world.button.cancel")));
+        buttons.add(buttonSelect = new ButtonElement(1, width / 2 - 154, height - 52, 150, 20, i18n.translateKey("gui.select_world.button.play_selected_world")));
+        buttons.add(buttonRename = new ButtonElement(6, width / 2 - 154, height - 28, 70, 20, i18n.translateKey("gui.select_world.button.rename")));
+        buttons.add(buttonDelete = new ButtonElement(2, width / 2 - 74, height - 28, 70, 20, i18n.translateKey("gui.select_world.button.delete")));
+        buttons.add(new ButtonElement(3, width / 2 + 4, height - 52, 150, 20, i18n.translateKey("gui.select_world.button.create_new_world")));
+        buttons.add(new ButtonElement(0, width / 2 + 4, height - 28, 150, 20, i18n.translateKey("gui.select_world.button.cancel")));
         buttonSelect.enabled = false;
         buttonRename.enabled = false;
         buttonDelete.enabled = false;
@@ -144,7 +143,7 @@ public class GuiSelectWorld extends GuiScreen
                 deleteWorld(true, selectedWorld);
             } else {
                 I18n i18n = I18n.getInstance();
-                GuiPopup popup = new PopupBuilder(this, 250)
+                PopupScreen popup = new PopupBuilder(this, 250)
                     .closeOnEsc(0)
                     .withLabel("gui.select_world.label.delete_title")
                     .withLabel("gui.select_world.label.delete_confirm.1")
@@ -158,14 +157,14 @@ public class GuiSelectWorld extends GuiScreen
                         }
                     })
                     .build();
-                mc.displayGuiScreen(popup);
+                mc.displayScreen(popup);
             }
         }
 
     }
 
     @Override
-    protected void buttonPressed(GuiButton button)
+    protected void buttonClicked(ButtonElement button)
     {
         if(!button.enabled)
         {
@@ -181,12 +180,12 @@ public class GuiSelectWorld extends GuiScreen
         }
         else if(button.id == 3)
         {
-            mc.displayGuiScreen(new GuiCreateWorld(this));
+            mc.displayScreen(new CreateWorldScreen(this));
         }
         else if(button.id == 6)
         {
             I18n i18n = I18n.getInstance();
-            GuiPopup popup = new PopupBuilder(this, 140)
+            PopupScreen popup = new PopupBuilder(this, 140)
                     .closeOnEsc(0)
                     .closeOnEnter(1)
                     .withLabel("gui.select_world.label.rename_title")
@@ -203,11 +202,11 @@ public class GuiSelectWorld extends GuiScreen
                         }
                     }))
                     .build();
-            mc.displayGuiScreen(popup);
+            mc.displayScreen(popup);
         }
         else if(button.id == 0)
         {
-            mc.displayGuiScreen(parentScreen);
+            mc.displayScreen(parentScreen);
         }
     }
 
@@ -220,7 +219,7 @@ public class GuiSelectWorld extends GuiScreen
             return;
         }
 
-        mc.displayGuiScreen(null);
+        mc.displayScreen(null);
         if(selected)
         {
             return;
@@ -233,7 +232,7 @@ public class GuiSelectWorld extends GuiScreen
             s = "World" + i;
         }
         mc.startWorld(s, getSaveName(i), 0L);
-        mc.displayGuiScreen(null);
+        mc.displayScreen(null);
     }
 
     public void deleteWorld(boolean flag, int i)
@@ -249,21 +248,21 @@ public class GuiSelectWorld extends GuiScreen
                 loadSaves();
                 selectedWorld = -1;
             }
-            mc.displayGuiScreen(this);
+            mc.displayScreen(this);
         }
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick)
+    public void render(int xm, int ym, float partialTick)
     {
-        worldSlotContainer.render(mouseX, mouseY, partialTick);
-        drawStringCentered(fontRenderer, stringTitle, width / 2, 20, 0xffffff);
-        super.drawScreen(mouseX, mouseY, partialTick);
+        worldSlotContainer.render(xm, ym, partialTick);
+        drawStringCentered(font, stringTitle, width / 2, 20, 0xffffff);
+        super.render(xm, ym, partialTick);
     }
 
-    class GuiWorldSlot extends ScrolledSelectionList
+    class WorldSlot extends ScrolledSelectionList
     {
-        public GuiWorldSlot()
+        public WorldSlot()
         {
             super(mc, width, height, 32, height - 64, 36);
         }
@@ -304,7 +303,7 @@ public class GuiSelectWorld extends GuiScreen
         @Override
         protected void renderHoleBackground()
         {
-            drawDefaultBackground();
+            renderBackground();
         }
 
         @Override
@@ -346,9 +345,9 @@ public class GuiSelectWorld extends GuiScreen
                 }
             }
 
-            drawString(fontRenderer, s, x + 2, y + 1, 0xffffff);
-            drawString(fontRenderer, s1, x + 2, y + 12, 0x808080);
-            drawString(fontRenderer, s2, x + 2, y + 12 + 10, 0x808080);
+            drawString(font, s, x + 2, y + 1, 0xffffff);
+            drawString(font, s1, x + 2, y + 12, 0x808080);
+            drawString(font, s2, x + 2, y + 12 + 10, 0x808080);
         }
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/GuiEditSign.java b/src/main/java/net/minecraft/client/gui/SignEditorScreen.java
similarity index 77%
rename from src/main/java/net/minecraft/client/gui/GuiEditSign.java
rename to src/main/java/net/minecraft/client/gui/SignEditorScreen.java
index 881c2f6f4..dc09c7ac3 100644
--- a/src/main/java/net/minecraft/client/gui/GuiEditSign.java
+++ b/src/main/java/net/minecraft/client/gui/SignEditorScreen.java
@@ -12,9 +12,9 @@ import net.minecraft.core.lang.I18n;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.opengl.GL11;
 
-public class GuiEditSign extends GuiScreen
+public class SignEditorScreen extends Screen
 {
-    public GuiEditSign(SignBlockEntity tileentitysign)
+    public SignEditorScreen(SignBlockEntity tileentitysign)
     {
         screenTitle = I18n.getInstance().translateKey("gui.edit_sign.label.title");
         editLine = 0;
@@ -24,7 +24,7 @@ public class GuiEditSign extends GuiScreen
     @Override
 	public void init()
     {
-        controlList.clear();
+        buttons.clear();
         Keyboard.enableRepeatEvents(true);
 
         Block block = entitySign.getBlockType();
@@ -33,14 +33,14 @@ public class GuiEditSign extends GuiScreen
             yOffset = 36;
         }
 
-        controlList.add(new GuiButton(0, width / 2 - 100, 150 + 50 + yOffset, I18n.getInstance().translateKey("gui.edit_sign.button.done")));
+        buttons.add(new ButtonElement(0, width / 2 - 100, 150 + 50 + yOffset, I18n.getInstance().translateKey("gui.edit_sign.button.done")));
         
-        controlList.add(new GuiButton(1, width / 2 - 20, 120 + 50 + yOffset, 20, 20, "<"));
-        controlList.add(new GuiButton(2, width / 2, 120 + 50 + yOffset, 20, 20, ">"));
+        buttons.add(new ButtonElement(1, width / 2 - 20, 120 + 50 + yOffset, 20, 20, "<"));
+        buttons.add(new ButtonElement(2, width / 2, 120 + 50 + yOffset, 20, 20, ">"));
     }
 
     @Override
-	public void onClosed()
+	public void removed()
     {
         Keyboard.enableRepeatEvents(false);
         // I have no idea how the hell the world is null sometimes
@@ -58,7 +58,7 @@ public class GuiEditSign extends GuiScreen
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
         if(!button.enabled)
         {
@@ -67,7 +67,7 @@ public class GuiEditSign extends GuiScreen
         if(button.id == 0)
         {
             entitySign.setChanged();
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
         }
         if (button.id == 1)
         {
@@ -88,36 +88,36 @@ public class GuiEditSign extends GuiScreen
     }
 
     @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
-    	if(i == Keyboard.KEY_ESCAPE)
+    	if(eventKey == Keyboard.KEY_ESCAPE)
     	{
             entitySign.setChanged();
-    		mc.displayGuiScreen(null);
+    		mc.displayScreen(null);
     	}
-        if(i == 200)
+        if(eventKey == 200)
         {
             editLine = editLine - 1 & 3;
         }
-        if(i == 208 || i == 28 || i == 156)
+        if(eventKey == 208 || eventKey == 28 || eventKey == 156)
         {
             editLine = editLine + 1 & 3;
         }
-        if(i == 14 && entitySign.signText[editLine].length() > 0)
+        if(eventKey == 14 && entitySign.signText[editLine].length() > 0)
         {
             entitySign.signText[editLine] = entitySign.signText[editLine].substring(0, entitySign.signText[editLine].length() - 1);
         }
-        if ((allowedCharacters.indexOf(c) >= 0 || Character.isLetterOrDigit(c)) && entitySign.signText[editLine].length() < 15)
+        if ((allowedCharacters.indexOf(eventCharacter) >= 0 || Character.isLetterOrDigit(eventCharacter)) && entitySign.signText[editLine].length() < 15)
         {
-            entitySign.signText[editLine] += c;
+            entitySign.signText[editLine] += eventCharacter;
         }
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
-        drawDefaultBackground();
-        drawStringCentered(fontRenderer, screenTitle, width / 2, 40, 0xffffff);
+        renderBackground();
+        drawStringCentered(font, screenTitle, width / 2, 40, 0xffffff);
         GL11.glPushMatrix();
         GL11.glTranslatef((float) width / 2, 0.0F, 50F);
         float scale = 93.75F;
@@ -156,9 +156,9 @@ public class GuiEditSign extends GuiScreen
         entitySign.lineBeingEdited = -1;
         GL11.glPopMatrix();
         
-        drawStringCentered(fontRenderer, I18n.getInstance().translateKey(entitySign.getPicture().getLanguageKey()), width / 2, 100 + 50 + yOffset, 0xFFFFFF);
+        drawStringCentered(font, I18n.getInstance().translateKey(entitySign.getPicture().getLanguageKey()), width / 2, 100 + 50 + yOffset, 0xFFFFFF);
 
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
     }
 
     protected String screenTitle;
diff --git a/src/main/java/net/minecraft/client/gui/GuiSleepMP.java b/src/main/java/net/minecraft/client/gui/SleepScreenMP.java
similarity index 71%
rename from src/main/java/net/minecraft/client/gui/GuiSleepMP.java
rename to src/main/java/net/minecraft/client/gui/SleepScreenMP.java
index 8f23abf8f..93e9c15f9 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSleepMP.java
+++ b/src/main/java/net/minecraft/client/gui/SleepScreenMP.java
@@ -12,10 +12,10 @@ import org.lwjgl.input.Keyboard;
 //            GuiChat, StringTranslate, GuiButton, LocalPlayer,
 //            MultiplayerLocalPlayer, PlayerCommandPacket, ClientPacketHandler
 
-public class GuiSleepMP extends GuiChat
+public class SleepScreenMP extends ChatScreen
 {
 
-    public GuiSleepMP()
+    public SleepScreenMP()
     {
     }
 
@@ -24,41 +24,41 @@ public class GuiSleepMP extends GuiChat
     {
         Keyboard.enableRepeatEvents(true);
         I18n stringtranslate = I18n.getInstance();
-        controlList.add(new GuiButton(1, width / 2 - 100, height - 40, stringtranslate.translateKey("gui.sleeping.multiplayer.leave_bed")));
+        buttons.add(new ButtonElement(1, width / 2 - 100, height - 40, stringtranslate.translateKey("gui.sleeping.multiplayer.leave_bed")));
 		int emotePickerYCells = (int)MathHelper.clamp(Math.ceil(ChatEmotes.getEmotes().size() / 5.0), 0, 4);
-		emotePicker = new GuiChatEmotePicker(mc, this, 5, emotePickerYCells);
+		emotePicker = new ChatEmotePickerElement(mc, this, 5, emotePickerYCells);
 		showEmotePicker = false;
     }
 
     @Override
-	public void onClosed()
+	public void removed()
     {
         Keyboard.enableRepeatEvents(false);
     }
     
     @Override
-	public void keyTyped(char c, int key, int mouseX, int mouseY) {
-    	super.keyTyped(c, key, mouseX, mouseY);
-    	if(key == Keyboard.KEY_ESCAPE) {
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
+    	super.keyPressed(eventCharacter, eventKey, mx, my);
+    	if(eventKey == Keyboard.KEY_ESCAPE) {
     		func_22115_j();
     	}
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
         if(button.id == 1)
         {
             func_22115_j();
         } else
         {
-            super.buttonPressed(button);
+            super.buttonClicked(button);
         }
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/GuiSleepSP.java b/src/main/java/net/minecraft/client/gui/SleepScreenSP.java
similarity index 59%
rename from src/main/java/net/minecraft/client/gui/GuiSleepSP.java
rename to src/main/java/net/minecraft/client/gui/SleepScreenSP.java
index b73f6a145..ee1424127 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSleepSP.java
+++ b/src/main/java/net/minecraft/client/gui/SleepScreenSP.java
@@ -3,23 +3,23 @@ package net.minecraft.client.gui;
 import net.minecraft.core.lang.I18n;
 import org.lwjgl.input.Keyboard;
 
-public class GuiSleepSP extends GuiScreen{
+public class SleepScreenSP extends Screen {
 	
 	@Override
 	public void init() {
         I18n stringtranslate = I18n.getInstance();
-        controlList.add(new GuiButton(1, width / 2 - 100, height - 40, stringtranslate.translateKey("gui.sleeping.leave_bed")));
+        buttons.add(new ButtonElement(1, width / 2 - 100, height - 40, stringtranslate.translateKey("gui.sleeping.leave_bed")));
 	}
 	
 	@Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY) {
-		if(i == Keyboard.KEY_ESCAPE) {
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
+		if(eventKey == Keyboard.KEY_ESCAPE) {
 			wakeUp();
 		}
 	}
 	
 	@Override
-	protected void buttonPressed(GuiButton button) {
+	protected void buttonClicked(ButtonElement button) {
 		if(button.id == 1) {
 			wakeUp();
 		}
@@ -30,7 +30,7 @@ public class GuiSleepSP extends GuiScreen{
 	}
 	
 	@Override
-	public boolean pausesGame() {
+	public boolean isPauseScreen() {
 		return false;
 	}
 	
diff --git a/src/main/java/net/minecraft/client/gui/GuiSlider.java b/src/main/java/net/minecraft/client/gui/SliderElement.java
similarity index 82%
rename from src/main/java/net/minecraft/client/gui/GuiSlider.java
rename to src/main/java/net/minecraft/client/gui/SliderElement.java
index f449b25f7..9758b52a2 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSlider.java
+++ b/src/main/java/net/minecraft/client/gui/SliderElement.java
@@ -1,30 +1,30 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import org.lwjgl.opengl.GL11;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.option.FloatOption;
 
-public class GuiSlider extends GuiButton {
+public class SliderElement extends ButtonElement {
 
 	public float sliderValue;
 	public boolean dragging;
 	private FloatOption option;
 
-	public GuiSlider(int id, int xPosition, int yPosition, FloatOption floatOption) {
+	public SliderElement(int id, int xPosition, int yPosition, FloatOption floatOption) {
 		this(id, xPosition, yPosition, 150, 20, floatOption);
 	}
 
-	public GuiSlider(int id, int xPosition, int yPosition, int width, int height, FloatOption floatOption) {
+	public SliderElement(int id, int xPosition, int yPosition, int width, int height, FloatOption floatOption) {
 		super(id, xPosition, yPosition, width, height, floatOption.getDisplayStringValue());
 		this.dragging = false;
 		this.option = floatOption;
 		this.sliderValue = floatOption.value;
 	}
 
-	public GuiSlider(int id, int xPosition, int yPosition, int width, int height, String text, float defaultValue) {
+	public SliderElement(int id, int xPosition, int yPosition, int width, int height, String text, float defaultValue) {
 		super(id, xPosition, yPosition, width, height, text);
 		dragging = false;
 		option = null;
@@ -55,7 +55,7 @@ public class GuiSlider extends GuiButton {
 	{
 		if (!visible) return;
 
-		FontRenderer fontrenderer = mc.fontRenderer;
+		Font font = mc.font;
 		boolean mouseOver = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height;
 		int state = getButtonState(mouseOver);
 
@@ -94,7 +94,7 @@ public class GuiSlider extends GuiButton {
 				textColor = 0xFFFFA0;
 				break;
 		}
-		drawStringCentered(fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, textColor);
+		drawStringCentered(font, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, textColor);
 	}
 
 	@Override
diff --git a/src/main/java/net/minecraft/client/gui/GuiSoundTest.java b/src/main/java/net/minecraft/client/gui/SoundTestScreen.java
similarity index 63%
rename from src/main/java/net/minecraft/client/gui/GuiSoundTest.java
rename to src/main/java/net/minecraft/client/gui/SoundTestScreen.java
index d9ecefd6a..ef3028ffb 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSoundTest.java
+++ b/src/main/java/net/minecraft/client/gui/SoundTestScreen.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerTextField;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
+import net.minecraft.client.gui.modelviewer.elements.ListenerTextFieldElement;
 import net.minecraft.client.gui.modelviewer.elements.IListenerElement;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.sound.SoundEngine;
@@ -18,7 +18,7 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
-public class GuiSoundTest extends GuiScreen{
+public class SoundTestScreen extends Screen {
     private static final int TOP_SPACING = 24;
     private static final int BUTTON_SPACING = 4;
 
@@ -29,14 +29,14 @@ public class GuiSoundTest extends GuiScreen{
     protected @Nullable SoundEvent currentEntry;
     protected List<SoundEvent> allEntries;
 
-    protected GuiListenerButton leftEntry;
+    protected ListenerButtonElement leftEntry;
 
     protected float volume = 1;
     protected float pitch = 1;
 
     protected boolean showURL = true;
 
-    public GuiSoundTest(GuiScreen parent) {
+    public SoundTestScreen(Screen parent) {
         super(parent);
         initRepos();
     }
@@ -48,24 +48,24 @@ public class GuiSoundTest extends GuiScreen{
         entryIndex = 0;
     }
     @Override
-    public void keyTyped(char c, int key, int mouseX, int mouseY)
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
-        if (key == Keyboard.KEY_ESCAPE) {
-            mc.displayGuiScreen(parentScreen);
+        if (eventKey == Keyboard.KEY_ESCAPE) {
+            mc.displayScreen(parentScreen);
         }
-        List<GuiButton> _buttons = new ArrayList<>(controlList);
-        for (GuiButton button : _buttons){
-            if (button instanceof IListenerElement && button.isHovered(mouseX, mouseY)){
-                ((IListenerElement) button).onKeyTyped(c, key);
+        List<ButtonElement> _buttons = new ArrayList<>(buttons);
+        for (ButtonElement button : _buttons){
+            if (button instanceof IListenerElement && button.isHovered(mx, my)){
+                ((IListenerElement) button).onKeyTyped(eventCharacter, eventKey);
             }
         }
     }
     @Override
     public void tick(){
-        List<GuiButton> _buttons = new ArrayList<>(controlList);
-        for (GuiButton button : _buttons){
-            if (button instanceof GuiListenerButton){
-                ((GuiListenerButton) button).tick();
+        List<ButtonElement> _buttons = new ArrayList<>(buttons);
+        for (ButtonElement button : _buttons){
+            if (button instanceof ListenerButtonElement){
+                ((ListenerButtonElement) button).tick();
             }
         }
     }
@@ -74,40 +74,40 @@ public class GuiSoundTest extends GuiScreen{
 
         top = TOP_SPACING;
         bottom = height - (BUTTON_SPACING + 20 + BUTTON_SPACING);
-        add(new GuiListenerButton(0, width/2 - 100, height - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.sound_test.button.done")).setActionListener(() -> {
-            onClosed();
-            mc.displayGuiScreen(null);
+        add(new ListenerButtonElement(0, width/2 - 100, height - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.sound_test.button.done")).setActionListener(() -> {
+            removed();
+            mc.displayScreen(null);
         }));
 
-        leftEntry = add(new GuiListenerButton(11, width - (20 + BUTTON_SPACING) * 2, bottom - (BUTTON_SPACING + 20) * 2, 20, 20, "<")
+        leftEntry = add(new ListenerButtonElement(11, width - (20 + BUTTON_SPACING) * 2, bottom - (BUTTON_SPACING + 20) * 2, 20, 20, "<")
             .setActionListener(() -> cycleEntry(-1)));
-        add(new GuiListenerButton(12, width - (20 + BUTTON_SPACING) * 1, bottom - (BUTTON_SPACING + 20) * 2, 20, 20, ">")
+        add(new ListenerButtonElement(12, width - (20 + BUTTON_SPACING) * 1, bottom - (BUTTON_SPACING + 20) * 2, 20, 20, ">")
             .setActionListener(() -> cycleEntry(1)));
 
-        GuiListenerButton b = add(new GuiListenerButton(20, width/2 - 100, bottom - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.sound_test.button.play"))
+        ListenerButtonElement b = add(new ListenerButtonElement(20, width/2 - 100, bottom - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.sound_test.button.play"))
             .setActionListener(this::playEntry)
         );
         b.playSound = false;
-        add(new GuiListenerButton(22, width/2 + 100 + BUTTON_SPACING, bottom - (BUTTON_SPACING + 20), 20, 20, "X")
+        add(new ListenerButtonElement(22, width/2 + 100 + BUTTON_SPACING, bottom - (BUTTON_SPACING + 20), 20, 20, "X")
             .setActionListener(this::stopSound)
         );
 
 
-        add(new GuiListenerButton(30, BUTTON_SPACING, bottom - (BUTTON_SPACING + 20), 20, 20, "")
+        add(new ListenerButtonElement(30, BUTTON_SPACING, bottom - (BUTTON_SPACING + 20), 20, 20, "")
             .setActionListener(() -> Utils.openDirectory(new File(mc.getMinecraftDir(), "resources")))
             .setTextures("minecraft:gui/misc/button_folder", "minecraft:gui/misc/button_folder_highlighted", "minecraft:gui/misc/button_folder"));
 
-        add(new GuiListenerButton(31, 20 + BUTTON_SPACING * 2, bottom - (BUTTON_SPACING + 20), 20, 20, "V"))
+        add(new ListenerButtonElement(31, 20 + BUTTON_SPACING * 2, bottom - (BUTTON_SPACING + 20), 20, 20, "V"))
             .setActionListener(() -> showURL = !showURL);
 
-        add(new GuiListenerButton(32, 40 + BUTTON_SPACING * 3, bottom - (BUTTON_SPACING + 20), 40, 20, I18n.getInstance().translateKey("gui.sound_test.button.reload")))
+        add(new ListenerButtonElement(32, 40 + BUTTON_SPACING * 3, bottom - (BUTTON_SPACING + 20), 40, 20, I18n.getInstance().translateKey("gui.sound_test.button.reload")))
             .setActionListener(() -> {
                 mc.sndManager = new SoundEngine();
                 mc.sndManager.init(mc.gameSettings);
                 initRepos();
             });
 
-        GuiListenerTextField volumeField = new GuiListenerTextField(parentScreen, mc.fontRenderer, width - BUTTON_SPACING - 60, bottom - (BUTTON_SPACING + 20) * 3, 60, 20, String.valueOf(volume), "Volume");
+        ListenerTextFieldElement volumeField = new ListenerTextFieldElement(parentScreen, mc.font, width - BUTTON_SPACING - 60, bottom - (BUTTON_SPACING + 20) * 3, 60, 20, String.valueOf(volume), "Volume");
         add(volumeField)
             .setPrefaceText("Vol: ")
             .setKeyListener(key -> {
@@ -120,7 +120,7 @@ public class GuiSoundTest extends GuiScreen{
                     volume = 1;
                 }});
 
-        GuiListenerTextField pitchField = new GuiListenerTextField(parentScreen, mc.fontRenderer, width - BUTTON_SPACING - 60, bottom - (BUTTON_SPACING + 20) * 4, 60, 20, String.valueOf(pitch), "Pitch");
+        ListenerTextFieldElement pitchField = new ListenerTextFieldElement(parentScreen, mc.font, width - BUTTON_SPACING - 60, bottom - (BUTTON_SPACING + 20) * 4, 60, 20, String.valueOf(pitch), "Pitch");
         add(pitchField)
             .setPrefaceText("Pitch: ")
             .setKeyListener(key -> {
@@ -134,11 +134,11 @@ public class GuiSoundTest extends GuiScreen{
                 }});
     }
 
-    protected void buttonPressed(GuiButton button)
+    protected void buttonClicked(ButtonElement button)
     {
     }
 
-    protected void buttonReleased(GuiButton button)
+    protected void buttonReleased(ButtonElement button)
     {
     }
 
@@ -149,35 +149,35 @@ public class GuiSoundTest extends GuiScreen{
         entryIndex = index;
     }
 
-    public void drawScreen(int mouseX, int mouseY, float partialTick) {
-        drawDefaultBackground();
+    public void render(int xm, int ym, float partialTick) {
+        renderBackground();
 
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
 
-        fontRenderer.drawCenteredString(I18n.getInstance().translateKey("gui.sound_test.label.title"), width/2, 5, 0xFFFFFF);
+        font.drawCenteredString(I18n.getInstance().translateKey("gui.sound_test.label.title"), width/2, 5, 0xFFFFFF);
 
         String msg = I18n.getInstance().translateKey("gui.sound_test.label.select_entry");
-        fontRenderer.drawString(msg, leftEntry.getX() - BUTTON_SPACING - fontRenderer.getStringWidth(msg), leftEntry.getY() + 6, 0xFFFFFF);
+        font.drawString(msg, leftEntry.getX() - BUTTON_SPACING - font.getStringWidth(msg), leftEntry.getY() + 6, 0xFFFFFF);
 
         StringBuilder builder = new StringBuilder();
-        builder.append(fontRenderer.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.id", currentEntry == null ? null : currentEntry.getEventID()), width - 10)).append("\n");
-//        builder.append(fontRenderer.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.name", currentEntry == null ? null : currentEntry.name), width - 10)).append("\n");
+        builder.append(font.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.id", currentEntry == null ? null : currentEntry.getEventID()), width - 10)).append("\n");
+        builder.append(font.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.subtitle", currentEntry == null ? null : currentEntry.getSubtitleKey(), currentEntry == null ? null : currentEntry.getSubtitleTranslated()), width - 10)).append("\n");
 //        builder.append(fontRenderer.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.url", String.valueOf(currentEntry == null ? null : (showURL ? currentEntry.url : "REDACTED"))), width - 10)).append("\n");
         String[] lines = builder.toString().split("\n");
         int y = top + 30;
         for (String line : lines) {
-            fontRenderer.drawString(line, 5, y, 0xBBBBBB);
+            font.drawString(line, 5, y, 0xBBBBBB);
             y += 10;
         }
     }
     @Override
-    public void drawDefaultBackground() {
-        super.drawDefaultBackground();
+    public void renderBackground() {
+        super.renderBackground();
 
         if (mc.theWorld == null)
         {
             Tessellator tessellator = Tessellator.instance;
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
             float scale = 32F;
             tessellator.startDrawingQuads();
@@ -211,7 +211,7 @@ public class GuiSoundTest extends GuiScreen{
         if (mc.theWorld == null)
         {
             Tessellator tessellator = Tessellator.instance;
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
             float scale = 32F;
             tessellator.startDrawingQuads();
diff --git a/src/main/java/net/minecraft/client/gui/GuiStats.java b/src/main/java/net/minecraft/client/gui/StatsScreen.java
similarity index 91%
rename from src/main/java/net/minecraft/client/gui/GuiStats.java
rename to src/main/java/net/minecraft/client/gui/StatsScreen.java
index 67b936327..61c6b52fa 100644
--- a/src/main/java/net/minecraft/client/gui/GuiStats.java
+++ b/src/main/java/net/minecraft/client/gui/StatsScreen.java
@@ -15,15 +15,15 @@ import org.lwjgl.opengl.GL12;
 
 import java.util.*;
 
-public class GuiStats extends GuiScreen {
+public class StatsScreen extends Screen {
     private static final int STATS_ICON_SIZE = 18;
     private static final int COLUMN_BUTTON_SIZE = 36;
     private static final int COLUMN0_RIGHT = 115;
     private static final int COLUMN1_RIGHT = 165;
     private static final int COLUMN2_RIGHT = 215;
 
-    protected GuiScreen parent;
-    protected GuiTooltip tooltip;
+    protected Screen parent;
+    protected TooltipElement tooltip;
     protected String title;
     private GeneralStatisticsList generalStatisticsList;
     private ItemStatisticsList itemStatisticsList;
@@ -31,13 +31,13 @@ public class GuiStats extends GuiScreen {
     private final StatsCounter statsCounter;
     private ScrolledSelectionList selectionList;
 
-    public GuiStats(GuiScreen parent, StatsCounter statsCounter)
+    public StatsScreen(Screen parent, StatsCounter statsCounter)
     {
         title = I18n.getInstance().translateKey("gui.statistics.label.title");
         selectionList = null;
         this.parent = parent;
         this.statsCounter = statsCounter;
-        tooltip = new GuiTooltip(Minecraft.getMinecraft(this));
+        tooltip = new TooltipElement(Minecraft.getMinecraft(this));
     }
 
     @Override
@@ -53,24 +53,24 @@ public class GuiStats extends GuiScreen {
     public void createButtons()
     {
         I18n i18n = I18n.getInstance();
-        controlList.add(new GuiButton(0, width / 2 + 4, height - 28, 150, 20, i18n.translateKey("gui.statistics.button.done")));
-        controlList.add(new GuiButton(1, width / 2 - 154, height - 52, 100, 20, i18n.translateKey("gui.statistics.button.general")));
-        GuiButton guibutton;
-        controlList.add(guibutton = new GuiButton(2, width / 2 - 46, height - 52, 100, 20, i18n.translateKey("gui.statistics.button.blocks")));
-        GuiButton guibutton1;
-        controlList.add(guibutton1 = new GuiButton(3, width / 2 + 62, height - 52, 100, 20, i18n.translateKey("gui.statistics.button.items")));
+        buttons.add(new ButtonElement(0, width / 2 + 4, height - 28, 150, 20, i18n.translateKey("gui.statistics.button.done")));
+        buttons.add(new ButtonElement(1, width / 2 - 154, height - 52, 100, 20, i18n.translateKey("gui.statistics.button.general")));
+        ButtonElement blocksButton;
+        buttons.add(blocksButton = new ButtonElement(2, width / 2 - 46, height - 52, 100, 20, i18n.translateKey("gui.statistics.button.blocks")));
+        ButtonElement itemsButton;
+        buttons.add(itemsButton = new ButtonElement(3, width / 2 + 62, height - 52, 100, 20, i18n.translateKey("gui.statistics.button.items")));
         if(blockStatisticsList.getItemCount() == 0)
         {
-            guibutton.enabled = false;
+            blocksButton.enabled = false;
         }
         if(itemStatisticsList.getItemCount() == 0)
         {
-            guibutton1.enabled = false;
+            itemsButton.enabled = false;
         }
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
         if(!button.enabled)
         {
@@ -78,7 +78,7 @@ public class GuiStats extends GuiScreen {
         }
         if(button.id == 0)
         {
-            mc.displayGuiScreen(parent);
+            mc.displayScreen(parent);
         } else
         if(button.id == 1)
         {
@@ -95,11 +95,11 @@ public class GuiStats extends GuiScreen {
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
-        selectionList.render(mouseX, mouseY, partialTick);
-        drawStringCentered(fontRenderer, title, width / 2, 20, 0xffffff);
-        super.drawScreen(mouseX, mouseY, partialTick);
+        selectionList.render(xm, ym, partialTick);
+        drawStringCentered(font, title, width / 2, 20, 0xffffff);
+        super.render(xm, ym, partialTick);
     }
 
     private void renderItemAsIcon(int x, int y, int itemID)
@@ -108,7 +108,7 @@ public class GuiStats extends GuiScreen {
         GL11.glEnable(GL12.GL_RESCALE_NORMAL);
         Lighting.enableInventoryLight();
         Item item = Item.itemsList[itemID];
-        ItemModelDispatcher.getInstance().getDispatch(item).renderItemIntoGui(Tessellator.instance, fontRenderer, mc.renderEngine, item.getDefaultStack(), x + 2, y + 2, 1F);
+        ItemModelDispatcher.getInstance().getDispatch(item).renderItemIntoGui(Tessellator.instance, font, mc.textureManager, item.getDefaultStack(), x + 2, y + 2, 1F);
         Lighting.disable();
         GL11.glDisable(GL12.GL_RESCALE_NORMAL);
     }
@@ -151,7 +151,7 @@ public class GuiStats extends GuiScreen {
         @Override
         protected void renderHoleBackground()
         {
-            drawDefaultBackground();
+            renderBackground();
         }
 
         @Override
@@ -236,11 +236,11 @@ public class GuiStats extends GuiScreen {
             if(statItem != null)
             {
                 String s = statItem.getFormattedValue(statsCounter.readStat(statItem));
-                drawString(fontRenderer, s, x - fontRenderer.getStringWidth(s), y + 5, white ? 0xffffff : 0x909090);
+                drawString(font, s, x - font.getStringWidth(s), y + 5, white ? 0xffffff : 0x909090);
             } else
             {
                 String s1 = "-";
-                drawString(fontRenderer, s1, x - fontRenderer.getStringWidth(s1), y + 5, white ? 0xffffff : 0x909090);
+                drawString(font, s1, x - font.getStringWidth(s1), y + 5, white ? 0xffffff : 0x909090);
             }
         }
 
@@ -341,16 +341,16 @@ public class GuiStats extends GuiScreen {
         @Override
         protected void renderHoleBackground()
         {
-            drawDefaultBackground();
+            renderBackground();
         }
 
         @Override
         protected void renderItem(int index, int x, int y, int height, Tessellator tessellator)
         {
             Stat stat = StatList.basicStats.get(index);
-            drawString(fontRenderer, stat.getStatName(), x + 2, y + 1, index % 2 != 0 ? 0x909090 : 0xffffff);
+            drawString(font, stat.getStatName(), x + 2, y + 1, index % 2 != 0 ? 0x909090 : 0xffffff);
             String s = stat.getFormattedValue(statsCounter.readStat(stat));
-            drawString(fontRenderer, s, (x + 2 + 213) - fontRenderer.getStringWidth(s), y + 1, index % 2 != 0 ? 0x909090 : 0xffffff);
+            drawString(font, s, (x + 2 + 213) - font.getStringWidth(s), y + 1, index % 2 != 0 ? 0x909090 : 0xffffff);
         }
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/GuiSwitchButton.java b/src/main/java/net/minecraft/client/gui/SwitchElement.java
similarity index 80%
rename from src/main/java/net/minecraft/client/gui/GuiSwitchButton.java
rename to src/main/java/net/minecraft/client/gui/SwitchElement.java
index 3400102ce..582577ffc 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSwitchButton.java
+++ b/src/main/java/net/minecraft/client/gui/SwitchElement.java
@@ -1,18 +1,18 @@
 package net.minecraft.client.gui;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import org.lwjgl.opengl.GL11;
 
-public class GuiSwitchButton
-    extends GuiButton {
+public class SwitchElement
+    extends ButtonElement {
     private final String onText;
     private final String offText;
 
     private boolean on;
 
-    public GuiSwitchButton(int id, int xPosition, int yPosition, boolean on, String onText, String offText) {
+    public SwitchElement(int id, int xPosition, int yPosition, boolean on, String onText, String offText) {
         super(id, xPosition, yPosition, "");
 
         this.on = on;
@@ -21,7 +21,7 @@ public class GuiSwitchButton
         updateText();
     }
 
-    public GuiSwitchButton(int id, int xPosition, int yPosition, int width, int height, boolean on, String onText, String offText) {
+    public SwitchElement(int id, int xPosition, int yPosition, int width, int height, boolean on, String onText, String offText) {
         super(id, xPosition, yPosition, width, height, "");
 
         this.on = on;
@@ -51,7 +51,7 @@ public class GuiSwitchButton
     public void drawButton(Minecraft mc, int mouseX, int mouseY) {
         if (!visible) return;
 
-        FontRenderer fontrenderer = mc.fontRenderer;
+        Font font = mc.font;
         boolean mouseOver = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height;
         int state = getButtonState(mouseOver);
         int xBar = on ? (width / 3) + 1 : 0;
@@ -91,6 +91,6 @@ public class GuiSwitchButton
                 textColor = 0xFFFFA0;
                 break;
         }
-        drawStringCentered(fontrenderer, displayString, xPosition + xBar + width / 3, yPosition + (height - 8) / 2, textColor);
+        drawStringCentered(font, displayString, xPosition + xBar + width / 3, yPosition + (height - 8) / 2, textColor);
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/GuiTextField.java b/src/main/java/net/minecraft/client/gui/TextFieldElement.java
similarity index 75%
rename from src/main/java/net/minecraft/client/gui/GuiTextField.java
rename to src/main/java/net/minecraft/client/gui/TextFieldElement.java
index 140320b76..fe042f86e 100644
--- a/src/main/java/net/minecraft/client/gui/GuiTextField.java
+++ b/src/main/java/net/minecraft/client/gui/TextFieldElement.java
@@ -1,15 +1,15 @@
 package net.minecraft.client.gui;
 
 import net.minecraft.client.gui.text.TextFieldEditor;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import org.lwjgl.input.Keyboard;
 
 import net.minecraft.client.gui.text.ITextField;
 
-public class GuiTextField extends Gui implements ITextField
+public class TextFieldElement extends Gui implements ITextField
 {
 	
-    private final FontRenderer fontRenderer;
+    private final Font font;
     public int xPosition;
     public int yPosition;
     public final int width;
@@ -19,18 +19,18 @@ public class GuiTextField extends Gui implements ITextField
     private int cursorCounter;
     public boolean isFocused;
     public boolean isEnabled;
-    public GuiScreen parent;
+    public Screen parent;
 	private ITextChangeListener textChangeListener;
     private String placeholder;
     public boolean drawBackground = true;
     private TextFieldEditor editor;
 
-    public GuiTextField(GuiScreen parent, FontRenderer fontrenderer, int xPosition, int yPosition, int width, int height, String defaultText, String placeholder)
+    public TextFieldElement(Screen parent, Font font, int xPosition, int yPosition, int width, int height, String defaultText, String placeholder)
     {
         isFocused = false;
         isEnabled = true;
         this.parent = parent;
-        fontRenderer = fontrenderer;
+        this.font = font;
         this.xPosition = xPosition;
         this.yPosition = yPosition;
         this.width = width;
@@ -112,40 +112,40 @@ public class GuiTextField extends Gui implements ITextField
         }
         if (text.isEmpty() && !isFocused)
         {
-            drawString(fontRenderer, placeholder, xPosition + 4, yPosition + (height - 8) / 2, 0x5f5f5f);
+            drawString(font, placeholder, xPosition + 4, yPosition + (height - 8) / 2, 0x5f5f5f);
         }
 
         if(isEnabled)
         {
             boolean drawCursor = isFocused && (cursorCounter / 6) % 2 == 0;
             int cursor = editor.getCursor();
-            int maxDisplayableChars = this.width / fontRenderer.getCharWidth('_');
+            int maxDisplayableChars = this.width / font.getCharWidth('_');
 
             if(text.length() <= maxDisplayableChars-1){
-                drawString(fontRenderer, text, xPosition + 4, yPosition + (height - 8) / 2, 0xE0E0E0);
+                drawString(font, text, xPosition + 4, yPosition + (height - 8) / 2, 0xE0E0E0);
             } else {
                 //only draw the part of the string that's maxDisplayableChars chars around the cursor
                 int begin = Math.max(0,cursor - maxDisplayableChars);
                 int end = Math.max(maxDisplayableChars,Math.min(text.length(),cursor));
-                drawString(fontRenderer, text.substring(begin, end), xPosition + 4, yPosition + (height - 8) / 2, 0xE0E0E0);
+                drawString(font, text.substring(begin, end), xPosition + 4, yPosition + (height - 8) / 2, 0xE0E0E0);
             }
             if (drawCursor)
             {
-                int width = fontRenderer.getStringWidth(text);
+                int width = font.getStringWidth(text);
                 if (cursor < text.length())
                 {
-                    width = fontRenderer.getStringWidth(text.substring(0, cursor));
+                    width = font.getStringWidth(text.substring(0, cursor));
                 }
                 if(width >= this.width-4){
                     // width of the text box - the width of the last character
-                    width = (this.width-4) - fontRenderer.getStringWidth(text.substring(text.length()-2,text.length()-1));
+                    width = (this.width-4) - font.getStringWidth(text.substring(text.length()-2,text.length()-1));
                 }
-                drawString(fontRenderer, "_", xPosition + 4 + width, yPosition + (height - 8) / 2, 0xE0E0E0);
+                drawString(font, "_", xPosition + 4 + width, yPosition + (height - 8) / 2, 0xE0E0E0);
             }
         }
         else
         {
-            drawString(fontRenderer, text, xPosition + 4, yPosition + (height - 8) / 2, 0x707070);
+            drawString(font, text, xPosition + 4, yPosition + (height - 8) / 2, 0x707070);
         }
     }
 
@@ -165,6 +165,6 @@ public class GuiTextField extends Gui implements ITextField
 
     public interface ITextChangeListener
     {
-    	void textChanged(GuiTextField textField);
+    	void textChanged(TextFieldElement textField);
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/GuiTextureViewer.java b/src/main/java/net/minecraft/client/gui/TextureViewerScreen.java
similarity index 67%
rename from src/main/java/net/minecraft/client/gui/GuiTextureViewer.java
rename to src/main/java/net/minecraft/client/gui/TextureViewerScreen.java
index f416f7538..6d07f2ad3 100644
--- a/src/main/java/net/minecraft/client/gui/GuiTextureViewer.java
+++ b/src/main/java/net/minecraft/client/gui/TextureViewerScreen.java
@@ -1,11 +1,10 @@
 package net.minecraft.client.gui;
 
 import net.minecraft.client.GLAllocation;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.client.gui.modelviewer.elements.IListenerElement;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texture.Texture;
-import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.util.helper.Textures;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.helper.Utils;
@@ -22,14 +21,14 @@ import static org.lwjgl.opengl.GL11.GL_TEXTURE_HEIGHT;
 import static org.lwjgl.opengl.GL11.GL_TEXTURE_WIDTH;
 import static org.lwjgl.opengl.GL11.glGetTexLevelParameteri;
 
-public class GuiTextureViewer extends GuiScreen{
+public class TextureViewerScreen extends Screen {
     private static final int TOP_SPACING = 24;
     private static final int BUTTON_SPACING = 4;
 
     protected int top;
     protected int bottom;
 
-    protected GuiListenerButton leftTexCycle;
+    protected ListenerButtonElement leftTexCycle;
 
     protected int texIndex = 0;
 
@@ -37,33 +36,33 @@ public class GuiTextureViewer extends GuiScreen{
     protected boolean flip = false;
     protected boolean drawText = true;
 
-    public GuiTextureViewer(GuiScreen parent) {
+    public TextureViewerScreen(Screen parent) {
         super(parent);
     }
 
     @Override
-    public void keyTyped(char c, int key, int mouseX, int mouseY)
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
-        if (key == Keyboard.KEY_LEFT) {
+        if (eventKey == Keyboard.KEY_LEFT) {
             cycleTexture(-1);
-        } else if (key == Keyboard.KEY_RIGHT) {
+        } else if (eventKey == Keyboard.KEY_RIGHT) {
             cycleTexture(1);
-        } else if (key == Keyboard.KEY_ESCAPE) {
-            mc.displayGuiScreen(parentScreen);
+        } else if (eventKey == Keyboard.KEY_ESCAPE) {
+            mc.displayScreen(parentScreen);
         }
-        List<GuiButton> _buttons = new ArrayList<>(controlList);
-        for (GuiButton button : _buttons){
-            if (button instanceof IListenerElement && button.isHovered(mouseX, mouseY)){
-                ((IListenerElement<?>) button).onKeyTyped(c, key);
+        List<ButtonElement> _buttons = new ArrayList<>(buttons);
+        for (ButtonElement button : _buttons){
+            if (button instanceof IListenerElement && button.isHovered(mx, my)){
+                ((IListenerElement<?>) button).onKeyTyped(eventCharacter, eventKey);
             }
         }
     }
     @Override
     public void tick(){
-        List<GuiButton> _buttons = new ArrayList<>(controlList);
-        for (GuiButton button : _buttons){
-            if (button instanceof GuiListenerButton){
-                ((GuiListenerButton) button).tick();
+        List<ButtonElement> _buttons = new ArrayList<>(buttons);
+        for (ButtonElement button : _buttons){
+            if (button instanceof ListenerButtonElement){
+                ((ListenerButtonElement) button).tick();
             }
         }
     }
@@ -72,38 +71,38 @@ public class GuiTextureViewer extends GuiScreen{
 
         top = TOP_SPACING;
         bottom = height - (BUTTON_SPACING + 20 + BUTTON_SPACING);
-        add(new GuiListenerButton(0, width/2 - 100, height - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.options.button.done")).setActionListener(() -> {
-            onClosed();
-            mc.displayGuiScreen(null);
+        add(new ListenerButtonElement(0, width/2 - 100, height - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.options.button.done")).setActionListener(() -> {
+            removed();
+            mc.displayScreen(null);
         }));
 
-        leftTexCycle = add(new GuiListenerButton(1, width - (20 + BUTTON_SPACING) * 2, bottom - (BUTTON_SPACING + 20), 20, 20, "<")
+        leftTexCycle = add(new ListenerButtonElement(1, width - (20 + BUTTON_SPACING) * 2, bottom - (BUTTON_SPACING + 20), 20, 20, "<")
             .setActionListener(() -> cycleTexture(-1)));
-        add(new GuiListenerButton(2, width - (20 + BUTTON_SPACING) * 1, bottom - (BUTTON_SPACING + 20), 20, 20, ">")
+        add(new ListenerButtonElement(2, width - (20 + BUTTON_SPACING) * 1, bottom - (BUTTON_SPACING + 20), 20, 20, ">")
             .setActionListener(() -> cycleTexture(1)));
 
-        add(new GuiListenerButton(11, BUTTON_SPACING, bottom - BUTTON_SPACING - 20, 20, 20, "V")
+        add(new ListenerButtonElement(11, BUTTON_SPACING, bottom - BUTTON_SPACING - 20, 20, 20, "V")
             .setActionListener(() -> drawCheckers = !drawCheckers)
         );
-        add(new GuiListenerButton(11, 20 + BUTTON_SPACING * 2, bottom - BUTTON_SPACING - 20, 20, 20, "F")
+        add(new ListenerButtonElement(11, 20 + BUTTON_SPACING * 2, bottom - BUTTON_SPACING - 20, 20, 20, "F")
             .setActionListener(() -> flip = !flip)
         );
-        add(new GuiListenerButton(12, 40 + BUTTON_SPACING * 3, bottom - BUTTON_SPACING - 20, 20, 20, "D")
+        add(new ListenerButtonElement(12, 40 + BUTTON_SPACING * 3, bottom - BUTTON_SPACING - 20, 20, 20, "D")
             .setActionListener(() -> {
                 Textures.dumpTextures();
                 Utils.openDirectory(new File("dumpTextures"));
             })
         );
-        add(new GuiListenerButton(13, 60 + BUTTON_SPACING * 4, bottom - BUTTON_SPACING - 20, 20, 20, "T")
+        add(new ListenerButtonElement(13, 60 + BUTTON_SPACING * 4, bottom - BUTTON_SPACING - 20, 20, 20, "T")
             .setActionListener(() -> drawText = !drawText)
         );
     }
 
-    protected void buttonPressed(GuiButton button)
+    protected void buttonClicked(ButtonElement button)
     {
     }
 
-    protected void buttonReleased(GuiButton button)
+    protected void buttonReleased(ButtonElement button)
     {
     }
 
@@ -116,16 +115,16 @@ public class GuiTextureViewer extends GuiScreen{
         texIndex = texIndex % textureList.size();
     }
 
-    public void drawScreen(int mouseX, int mouseY, float partialTick) {
-        drawDefaultBackground();
+    public void render(int xm, int ym, float partialTick) {
+        renderBackground();
 
-        fontRenderer.drawCenteredString(I18n.getInstance().translateKey("gui.texture_viewer.label.title"), width/2, 5, 0xFFFFFF);
+        font.drawCenteredString(I18n.getInstance().translateKey("gui.texture_viewer.label.title"), width/2, 5, 0xFFFFFF);
 
         List<Integer> textureList = GLAllocation.textureNames;
         int id = texIndex % textureList.size();
         GL11.glBindTexture(GL_TEXTURE_2D, textureList.get(id));
 
-        Texture t = mc.renderEngine.idToTextureMap.get(textureList.get(id));
+        Texture t = mc.textureManager.idToTextureMap.get(textureList.get(id));
 
 
         GL11.glEnable(GL_BLEND);
@@ -149,7 +148,7 @@ public class GuiTextureViewer extends GuiScreen{
         Tessellator tessellator = Tessellator.instance;
 
         if (drawCheckers) {
-            mc.renderEngine.bindTexture(mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/designer_bg.png"));
+            mc.textureManager.bindTexture(mc.textureManager.loadTexture("/assets/minecraft/textures/gui/designer_bg.png"));
             tessellator.startDrawingQuads();
             tessellator.addVertexWithUV(x + 0,         y + imgHeight,   zLevel, 0,          imgHeight/2);
             tessellator.addVertexWithUV(x + imgWidth,  y + imgHeight,   zLevel, imgWidth/2, imgHeight/2);
@@ -182,14 +181,14 @@ public class GuiTextureViewer extends GuiScreen{
 
 //        drawGuiIcon((width - bw)/2, (height - bh)/2, bw, bh, TextureRegistry.getTexture("minecraft:gui/widgets/button"));
 
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
 
         GL11.glDisable(GL11.GL_DEPTH_TEST);
 
         if (drawText) {
-            fontRenderer.drawString("Tex ID: " + id , 1, top + 1, 0xFFFFFF, true);
-            fontRenderer.drawString("Tex Width: " + texWidth, 1, top + 11, 0xFFFFFF, true);
-            fontRenderer.drawString("Tex Height: " + texHeight, 1, top + 21, 0xFFFFFF, true);
+            font.drawString("Tex ID: " + id , 1, top + 1, 0xFFFFFF, true);
+            font.drawString("Tex Width: " + texWidth, 1, top + 11, 0xFFFFFF, true);
+            font.drawString("Tex Height: " + texHeight, 1, top + 21, 0xFFFFFF, true);
 
             String s;
             if (t == null) {
@@ -200,19 +199,19 @@ public class GuiTextureViewer extends GuiScreen{
             String[] lines = s.split("\n");
             int yOff = top + 31;
             for (String line : lines) {
-                fontRenderer.drawString(line, 1, yOff, 0xFFFFFF, true);
+                font.drawString(line, 1, yOff, 0xFFFFFF, true);
                 yOff += 10;
             }
         }
     }
     @Override
-    public void drawDefaultBackground() {
-        super.drawDefaultBackground();
+    public void renderBackground() {
+        super.renderBackground();
 
         if (mc.theWorld == null)
         {
             Tessellator tessellator = Tessellator.instance;
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
             float scale = 32F;
             tessellator.startDrawingQuads();
diff --git a/src/main/java/net/minecraft/client/gui/GuiTexturedButton.java b/src/main/java/net/minecraft/client/gui/TexturedButtonElement.java
similarity index 81%
rename from src/main/java/net/minecraft/client/gui/GuiTexturedButton.java
rename to src/main/java/net/minecraft/client/gui/TexturedButtonElement.java
index e7f2e164f..e8627cecb 100644
--- a/src/main/java/net/minecraft/client/gui/GuiTexturedButton.java
+++ b/src/main/java/net/minecraft/client/gui/TexturedButtonElement.java
@@ -3,12 +3,12 @@ package net.minecraft.client.gui;
 import net.minecraft.client.Minecraft;
 import org.lwjgl.opengl.GL11;
 
-public class GuiTexturedButton extends GuiButton {
+public class TexturedButtonElement extends ButtonElement {
     private final String texturePath;
     private int u;
     private int v;
 
-    public GuiTexturedButton(int id, String texturePath, int xPosition, int yPosition, int u, int v, int width, int height) {
+    public TexturedButtonElement(int id, String texturePath, int xPosition, int yPosition, int u, int v, int width, int height) {
         super(id, xPosition, yPosition,width, height, "");
         this.texturePath = texturePath;
         this.u = u;
@@ -20,7 +20,7 @@ public class GuiTexturedButton extends GuiButton {
         if (!visible) {
             return;
         }
-        mc.renderEngine.loadTexture(texturePath).bind();
+        mc.textureManager.loadTexture(texturePath).bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         boolean isHovered = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height;
         if (!enabled)
diff --git a/src/main/java/net/minecraft/client/gui/GuiTooltip.java b/src/main/java/net/minecraft/client/gui/TooltipElement.java
similarity index 97%
rename from src/main/java/net/minecraft/client/gui/GuiTooltip.java
rename to src/main/java/net/minecraft/client/gui/TooltipElement.java
index c9a42285b..54353f1d0 100644
--- a/src/main/java/net/minecraft/client/gui/GuiTooltip.java
+++ b/src/main/java/net/minecraft/client/gui/TooltipElement.java
@@ -6,7 +6,7 @@ import net.minecraft.core.data.registry.recipe.entry.RecipeEntryTrommel;
 import net.minecraft.core.data.registry.recipe.RecipeSymbol;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.client.option.enums.TooltipStyle;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.player.inventory.slot.Slot;
 import net.minecraft.core.player.inventory.slot.ResultSlot;
@@ -18,15 +18,15 @@ import org.lwjgl.opengl.GL11;
 
 import com.mojang.nbt.CompoundTag;
 
-public class GuiTooltip extends Gui
+public class TooltipElement extends Gui
 {
     Minecraft mc;
-    FontRenderer fr;
+    Font fr;
 
-    public GuiTooltip(Minecraft mc)
+    public TooltipElement(Minecraft mc)
     {
         this.mc = mc;
-        this.fr = mc.fontRenderer;
+        this.fr = mc.font;
     }
     public static final int BASE_PADDING = 3;
     public static final int LINE_SPACING = 3;
@@ -117,7 +117,7 @@ public class GuiTooltip extends Gui
 
         Tessellator tl = Tessellator.instance;
 
-        mc.renderEngine.bindTexture(mc.renderEngine.loadTexture(mc.gameSettings.tooltipStyle.value.getFilePath()));
+        mc.textureManager.bindTexture(mc.textureManager.loadTexture(mc.gameSettings.tooltipStyle.value.getFilePath()));
 
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
diff --git a/src/main/java/net/minecraft/client/gui/GuiWandPickerMonster.java b/src/main/java/net/minecraft/client/gui/WandMobPickerScreen.java
similarity index 89%
rename from src/main/java/net/minecraft/client/gui/GuiWandPickerMonster.java
rename to src/main/java/net/minecraft/client/gui/WandMobPickerScreen.java
index e6dd56191..a54c7e0f9 100644
--- a/src/main/java/net/minecraft/client/gui/GuiWandPickerMonster.java
+++ b/src/main/java/net/minecraft/client/gui/WandMobPickerScreen.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.gui.popup.GuiPopup;
+import net.minecraft.client.gui.popup.PopupScreen;
 import net.minecraft.client.gui.popup.PopupBuilder;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityDispatcher;
@@ -14,13 +14,13 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-public class GuiWandPickerMonster extends GuiScreen {
+public class WandMobPickerScreen extends Screen {
     private String mobId;
     private boolean shouldClose = false;
     private final ItemStack wand;
 
 
-    public GuiWandPickerMonster(String mobId, ItemStack itemStack) {
+    public WandMobPickerScreen(String mobId, ItemStack itemStack) {
         this.mobId = mobId;
         wand = itemStack;
     }
@@ -46,7 +46,7 @@ public class GuiWandPickerMonster extends GuiScreen {
             prettyMonsters.add(sb.toString());
         }
 
-        GuiPopup popup = new PopupBuilder(this, 150)
+        PopupScreen popup = new PopupBuilder(this, 150)
                 .withLabel("gui.pick_monster.label.title")
                 .withList("list", 140, prettyMonsters.toArray(new String[0]), null, -1, true)
                 .closeOnEsc(0)
@@ -63,14 +63,14 @@ public class GuiWandPickerMonster extends GuiScreen {
                     shouldClose = true;
                 })
                 .build();
-        mc.displayGuiScreen(popup);
+        mc.displayScreen(popup);
     }
 
     @Override
     public void tick() {
         super.tick();
         if (shouldClose) {
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
         }
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/achievements/GuiAchievements.java b/src/main/java/net/minecraft/client/gui/achievements/AchievementsScreen.java
similarity index 91%
rename from src/main/java/net/minecraft/client/gui/achievements/GuiAchievements.java
rename to src/main/java/net/minecraft/client/gui/achievements/AchievementsScreen.java
index 4ddc835e7..e0f690869 100644
--- a/src/main/java/net/minecraft/client/gui/achievements/GuiAchievements.java
+++ b/src/main/java/net/minecraft/client/gui/achievements/AchievementsScreen.java
@@ -1,14 +1,14 @@
 package net.minecraft.client.gui.achievements;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiRenderItem;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.GuiTooltip;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.ItemElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.achievements.data.AchievementPage;
 import net.minecraft.client.gui.achievements.data.AchievementPageRegistry;
 import net.minecraft.client.gui.achievements.data.AchievementPages;
-import net.minecraft.client.gui.options.GuiOptionsButton;
+import net.minecraft.client.gui.options.OptionsButtonElement;
 import net.minecraft.client.render.Lighting;
 import net.minecraft.client.render.Scissor;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
@@ -37,7 +37,7 @@ import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
 import static org.lwjgl.opengl.GL11.glDisable;
 import static org.lwjgl.opengl.GL11.glEnable;
 
-public class GuiAchievements extends GuiScreen
+public class AchievementsScreen extends Screen
 {
 
 
@@ -67,9 +67,9 @@ public class GuiAchievements extends GuiScreen
     protected double currentShiftY;
     private boolean draggingViewport;
     private final StatsCounter statsCounter;
-    private final GuiTooltip tooltip;
-    private GuiRenderItem renderItem = null;
-    GuiScreen parent;
+    private final TooltipElement tooltip;
+    private ItemElement renderItem = null;
+    Screen parent;
 
     private int top;
     private int bottom;
@@ -104,7 +104,7 @@ public class GuiAchievements extends GuiScreen
 
     private @NotNull BGLayer[] layers;
 
-    public GuiAchievements(GuiScreen parent, StatsCounter statsCounter)
+    public AchievementsScreen(Screen parent, StatsCounter statsCounter)
     {
         mouseXOld = 0;
         mouseYOld = 0;
@@ -113,8 +113,8 @@ public class GuiAchievements extends GuiScreen
 
         this.parent = parent;
         this.mc = Minecraft.getMinecraft(this);
-        this.tooltip = new GuiTooltip(mc);
-        this.renderItem = new GuiRenderItem(mc);
+        this.tooltip = new TooltipElement(mc);
+        this.renderItem = new ItemElement(mc);
 
         layers = new BGLayer[currentPage.backgroundLayers()];
         for (int i = 0; i < layers.length; i++) {
@@ -125,8 +125,8 @@ public class GuiAchievements extends GuiScreen
     @Override
 	public void init()
     {
-        controlList.clear();
-        controlList.add(new GuiOptionsButton(1, width / 2 - 100, height - 20 - BUTTON_SPACING, 200, 20, I18n.getInstance().translateKey("gui.achievements.button.done")));
+        buttons.clear();
+        buttons.add(new OptionsButtonElement(1, width / 2 - 100, height - 20 - BUTTON_SPACING, 200, 20, I18n.getInstance().translateKey("gui.achievements.button.done")));
 
         lastTileX = Integer.MIN_VALUE;
         lastTileY = Integer.MIN_VALUE;
@@ -185,33 +185,33 @@ public class GuiAchievements extends GuiScreen
     }
 
     @Override
-	protected void buttonPressed(GuiButton button) {
+	protected void buttonClicked(ButtonElement button) {
         if(button.id == 1) {
-            mc.displayGuiScreen(parent);
+            mc.displayScreen(parent);
             //mc.setIngameFocus();
         }
-        super.buttonPressed(button);
+        super.buttonClicked(button);
     }
 
     @Override
-	public void keyTyped(char c, int key, int mouseX, int mouseY)
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
-        if (key == Keyboard.KEY_ESCAPE) {
-            mc.displayGuiScreen(parent);
+        if (eventKey == Keyboard.KEY_ESCAPE) {
+            mc.displayScreen(parent);
         } else {
-            super.keyTyped(c, key, mouseX, mouseY);
+            super.keyPressed(eventCharacter, eventKey, mx, my);
         }
     }
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
-        if (drawSidebar() && mouseX >= pageListLeft && mouseX <= (pageListRight - 6) && mouseY >= top && mouseY <= bottom) {
+    public void mouseClicked(int mx, int my, int buttonNum) {
+        if (drawSidebar() && mx >= pageListLeft && mx <= (pageListRight - 6) && my >= top && my <= bottom) {
             int pagesListHeight = getTotalPagesListHeight();
             int pagesListY = top - (int) pageListScrollAmount;
             if (pagesListHeight < bottom - top) {
                 pagesListY = top + (bottom - top - pagesListHeight) / 2;
             }
             for(AchievementPage page : AchievementPageRegistry.getInstance().getPages()) {
-                if (mouseX >= pageListLeft && mouseX <= (pageListRight - 6) && mouseY >= pagesListY && mouseY <= pagesListY + PAGE_BUTTON_HEIGHT) {
+                if (mx >= pageListLeft && mx <= (pageListRight - 6) && my >= pagesListY && my <= pagesListY + PAGE_BUTTON_HEIGHT) {
                     currentPage = page;
                     mc.sndManager.playSound("random.click", SoundCategory.GUI_SOUNDS, 1.0F, 1.0F);
 
@@ -226,27 +226,27 @@ public class GuiAchievements extends GuiScreen
                 pagesListY += PAGE_BUTTON_HEIGHT;
             }
         }
-        super.mouseClicked(mouseX, mouseY, mouseButton);
+        super.mouseClicked(mx, my, buttonNum);
 
-        clickX = mouseX;
-        clickY = mouseY;
+        clickX = mx;
+        clickY = my;
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
         if(Mouse.isButtonDown(0)) {
-            if(mouseX >= viewportLeft && mouseX < viewportRight && mouseY >= viewportTop && mouseY < viewportBottom) {
+            if(xm >= viewportLeft && xm < viewportRight && ym >= viewportTop && ym < viewportBottom) {
                 if(!draggingViewport) {
                     draggingViewport = true;
                 } else {
-                    targetShiftX -= (mouseX - mouseXOld) / viewportZoom;
-                    targetShiftY -= (mouseY - mouseYOld) / viewportZoom;
+                    targetShiftX -= (xm - mouseXOld) / viewportZoom;
+                    targetShiftY -= (ym - mouseYOld) / viewportZoom;
                     currentShiftX = oldShiftX = targetShiftX;
                     currentShiftY = oldShiftY = targetShiftY;
                 }
-                mouseXOld = mouseX;
-                mouseYOld = mouseY;
+                mouseXOld = xm;
+                mouseYOld = ym;
             }
             currentShiftX =  MathHelper.clamp(currentShiftX, shiftMinX, shiftMaxX);
             currentShiftY =  MathHelper.clamp(currentShiftY, shiftMinY, shiftMaxY);
@@ -257,14 +257,14 @@ public class GuiAchievements extends GuiScreen
             draggingViewport = false;
         }
 
-        if (drawSidebar() &&mouseX >= pageListLeft && mouseX <= pageListRight) {
+        if (drawSidebar() && xm >= pageListLeft && xm <= pageListRight) {
             if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) {
                 scrollPagesList(Mouse.getDWheel() / -0.01f);
             } else {
                 scrollPagesList(Mouse.getDWheel() / -0.05f);
             }
             onScrollPagesList();
-        } else if (mouseX >= viewportLeft && mouseX <= viewportRight && mouseY >= viewportTop && mouseY <= viewportBottom){
+        } else if (xm >= viewportLeft && xm <= viewportRight && ym >= viewportTop && ym <= viewportBottom){
             viewportZoom = MathHelper.clamp(viewportZoom + (Mouse.getDWheel()/10d), 0.5d, 2);
 
             // Make zoom notch onto integer multiples
@@ -278,13 +278,13 @@ public class GuiAchievements extends GuiScreen
         }
         Mouse.getDWheel();
 
-        drawDefaultBackground();
+        renderBackground();
 
         if (drawSidebar()){
             overlayBackground(0, pageListRight, top, bottom, 0x202020);
         }
 
-        renderAchievementsPanel(mouseX, mouseY, partialTick);
+        renderAchievementsPanel(xm, ym, partialTick);
 
         overlayBackground(0, width, 0, top, 0x404040);
         overlayBackground(0, width, bottom, height, 0x404040);
@@ -296,7 +296,7 @@ public class GuiAchievements extends GuiScreen
         GL11.glShadeModel(GL11.GL_SMOOTH);
         GL11.glEnable(GL11.GL_TEXTURE_2D);
 
-        super.drawScreen(mouseX, mouseY, partialTick); // Draw Buttons
+        super.render(xm, ym, partialTick); // Draw Buttons
         GL11.glEnable(GL11.GL_DEPTH_TEST);
         GL11.glEnable(GL11.GL_LIGHTING);
         Lighting.disable();
@@ -314,8 +314,8 @@ public class GuiAchievements extends GuiScreen
             if (pagesListHeight < bottom - top) {
                 pagesListY = top + (bottom - top - pagesListHeight) / 2;
             }
-            if (mouseY >= top && mouseY <= bottom) {
-                hoveredPage = drawPagesListItems(pageListLeft + PADDING - 4, pagesListY, pageListRight - PADDING, mouseX, mouseY);
+            if (ym >= top && ym <= bottom) {
+                hoveredPage = drawPagesListItems(pageListLeft + PADDING - 4, pagesListY, pageListRight - PADDING, xm, ym);
             } else {
                 hoveredPage = drawPagesListItems(pageListLeft + PADDING - 4, pagesListY, pageListRight - PADDING, -1, -1);
             }
@@ -391,14 +391,14 @@ public class GuiAchievements extends GuiScreen
         }
 
         if (hoveredAchievement != null){
-            drawAchievementToolTip(hoveredAchievement, mouseX, mouseY);
+            drawAchievementToolTip(hoveredAchievement, xm, ym);
         }
 
         if (drawSidebar()) {
-            drawPagesListScrollBar(mouseX, mouseY);
+            drawPagesListScrollBar(xm, ym);
 
             if (hoveredPage != null){
-                String msg = fontRenderer.wrapFormattedStringToWidth(hoveredPage.getDescription(), TOOLTIP_BOX_WIDTH_MIN);
+                String msg = font.wrapFormattedStringToWidth(hoveredPage.getDescription(), TOOLTIP_BOX_WIDTH_MIN);
                 int completed = 0;
                 for (Achievement a : hoveredPage.getAchievements()){
                     if (statsCounter.isUnlocked(a)){
@@ -406,7 +406,7 @@ public class GuiAchievements extends GuiScreen
                     }
                 }
                 msg += "\n" + TextFormatting.LIGHT_GRAY + I18n.getInstance().translateKeyAndFormat("gui.achievements.label.completion",  Math.round(hoveredPage.getCompletionFraction(statsCounter) * 100) + "%");
-                tooltip.render(msg, mouseX, mouseY, TOOLTIP_OFF_X, TOOLTIP_OFF_Y);
+                tooltip.render(msg, xm, ym, TOOLTIP_OFF_X, TOOLTIP_OFF_Y);
             }
         }
 
@@ -434,7 +434,7 @@ public class GuiAchievements extends GuiScreen
     }
 
     protected void renderLabels() {
-        fontRenderer.drawCenteredString(I18n.getInstance().translateKey("gui.achievements.label.title")/* + " " + viewportZoom + " X:" + currentShiftX + ", Y:" + currentShiftY*/, width/2, 5 , 0xFFFFFF);
+        font.drawCenteredString(I18n.getInstance().translateKey("gui.achievements.label.title")/* + " " + viewportZoom + " X:" + currentShiftX + ", Y:" + currentShiftY*/, width/2, 5 , 0xFFFFFF);
     }
 
 
@@ -822,7 +822,7 @@ public class GuiAchievements extends GuiScreen
             GL11.glTranslated(achViewX + 3 * zoom, achViewY + 3 * zoom, 0);
             GL11.glScaled(zoom, zoom, 1);
             ItemModelDispatcher.getInstance().getDispatch(achievementItem)
-                .renderItemIntoGui(Tessellator.instance, mc.fontRenderer, mc.renderEngine, achievementItem.getDefaultStack(), 0, 0, 1.0f);
+                .renderItemIntoGui(Tessellator.instance, mc.font, mc.textureManager, achievementItem.getDefaultStack(), 0, 0, 1.0f);
 
             GL11.glDisable(GL11.GL_LIGHTING);
             GL11.glPopMatrix();
@@ -842,25 +842,25 @@ public class GuiAchievements extends GuiScreen
         final int padding = tooltip.getPadding();
         int[] boxRender;
         if(statsCounter.canUnlock(achievement)) { // Can unlock/ is unlocked
-            int boxWidth = Math.max(fontRenderer.getStringWidth(name), TOOLTIP_BOX_WIDTH_MIN);
-            int boxHeight = fontRenderer.getHeightOfConstrainedString(desc, boxWidth);
+            int boxWidth = Math.max(font.getStringWidth(name), TOOLTIP_BOX_WIDTH_MIN);
+            int boxHeight = font.getHeightOfConstrainedString(desc, boxWidth);
             if(statsCounter.isUnlocked(achievement)) {
                 boxHeight += 12;
             }
             boxRender = tooltip.drawBackground(mouseX, mouseY, TOOLTIP_OFF_X, TOOLTIP_OFF_Y, boxWidth + 3, boxHeight + 3 + 12);
-            fontRenderer.drawStringIntoConstrainedBlock(desc, boxRender[0] + padding, boxRender[1] + 12 + padding, boxWidth, 0xffa0a0a0);
+            font.drawStringIntoConstrainedBlock(desc, boxRender[0] + padding, boxRender[1] + 12 + padding, boxWidth, 0xffa0a0a0);
             if(statsCounter.isUnlocked(achievement)) { // Add taken string to bottom
-                fontRenderer.drawStringWithShadow(I18n.getInstance().translateKey("gui.achievements.label.taken"), boxRender[0] + padding, boxRender[1] + boxHeight + 8 + padding, 0xff9090ff);
+                font.drawStringWithShadow(I18n.getInstance().translateKey("gui.achievements.label.taken"), boxRender[0] + padding, boxRender[1] + boxHeight + 8 + padding, 0xff9090ff);
             }
         } else { // Not unlocked so darken
-            int boxWidth = Math.max(fontRenderer.getStringWidth(name), TOOLTIP_BOX_WIDTH_MIN);
+            int boxWidth = Math.max(font.getStringWidth(name), TOOLTIP_BOX_WIDTH_MIN);
             String msg = I18n.getInstance().translateKeyAndFormat("gui.achievements.label.requires", achievement.parent.getStatName());
-            int boxHeight = fontRenderer.getHeightOfConstrainedString(msg, boxWidth);
+            int boxHeight = font.getHeightOfConstrainedString(msg, boxWidth);
             boxRender = tooltip.drawBackground(mouseX, mouseY, TOOLTIP_OFF_X, TOOLTIP_OFF_Y, boxWidth + 3, boxHeight + 3 + 12);
-            fontRenderer.drawStringIntoConstrainedBlock(msg, boxRender[0] + padding, boxRender[1] + 12 + padding, boxWidth, 0xff705050);
+            font.drawStringIntoConstrainedBlock(msg, boxRender[0] + padding, boxRender[1] + 12 + padding, boxWidth, 0xff705050);
         }
         int color = statsCounter.canUnlock(achievement) ? achievement.getType().colorName : achievement.getType().colorNameLocked;
-        fontRenderer.drawStringWithShadow(name, boxRender[0] + padding, boxRender[1] + padding, color);
+        font.drawStringWithShadow(name, boxRender[0] + padding, boxRender[1] + padding, color);
     }
     public boolean drawSidebar(){
         return AchievementPageRegistry.getInstance().getPages().size() > 1;
@@ -900,7 +900,7 @@ public class GuiAchievements extends GuiScreen
                 GL11.glColor4f(1f, 1f, 1f, 1f);
                 drawGuiIcon(x + 8, y2 + (PAGE_BUTTON_HEIGHT / 2) - 9 + 8, 11, 11, TextureRegistry.getTexture("minecraft:gui/achievement/star"));
             }
-            mc.fontRenderer.drawStringWithShadow(name, x + 19, y2 + (PAGE_BUTTON_HEIGHT / 2) - 4, textColor);
+            mc.font.drawStringWithShadow(name, x + 19, y2 + (PAGE_BUTTON_HEIGHT / 2) - 4, textColor);
             y2 += PAGE_BUTTON_HEIGHT;
         }
 
@@ -954,7 +954,7 @@ public class GuiAchievements extends GuiScreen
     private void overlayBackground(int minX, int maxX, int minY, int maxY, int color)
     {
         Tessellator tessellator = Tessellator.instance;
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         float scale = 32F;
         tessellator.startDrawingQuads();
diff --git a/src/main/java/net/minecraft/client/gui/achievements/data/AchievementPage.java b/src/main/java/net/minecraft/client/gui/achievements/data/AchievementPage.java
index d6798d336..656bf7e2c 100644
--- a/src/main/java/net/minecraft/client/gui/achievements/data/AchievementPage.java
+++ b/src/main/java/net/minecraft/client/gui/achievements/data/AchievementPage.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.gui.achievements.data;
 
-import net.minecraft.client.gui.achievements.GuiAchievements;
+import net.minecraft.client.gui.achievements.AchievementsScreen;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.core.achievement.Achievement;
@@ -29,9 +29,9 @@ public abstract class AchievementPage {
 
     public abstract @NotNull Achievement onOpenAchievement();
 
-    public abstract @Nullable IconCoordinate getBackgroundTile(GuiAchievements gui, int layer, Random random, int tileX, int tileY);
+    public abstract @Nullable IconCoordinate getBackgroundTile(AchievementsScreen screen, int layer, Random random, int tileX, int tileY);
 
-    public abstract void postProcessBackground(GuiAchievements gui, Random random, GuiAchievements.BGLayer layerCache, int orgX, int orgY);
+    public abstract void postProcessBackground(AchievementsScreen screen, Random random, AchievementsScreen.BGLayer layerCache, int orgX, int orgY);
 
     public abstract @NotNull ItemStack getIcon();
 
diff --git a/src/main/java/net/minecraft/client/gui/achievements/pages/NetherPage.java b/src/main/java/net/minecraft/client/gui/achievements/pages/NetherPage.java
index 46720681f..33cfda288 100644
--- a/src/main/java/net/minecraft/client/gui/achievements/pages/NetherPage.java
+++ b/src/main/java/net/minecraft/client/gui/achievements/pages/NetherPage.java
@@ -1,9 +1,8 @@
 package net.minecraft.client.gui.achievements.pages;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.achievements.GuiAchievements;
+import net.minecraft.client.gui.achievements.AchievementsScreen;
 import net.minecraft.client.gui.achievements.data.AchievementPage;
-import net.minecraft.client.gui.achievements.data.AchievementPages;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.achievement.Achievement;
@@ -42,7 +41,7 @@ public class NetherPage extends AchievementPage {
     }
 
     @Override
-    public IconCoordinate getBackgroundTile(GuiAchievements guiAchievements, int layer, Random random, int tileX, int tileY) {
+    public IconCoordinate getBackgroundTile(AchievementsScreen screen, int layer, Random random, int tileX, int tileY) {
         random.setSeed(random.nextLong() + key.hashCode()); // makes seed different for each instance of this class :)
 
         final int bedrockLayer = 35;
@@ -61,7 +60,7 @@ public class NetherPage extends AchievementPage {
     }
 
     @Override
-    public void postProcessBackground(GuiAchievements gui, Random random, GuiAchievements.BGLayer layerCache, int orgX, int orgY) {
+    public void postProcessBackground(AchievementsScreen screen, Random random, AchievementsScreen.BGLayer layerCache, int orgX, int orgY) {
         if (layerCache.id == 0) {
             int lastY = 0;
             int cave = -1;
@@ -71,7 +70,7 @@ public class NetherPage extends AchievementPage {
                 }
                 if (cave > 0){
                     lastY = (25 + random.nextInt(4) - random.nextInt(4));
-                    carveCircle(gui, layerCache, _x - orgX, lastY - orgY, 2 + random.nextInt(3));
+                    carveCircle(screen, layerCache, _x - orgX, lastY - orgY, 2 + random.nextInt(3));
                 }
                 cave--;
             }
@@ -81,7 +80,7 @@ public class NetherPage extends AchievementPage {
                     cave = 5 + random.nextInt(5) - random.nextInt(5);
                 }
                 if (cave > 0){
-                    carveCircle(gui, layerCache, _x - orgX, (10 + random.nextInt(2) - random.nextInt(2)) - orgY, random.nextInt(3));
+                    carveCircle(screen, layerCache, _x - orgX, (10 + random.nextInt(2) - random.nextInt(2)) - orgY, random.nextInt(3));
                 }
                 cave--;
             }
@@ -124,7 +123,7 @@ public class NetherPage extends AchievementPage {
         return 0xff0000;
     }
 
-    protected void carveCircle(GuiAchievements gui, GuiAchievements.BGLayer layer, int centerX, int centerY, int radius){
+    protected void carveCircle(AchievementsScreen screen, AchievementsScreen.BGLayer layer, int centerX, int centerY, int radius){
         for (int i = centerX - radius; i <= centerX + radius ; i++) {
             for (int j = centerY - radius; j < centerY + radius; j++) {
                 double diffX = (i + 0.5) - centerX;
diff --git a/src/main/java/net/minecraft/client/gui/achievements/pages/OverworldPage.java b/src/main/java/net/minecraft/client/gui/achievements/pages/OverworldPage.java
index 63e34bf9a..3dd29cc46 100644
--- a/src/main/java/net/minecraft/client/gui/achievements/pages/OverworldPage.java
+++ b/src/main/java/net/minecraft/client/gui/achievements/pages/OverworldPage.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui.achievements.pages;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.achievements.GuiAchievements;
+import net.minecraft.client.gui.achievements.AchievementsScreen;
 import net.minecraft.client.gui.achievements.data.AchievementPage;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
@@ -57,7 +57,7 @@ public class OverworldPage extends AchievementPage {
     protected static final Block[] BASALT_ORES = new Block[]    { Blocks.ORE_COAL_BASALT,   Blocks.ORE_IRON_BASALT,     Blocks.ORE_GOLD_BASALT,     Blocks.ORE_DIAMOND_BASALT,      Blocks.ORE_REDSTONE_BASALT,     Blocks.ORE_LAPIS_BASALT};
 
     @Override
-    public IconCoordinate getBackgroundTile(GuiAchievements guiAchievements, int layer, Random random, int tileX, int tileY) {
+    public IconCoordinate getBackgroundTile(AchievementsScreen screen, int layer, Random random, int tileX, int tileY) {
         random.setSeed(random.nextLong() + key.hashCode()); // makes seed different for each instance of this class :)
         // expect x range from  0  to 45
         // expect y range from -12 to 50
@@ -96,7 +96,7 @@ public class OverworldPage extends AchievementPage {
     }
 
     @Override
-    public void postProcessBackground(GuiAchievements gui, Random random, GuiAchievements.BGLayer layer, int orgX, int orgY) {
+    public void postProcessBackground(AchievementsScreen screen, Random random, AchievementsScreen.BGLayer layer, int orgX, int orgY) {
         random.setSeed(random.nextLong() + key.hashCode()); // makes seed different for each instance of this class :)
         if (layer.id == 0) {
 
@@ -128,7 +128,7 @@ public class OverworldPage extends AchievementPage {
                     } else {
                         layer.put(null, _x - orgX, rY - orgY);
                     }
-                    gui.getLayer(1).put(null, _x - orgX, rY - orgY);
+                    screen.getLayer(1).put(null, _x - orgX, rY - orgY);
                 }
             }
 
@@ -142,7 +142,7 @@ public class OverworldPage extends AchievementPage {
                 }
                 if (cave > 0){
                     lastY = (25 + random.nextInt(4) - random.nextInt(4));
-                    carveCircle(gui, layer, _x - orgX, lastY - orgY, 2 + random.nextInt(3));
+                    carveCircle(screen, layer, _x - orgX, lastY - orgY, 2 + random.nextInt(3));
                 }
                 if (cave == 0 && (-10 <= _x && _x <= 40)) {
                     brickPos = new int[]{_x, lastY};
@@ -155,7 +155,7 @@ public class OverworldPage extends AchievementPage {
                     cave = 5 + random.nextInt(5) - random.nextInt(5);
                 }
                 if (cave > 0){
-                    carveCircle(gui, layer, _x - orgX, (10 + random.nextInt(2) - random.nextInt(2)) - orgY, random.nextInt(3));
+                    carveCircle(screen, layer, _x - orgX, (10 + random.nextInt(2) - random.nextInt(2)) - orgY, random.nextInt(3));
                 }
                 cave--;
             }
@@ -164,7 +164,7 @@ public class OverworldPage extends AchievementPage {
                 brickPos = new int[]{5 + random.nextInt(20) + random.nextInt(20), 15 + random.nextInt(10)};
             }
 
-            placeStructure(gui, dungeonBrick, brickPos[0] - orgX,brickPos[1] - orgY, (struct, cache) -> {
+            placeStructure(screen, dungeonBrick, brickPos[0] - orgX,brickPos[1] - orgY, (struct, cache) -> {
                 if (cache == null) {
                     if (struct == chest || struct == spawner) {
                         return struct;
@@ -173,7 +173,7 @@ public class OverworldPage extends AchievementPage {
                 }
                 return struct;
             });
-            placeStructure(gui, dungeonCobble, -orgX + 5 + random.nextInt(20) + random.nextInt(20),-orgY + 5 + random.nextInt(5), (struct, cache) -> {
+            placeStructure(screen, dungeonCobble, -orgX + 5 + random.nextInt(20) + random.nextInt(20),-orgY + 5 + random.nextInt(5), (struct, cache) -> {
                 if (cache == null) {
                     if (struct == chest || struct == spawner) {
                         return struct;
@@ -184,7 +184,7 @@ public class OverworldPage extends AchievementPage {
             });
         } else if (layer.id == 1) {
             // Remove covered icons
-            IconCoordinate[] foreground = gui.getLayer(0).getData();
+            IconCoordinate[] foreground = screen.getLayer(0).getData();
             IconCoordinate[] background = layer.getData();
             for (int i = 0; i < background.length; i++) {
                 if (foreground[i] != null && foreground[i] != spawner){
@@ -194,7 +194,7 @@ public class OverworldPage extends AchievementPage {
         }
     }
 
-    protected void carveCircle(GuiAchievements gui, GuiAchievements.BGLayer layer, int centerX, int centerY, int radius){
+    protected void carveCircle(AchievementsScreen screen, AchievementsScreen.BGLayer layer, int centerX, int centerY, int radius){
         for (int i = centerX - radius; i <= centerX + radius ; i++) {
             for (int j = centerY - radius; j < centerY + radius; j++) {
                 double diffX = (i + 0.5) - centerX;
@@ -206,12 +206,12 @@ public class OverworldPage extends AchievementPage {
         }
     }
 
-    protected void placeStructure(GuiAchievements gui, PageStructure structure, int tileX, int tileY, @Nullable BiFunction<IconCoordinate, IconCoordinate, IconCoordinate> coordinateProcessor) {
+    protected void placeStructure(AchievementsScreen screen, PageStructure structure, int tileX, int tileY, @Nullable BiFunction<IconCoordinate, IconCoordinate, IconCoordinate> coordinateProcessor) {
         if (coordinateProcessor == null) {
             coordinateProcessor = (i, i2) -> i;
         }
         for (int layer = 0; layer < structure.layers; layer++) {
-            GuiAchievements.BGLayer cache = gui.getLayer(layer);
+            AchievementsScreen.BGLayer cache = screen.getLayer(layer);
             if (cache != null) {
                 for (int _x = 0; _x < structure.width; _x++) {
                     for (int _y = 0; _y < structure.height; _y++) {
diff --git a/src/main/java/net/minecraft/client/gui/GuiContainer.java b/src/main/java/net/minecraft/client/gui/container/AbstractContainerScreen.java
similarity index 81%
rename from src/main/java/net/minecraft/client/gui/GuiContainer.java
rename to src/main/java/net/minecraft/client/gui/container/AbstractContainerScreen.java
index 3efb12233..7bc1cc3bc 100644
--- a/src/main/java/net/minecraft/client/gui/GuiContainer.java
+++ b/src/main/java/net/minecraft/client/gui/container/AbstractContainerScreen.java
@@ -1,14 +1,17 @@
 
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.container;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.guidebook.GuiGuidebook;
+import net.minecraft.client.gui.ItemElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.TooltipElement;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.gui.guidebook.GuidebookSections;
 import net.minecraft.client.gui.guidebook.PageManager;
 import net.minecraft.client.gui.guidebook.SearchableGuidebookSection;
 import net.minecraft.client.gui.guidebook.search.SearchPage;
 import net.minecraft.client.input.controller.ControllerInput;
-import net.minecraft.client.util.helper.GuiItemDragHandler;
+import net.minecraft.client.util.helper.ItemDragHandler;
 import net.minecraft.core.InventoryAction;
 import net.minecraft.core.block.entity.BlastFurnaceBlockEntity;
 import net.minecraft.core.crafting.LookupFuelFurnace;
@@ -34,28 +37,28 @@ import org.lwjgl.opengl.GL11;
 //            ItemStack, FontRenderer, RenderEngine, PlayerController,
 //            GameSettings, KeyBinding
 
-public abstract class GuiContainer extends GuiScreen
+public abstract class AbstractContainerScreen extends Screen
 {
 	public int xSize;
 	public int ySize;
 	public AbstractContainerMenu inventorySlots;
-	GuiTooltip guiTooltip;
-	GuiRenderItem guiRenderItem;
-	public GuiItemDragHandler itemDragHandler;
+	TooltipElement tooltipElement;
+	ItemElement itemElement;
+	public ItemDragHandler itemDragHandler;
 
-	public GuiContainer(final AbstractContainerMenu container)
+	public AbstractContainerScreen(final AbstractContainerMenu container)
 	{
 		Minecraft mc = Minecraft.getMinecraft(this);
 		xSize = 176;
 		ySize = 166;
 		inventorySlots = container;
-		guiTooltip = new GuiTooltip(mc);
-		guiRenderItem = new GuiRenderItem(mc);
-		itemDragHandler = new GuiItemDragHandler(mc, this, guiRenderItem);
+		tooltipElement = new TooltipElement(mc);
+		itemElement = new ItemElement(mc);
+		itemDragHandler = new ItemDragHandler(mc, this, itemElement);
 	}
 
 	@Override
-	public boolean pausesGame()
+	public boolean isPauseScreen()
 	{
 		return false;
 	}
@@ -67,9 +70,9 @@ public abstract class GuiContainer extends GuiScreen
 	}
 
 	@Override
-	public void drawScreen(final int mouseX, final int mouseY, final float partialTick)
+	public void render(final int xm, final int ym, final float partialTick)
 	{
-		drawDefaultBackground();
+		renderBackground();
 		final int centerX = (width - xSize) / 2;
 		final int centerY = (height - ySize) / 2;
 		drawGuiContainerBackgroundLayer(partialTick);
@@ -80,9 +83,9 @@ public abstract class GuiContainer extends GuiScreen
 		for (int i = 0; i < inventorySlots.slots.size(); i++)
 		{
 			final Slot slot1 = inventorySlots.slots.get(i);
-			boolean mouseOver = getIsMouseOverSlot(slot1, mouseX, mouseY);
+			boolean mouseOver = getIsMouseOverSlot(slot1, xm, ym);
 			if(!itemDragHandler.isSlotDragged(slot1)) {
-				guiRenderItem.render(slot1.getItem(), slot1.x, slot1.y, mouseOver, slot1);
+				itemElement.render(slot1.getItem(), slot1.x, slot1.y, mouseOver, slot1);
 			}
 			if (mouseOver)
 			{
@@ -93,7 +96,7 @@ public abstract class GuiContainer extends GuiScreen
 		final Inventory inventoryplayer = mc.thePlayer.inventory;
 		ItemStack grabbedItem = inventoryplayer.getHeldItemStack();
 		if(mc.gameSettings.enableItemDragging.value) {
-			itemDragHandler.drawScreen(mouseX, mouseY, partialTick);
+			itemDragHandler.drawScreen(xm, ym, partialTick);
 
 			ItemStack grabbedItemOverride = itemDragHandler.getHeldItemRenderOverride();
 			if(grabbedItemOverride != null) {
@@ -102,13 +105,13 @@ public abstract class GuiContainer extends GuiScreen
 		}
 		GL11.glPopMatrix();
 
-		super.drawScreen(mouseX, mouseY, partialTick);
+		super.render(xm, ym, partialTick);
 
 		GL11.glPushMatrix();
 		if (grabbedItem != null)
 		{
 			GL11.glTranslatef(centerX, centerY, 100.0F);
-			guiRenderItem.render(grabbedItem, mouseX - centerX - 8, mouseY - centerY - 8);
+			itemElement.render(grabbedItem, xm - centerX - 8, ym - centerY - 8);
 		}
 		GL11.glPopMatrix();
 
@@ -116,10 +119,10 @@ public abstract class GuiContainer extends GuiScreen
 		if (inventoryplayer.getHeldItemStack() == null && slot != null && slot.hasItem())
 		{
 			boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-			String str = guiTooltip.getTooltipText(slot.getItem(), showDescription, slot);
+			String str = tooltipElement.getTooltipText(slot.getItem(), showDescription, slot);
 			if(str.length() > 0)
 			{
-				guiTooltip.render(str, mouseX, mouseY, 8, -8);
+				tooltipElement.render(str, xm, ym, 8, -8);
 			}
 		}
 		GL11.glEnable(GL11.GL_DEPTH_TEST);
@@ -156,119 +159,119 @@ public abstract class GuiContainer extends GuiScreen
 	}
 
 	@Override
-	public void keyTyped(final char c, final int i, int mouseX, int mouseY)
+	public void keyPressed(final char eventCharacter, final int eventKey, int mx, int my)
 	{
-		if (i == Keyboard.KEY_ESCAPE || mc.gameSettings.keyInventory.isKeyboardKey(i) || i == Keyboard.KEY_BACK)
+		if (eventKey == Keyboard.KEY_ESCAPE || mc.gameSettings.keyInventory.isKeyboardKey(eventKey) || eventKey == Keyboard.KEY_BACK)
 		{
 			mc.thePlayer.closeScreen();
 		}
-		int slotId = getSlotId(mouseX, mouseY);
+		int slotId = getSlotId(mx, my);
 		if(slotId >= 0) {
-			if(mc.gameSettings.keyShowRecipe.isKeyboardKey(i)){
+			if(mc.gameSettings.keyShowRecipe.isKeyboardKey(eventKey)){
 				Slot slot = inventorySlots.slots.get(slotId);
 				if(slot.hasItem()){
 					String query = "r:"+slot.getItem().getDisplayName()+"!";
-					onClosed();
+					removed();
 					mc.thePlayer.closeScreen();
 					PageManager.searchQuery = SearchQuery.resolve(query);
 					SearchPage.searchField.setText(query);
-					GuiGuidebook.getPageManager().updatePages();
+					GuidebookScreen.getPageManager().updatePages();
                     if (!((SearchableGuidebookSection) GuidebookSections.CRAFTING).searchPages(PageManager.searchQuery).isEmpty()) {
-						GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+						GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
                     } else if (!((SearchableGuidebookSection) GuidebookSections.FURNACE).searchPages(PageManager.searchQuery).isEmpty()) {
-						GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.FURNACE), true);
+						GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.FURNACE), true);
 					} else if (!((SearchableGuidebookSection) GuidebookSections.BLAST_FURNACE).searchPages(PageManager.searchQuery).isEmpty()) {
-						GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.BLAST_FURNACE), true);
+						GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.BLAST_FURNACE), true);
 					} else if (!((SearchableGuidebookSection) GuidebookSections.TROMMEL).searchPages(PageManager.searchQuery).isEmpty()) {
-						GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.TROMMEL), true);
+						GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.TROMMEL), true);
 					}
-					mc.thePlayer.displayGUIGuidebook();
+					mc.thePlayer.displayGuidebookScreen();
 				}
 			}
-			if(mc.gameSettings.keyShowUsage.isKeyboardKey(i)){
+			if(mc.gameSettings.keyShowUsage.isKeyboardKey(eventKey)){
 				Slot slot = inventorySlots.slots.get(slotId);
 				if(slot.hasItem()) {
 					String query = "u:" + slot.getItem().getDisplayName() + "!";
-					onClosed();
+					removed();
 					mc.thePlayer.closeScreen();
 					PageManager.searchQuery = SearchQuery.resolve(query);
 					SearchPage.searchField.setText(query);
-					GuiGuidebook.getPageManager().updatePages();
+					GuidebookScreen.getPageManager().updatePages();
 					if (!((SearchableGuidebookSection) GuidebookSections.CRAFTING).searchPages(PageManager.searchQuery).isEmpty()) {
-						GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+						GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
 					} else if (!((SearchableGuidebookSection) GuidebookSections.FURNACE).searchPages(PageManager.searchQuery).isEmpty()) {
-						GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.FURNACE), true);
+						GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.FURNACE), true);
 					} else if (!((SearchableGuidebookSection) GuidebookSections.BLAST_FURNACE).searchPages(PageManager.searchQuery).isEmpty()) {
-						GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.BLAST_FURNACE), true);
+						GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.BLAST_FURNACE), true);
 					} else if (!((SearchableGuidebookSection) GuidebookSections.TROMMEL).searchPages(PageManager.searchQuery).isEmpty()) {
-						GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.TROMMEL), true);
+						GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.TROMMEL), true);
 					}
-					mc.thePlayer.displayGUIGuidebook();
+					mc.thePlayer.displayGuidebookScreen();
 				}
 			}
-			if(mc.gameSettings.keyDrop.isKeyboardKey(i)) {
+			if(mc.gameSettings.keyDrop.isKeyboardKey(eventKey)) {
 				boolean ctrl = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL);
 				int amount = 1;
 				if(ctrl) amount = 64;
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.DROP, new int[] {slotId, amount}, mc.thePlayer);
 			}
 			// Horrifying
-			if (mc.gameSettings.keyHotBarSlot1.isKeyboardKey(i)){
+			if (mc.gameSettings.keyHotBarSlot1.isKeyboardKey(eventKey)){
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[] {slotId, 1}, mc.thePlayer);
 			}
-			if (mc.gameSettings.keyHotBarSlot2.isKeyboardKey(i)){
+			if (mc.gameSettings.keyHotBarSlot2.isKeyboardKey(eventKey)){
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[] {slotId, 2}, mc.thePlayer);
 			}
-			if (mc.gameSettings.keyHotBarSlot3.isKeyboardKey(i)){
+			if (mc.gameSettings.keyHotBarSlot3.isKeyboardKey(eventKey)){
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[] {slotId, 3}, mc.thePlayer);
 			}
-			if (mc.gameSettings.keyHotBarSlot4.isKeyboardKey(i)){
+			if (mc.gameSettings.keyHotBarSlot4.isKeyboardKey(eventKey)){
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[] {slotId, 4}, mc.thePlayer);
 			}
-			if (mc.gameSettings.keyHotBarSlot5.isKeyboardKey(i)){
+			if (mc.gameSettings.keyHotBarSlot5.isKeyboardKey(eventKey)){
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[] {slotId, 5}, mc.thePlayer);
 			}
-			if (mc.gameSettings.keyHotBarSlot6.isKeyboardKey(i)){
+			if (mc.gameSettings.keyHotBarSlot6.isKeyboardKey(eventKey)){
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[] {slotId, 6}, mc.thePlayer);
 			}
-			if (mc.gameSettings.keyHotBarSlot7.isKeyboardKey(i)){
+			if (mc.gameSettings.keyHotBarSlot7.isKeyboardKey(eventKey)){
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[] {slotId, 7}, mc.thePlayer);
 			}
-			if (mc.gameSettings.keyHotBarSlot8.isKeyboardKey(i)){
+			if (mc.gameSettings.keyHotBarSlot8.isKeyboardKey(eventKey)){
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[] {slotId, 8}, mc.thePlayer);
 			}
-			if (mc.gameSettings.keyHotBarSlot9.isKeyboardKey(i)){
+			if (mc.gameSettings.keyHotBarSlot9.isKeyboardKey(eventKey)){
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[] {slotId, 9}, mc.thePlayer);
 			}
 
-			if(mc.gameSettings.keySortInventory.isKeyboardKey(i)) {
+			if(mc.gameSettings.keySortInventory.isKeyboardKey(eventKey)) {
 				mc.playerController.handleInventoryMouseClick(inventorySlots.containerId, InventoryAction.SORT, new int[] {slotId}, mc.thePlayer);
 			}
 		}
 	}
 
 	@Override
-	public void mouseClicked(final int mouseX, final int mouseY, int mouseButton)
+	public void mouseClicked(final int mx, final int my, int buttonNum)
 	{
-		super.mouseClicked(mouseX, mouseY, mouseButton);
+		super.mouseClicked(mx, my, buttonNum);
 		if(mc.gameSettings.enableItemDragging.value) {
-			itemDragHandler.mouseEvent(mouseX, mouseY, mouseButton, true);
+			itemDragHandler.mouseEvent(mx, my, buttonNum, true);
 			return;
 		}
-		if (mouseButton == 0 || mouseButton == 1 || mouseButton == 2 || mouseButton == 10) //button == 10 = controller shift click
+		if (buttonNum == 0 || buttonNum == 1 || buttonNum == 2 || buttonNum == 10) //button == 10 = controller shift click
 		{
-			clickInventory(mouseX, mouseY, mouseButton);
+			clickInventory(mx, my, buttonNum);
 		}
 	}
 	
 	@Override
-	public void mouseMovedOrButtonReleased(int mouseX, int mouseY, int mouseButton) {
-		if(mouseButton >= 0) {
+	public void mouseReleased(int mx, int my, int buttonNum) {
+		if(buttonNum >= 0) {
 			if(mc.gameSettings.enableItemDragging.value) {
-				itemDragHandler.mouseEvent(mouseX, mouseY, mouseButton, false);
+				itemDragHandler.mouseEvent(mx, my, buttonNum, false);
 			}
 		}
-		super.mouseMovedOrButtonReleased(mouseX, mouseY, mouseButton);
+		super.mouseReleased(mx, my, buttonNum);
 	}
 	
 	/**
@@ -598,7 +601,7 @@ public abstract class GuiContainer extends GuiScreen
 	}
 
 	@Override
-	public void onClosed()
+	public void removed()
 	{
 		if (mc.thePlayer == null)
 		{
diff --git a/src/main/java/net/minecraft/client/gui/GuiChest.java b/src/main/java/net/minecraft/client/gui/container/ContainerScreen.java
similarity index 75%
rename from src/main/java/net/minecraft/client/gui/GuiChest.java
rename to src/main/java/net/minecraft/client/gui/container/ContainerScreen.java
index f77122fad..3b94caaa3 100644
--- a/src/main/java/net/minecraft/client/gui/GuiChest.java
+++ b/src/main/java/net/minecraft/client/gui/container/ContainerScreen.java
@@ -1,4 +1,4 @@
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.container;
 
 import net.minecraft.core.player.inventory.menu.ContainerMenu;
 import net.minecraft.core.player.inventory.container.Container;
@@ -8,16 +8,16 @@ import org.lwjgl.opengl.GL11;
 //            GuiContainer, ContainerChest, IInventory, FontRenderer, 
 //            RenderEngine
 
-public class GuiChest extends GuiContainer
+public class ContainerScreen extends AbstractContainerScreen
 {
 
-    public GuiChest(Container iinventory, Container iinventory1)
+    public ContainerScreen(Container iinventory, Container iinventory1)
     {
         super(new ContainerMenu(iinventory, iinventory1));
         inventoryRows = 0;
         upperChestInventory = iinventory;
         lowerChestInventory = iinventory1;
-        allowIngameInput = false;
+        passEvents = false;
         char c = '\336';
         int i = c - 108;
         inventoryRows = iinventory1.getContainerSize() / 9;
@@ -27,15 +27,15 @@ public class GuiChest extends GuiContainer
     @Override
 	protected void drawGuiContainerForegroundLayer()
     {
-        fontRenderer.drawString(lowerChestInventory.getName(), 8, 6, 0x404040);
-        fontRenderer.drawString(upperChestInventory.getName(), 8, (ySize - 96) + 2, 0x404040);
+        font.drawString(lowerChestInventory.getName(), 8, 6, 0x404040);
+        font.drawString(upperChestInventory.getName(), 8, (ySize - 96) + 2, 0x404040);
     }
 
     @Override
 	protected void drawGuiContainerBackgroundLayer(float f)
     {
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/container.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/container.png").bind();
         int x = (width - xSize) / 2;
         int y = (height - ySize) / 2;
         
diff --git a/src/main/java/net/minecraft/client/gui/GuiCrafting.java b/src/main/java/net/minecraft/client/gui/container/CraftingScreen.java
similarity index 63%
rename from src/main/java/net/minecraft/client/gui/GuiCrafting.java
rename to src/main/java/net/minecraft/client/gui/container/CraftingScreen.java
index eafc14814..520fe1d65 100644
--- a/src/main/java/net/minecraft/client/gui/GuiCrafting.java
+++ b/src/main/java/net/minecraft/client/gui/container/CraftingScreen.java
@@ -1,4 +1,4 @@
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.container;
 
 import net.minecraft.client.input.controller.ControllerInput;
 import net.minecraft.core.lang.I18n;
@@ -11,39 +11,39 @@ import org.lwjgl.opengl.GL11;
 //            GuiContainer, ContainerWorkbench, Container, FontRenderer, 
 //            RenderEngine, InventoryPlayer, World
 
-public class GuiCrafting extends GuiContainer
+public class CraftingScreen extends AbstractContainerScreen
 {
 
-    public GuiCrafting(Inventory inventoryplayer, World world, int i, int j, int k)
+    public CraftingScreen(Inventory inventoryplayer, World world, int i, int j, int k)
     {
         super(new CraftingMenu(inventoryplayer, world, i, j, k));
     }
 
     @Override
-	public void onClosed()
+	public void removed()
     {
-        super.onClosed();
+        super.removed();
         inventorySlots.onCraftGuiClosed(mc.thePlayer);
     }
 
     @Override
 	protected void drawGuiContainerForegroundLayer()
     {
-        fontRenderer.drawString(I18n.getInstance().translateKey("gui.crafting.label.crafting"), 28, 6, 0x404040);
-        fontRenderer.drawString(I18n.getInstance().translateKey("gui.crafting.label.inventory"), 8, (ySize - 96) + 2, 0x404040);
+        font.drawString(I18n.getInstance().translateKey("gui.crafting.label.crafting"), 28, 6, 0x404040);
+        font.drawString(I18n.getInstance().translateKey("gui.crafting.label.inventory"), 8, (ySize - 96) + 2, 0x404040);
     }
 
     @Override
 	protected void drawGuiContainerBackgroundLayer(float f)
     {
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/crafting.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/crafting.png").bind();
         int j = (width - xSize) / 2;
         int k = (height - ySize) / 2;
         drawTexturedModalRect(j, k, 0, 0, xSize, ySize);
     }
     @Override
     public void guiSpecificControllerInput(ControllerInput controller){
-        controller.craftingGuiHandler.handleCrafting(this);
+        controller.inventoryHandler.handleCrafting(this);
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/GuiDispenser.java b/src/main/java/net/minecraft/client/gui/container/DispenserScreen.java
similarity index 61%
rename from src/main/java/net/minecraft/client/gui/GuiDispenser.java
rename to src/main/java/net/minecraft/client/gui/container/DispenserScreen.java
index 2bf5a9913..75f11ba4a 100644
--- a/src/main/java/net/minecraft/client/gui/GuiDispenser.java
+++ b/src/main/java/net/minecraft/client/gui/container/DispenserScreen.java
@@ -1,4 +1,4 @@
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.container;
 
 import net.minecraft.core.block.entity.DispenserBlockEntity;
 import net.minecraft.core.lang.I18n;
@@ -10,10 +10,10 @@ import org.lwjgl.opengl.GL11;
 //            GuiContainer, ContainerDispenser, FontRenderer, RenderEngine, 
 //            InventoryPlayer, DispenserBlockEntity
 
-public class GuiDispenser extends GuiContainer
+public class DispenserScreen extends AbstractContainerScreen
 {
 
-    public GuiDispenser(Inventory inventoryplayer, DispenserBlockEntity tileentitydispenser)
+    public DispenserScreen(Inventory inventoryplayer, DispenserBlockEntity tileentitydispenser)
     {
         super(new TrapMenu(inventoryplayer, tileentitydispenser));
     }
@@ -21,15 +21,15 @@ public class GuiDispenser extends GuiContainer
     @Override
 	protected void drawGuiContainerForegroundLayer()
     {
-        fontRenderer.drawString(I18n.getInstance().translateKey("gui.dispenser.label.dispenser"), 60, 6, 0x404040);
-        fontRenderer.drawString(I18n.getInstance().translateKey("gui.dispenser.label.inventory"), 8, (ySize - 96) + 2, 0x404040);
+        font.drawString(I18n.getInstance().translateKey("gui.dispenser.label.dispenser"), 60, 6, 0x404040);
+        font.drawString(I18n.getInstance().translateKey("gui.dispenser.label.inventory"), 8, (ySize - 96) + 2, 0x404040);
     }
 
     @Override
 	protected void drawGuiContainerBackgroundLayer(float f)
     {
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/dispenser.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/dispenser.png").bind();
         int j = (width - xSize) / 2;
         int k = (height - ySize) / 2;
         drawTexturedModalRect(j, k, 0, 0, xSize, ySize);
diff --git a/src/main/java/net/minecraft/client/gui/GuiEditFlag.java b/src/main/java/net/minecraft/client/gui/container/FlagEditorScreen.java
similarity index 70%
rename from src/main/java/net/minecraft/client/gui/GuiEditFlag.java
rename to src/main/java/net/minecraft/client/gui/container/FlagEditorScreen.java
index 1cd9941da..46346e755 100644
--- a/src/main/java/net/minecraft/client/gui/GuiEditFlag.java
+++ b/src/main/java/net/minecraft/client/gui/container/FlagEditorScreen.java
@@ -1,5 +1,9 @@
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.container;
 
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.ClickableLabelElement;
+import net.minecraft.client.gui.DrawableSurfaceElement;
+import net.minecraft.client.gui.TexturedButtonElement;
 import net.minecraft.core.block.entity.FlagBlockEntity;
 import net.minecraft.core.entity.player.Player;
 import org.lwjgl.input.Keyboard;
@@ -16,8 +20,8 @@ import net.minecraft.core.net.packet.CustomPayloadPacket;
 import net.minecraft.core.player.inventory.menu.FlagMenu;
 import net.minecraft.core.util.helper.MathHelper;
 
-public class GuiEditFlag
-    extends GuiContainer
+public class FlagEditorScreen
+    extends AbstractContainerScreen
     implements IDrawableSurface<Byte>
 {
     private final FlagBlockEntity tileEntity;
@@ -33,28 +37,28 @@ public class GuiEditFlag
     private int canvasX = 0;
     private int canvasY = 0;
     private int selectedColor = 0;
-    private GuiClickableLabel[] colorLabels;
+    private ClickableLabelElement[] colorLabels;
 
     private final DrawableEditor<Byte> flagSurfaceEditor;
     private final DrawableEditor<Byte> drawOverlaySurfaceEditor;
 
-    private GuiTexturedButton[] toolBtns;
+    private TexturedButtonElement[] toolBtns;
     private int activeTool = 0;
 
-    GuiSurface flagSurface;
-    GuiSurface drawOverlaySurface;
+    DrawableSurfaceElement flagSurface;
+    DrawableSurfaceElement drawOverlaySurface;
     
-    public GuiEditFlag(Player player, FlagBlockEntity flagTileEntity)
+    public FlagEditorScreen(Player player, FlagBlockEntity flagTileEntity)
     {
         super(new FlagMenu(player.inventory, flagTileEntity));
         this.tileEntity = flagTileEntity;
         xSize = 176;
         ySize = 195;
-        flagTileEntity.owner = player.username;
+        flagTileEntity.owner = player.uuid;
 
-        flagSurface = new GuiSurface(CANVAS_WIDTH, CANVAS_HEIGHT, CANVAS_SCALE, flagTileEntity.flagColors);
+        flagSurface = new DrawableSurfaceElement(CANVAS_WIDTH, CANVAS_HEIGHT, CANVAS_SCALE, flagTileEntity.flagColors);
         flagSurfaceEditor = new DrawableEditor<>(flagSurface);
-        drawOverlaySurface = new GuiSurface(CANVAS_WIDTH, CANVAS_HEIGHT, CANVAS_SCALE);
+        drawOverlaySurface = new DrawableSurfaceElement(CANVAS_WIDTH, CANVAS_HEIGHT, CANVAS_SCALE);
         drawOverlaySurfaceEditor = new DrawableEditor<>(drawOverlaySurface);
     }
 
@@ -62,30 +66,30 @@ public class GuiEditFlag
     public void init()
     {
         super.init();
-        controlList.clear();
+        buttons.clear();
 
         canvasX = (width - xSize) / 2 + 27;
         canvasY = (height - ySize) / 2 + 8;
 
-        toolBtns = new GuiTexturedButton[7];
+        toolBtns = new TexturedButtonElement[7];
 
         for (int i = 0; i < 7; i++)
         {
-            toolBtns[i] = new GuiTexturedButton(i, "/assets/minecraft/textures/gui/container/flag_editor.png", (width - xSize) / 2 + 12 + 22 * i, (height - ySize) / 2 + 76, 20 * i, 195, 20, 20);
+            toolBtns[i] = new TexturedButtonElement(i, "/assets/minecraft/textures/gui/container/flag_editor.png", (width - xSize) / 2 + 12 + 22 * i, (height - ySize) / 2 + 76, 20 * i, 195, 20, 20);
             if (i == activeTool) toolBtns[i].enabled = false;
-            controlList.add(toolBtns[i]);
+            buttons.add(toolBtns[i]);
         }
 
-        colorLabels = new GuiClickableLabel[3];
+        colorLabels = new ClickableLabelElement[3];
 
         for (int i = 0; i < 3; i++)
         {
-            colorLabels[i] = new GuiClickableLabel(100 + i, (width - xSize) / 2 + 150, (height - ySize) / 2 + 12 + (i * 22), String.valueOf(i + 1), 0xFFFFFFFF, 0x00000000);
+            colorLabels[i] = new ClickableLabelElement(100 + i, (width - xSize) / 2 + 150, (height - ySize) / 2 + 12 + (i * 22), String.valueOf(i + 1), 0xFFFFFFFF, 0x00000000);
             if (i != selectedColor) {
-                colorLabels[i].textColor = 0xFF3F3F3F;
-                colorLabels[i].shadow = false;
+                colorLabels[i].setTextColor(0xFF3F3F3F);
+                colorLabels[i].setShadow(false);
             }
-            controlList.add(colorLabels[i]);
+            buttons.add(colorLabels[i]);
         }
     }
 
@@ -115,9 +119,9 @@ public class GuiEditFlag
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton)
+    public void mouseClicked(int mx, int my, int buttonNum)
     {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
+        super.mouseClicked(mx, my, buttonNum);
         
         // Do not draw with no color selected
         if(tileEntity.getItem(36 + selectedColor) == null) {
@@ -128,15 +132,15 @@ public class GuiEditFlag
         {
             if (!isDrawing)
             {
-                int xInCanvas = (mouseX - canvasX) / CANVAS_SCALE;
-                int yInCanvas = (mouseY - canvasY) / CANVAS_SCALE;
+                int xInCanvas = (mx - canvasX) / CANVAS_SCALE;
+                int yInCanvas = (my - canvasY) / CANVAS_SCALE;
                 if (xInCanvas >= 0 && xInCanvas < CANVAS_WIDTH
                         && yInCanvas >= 0 && yInCanvas < CANVAS_HEIGHT)
                 {
                     isDrawing = true;
                     xLast = xInCanvas;
                     yLast = yInCanvas;
-                    this.mouseButton = mouseButton;
+                    this.mouseButton = buttonNum;
 
                     byte color = 0;
                     if (this.mouseButton == 0)
@@ -151,13 +155,13 @@ public class GuiEditFlag
         {
             if (!isDrawing)
             {
-                int xInCanvas = (mouseX - canvasX) / CANVAS_SCALE;
-                int yInCanvas = (mouseY - canvasY) / CANVAS_SCALE;
+                int xInCanvas = (mx - canvasX) / CANVAS_SCALE;
+                int yInCanvas = (my - canvasY) / CANVAS_SCALE;
                 if (xInCanvas >= 0 && xInCanvas < CANVAS_WIDTH
                         && yInCanvas >= 0 && yInCanvas < CANVAS_HEIGHT)
                 {
                     isDrawing = true;
-                    this.mouseButton = mouseButton;
+                    this.mouseButton = buttonNum;
 
                     byte color = 0;
                     if (this.mouseButton == 0)
@@ -172,13 +176,13 @@ public class GuiEditFlag
         {
             if (!isDrawing)
             {
-                int xInCanvas = (mouseX - canvasX) / CANVAS_SCALE;
-                int yInCanvas = (mouseY - canvasY) / CANVAS_SCALE;
+                int xInCanvas = (mx - canvasX) / CANVAS_SCALE;
+                int yInCanvas = (my - canvasY) / CANVAS_SCALE;
                 if (xInCanvas >= 0 && xInCanvas < CANVAS_WIDTH
                         && yInCanvas >= 0 && yInCanvas < CANVAS_HEIGHT)
                 {
                     isDrawing = true;
-                    this.mouseButton = mouseButton;
+                    this.mouseButton = buttonNum;
 
                     xLast = xInCanvas;
                     yLast = yInCanvas;
@@ -188,9 +192,9 @@ public class GuiEditFlag
     }
 
     @Override
-    protected void buttonPressed(GuiButton button)
+    protected void buttonClicked(ButtonElement button)
     {
-        super.buttonPressed(button);
+        super.buttonClicked(button);
         if (button.id >= 0 && button.id < 7)
         {
             toolBtns[activeTool].enabled = true;
@@ -199,22 +203,22 @@ public class GuiEditFlag
         }
         if (button.id >= 100 && button.id < 103)
         {
-            colorLabels[selectedColor].textColor = 0xFF404040;
-            colorLabels[selectedColor].shadow = false;
+            colorLabels[selectedColor].setTextColor(0xFF404040);
+            colorLabels[selectedColor].setShadow(false);
             selectedColor = button.id - 100;
-            colorLabels[selectedColor].textColor = 0xFFFFFFFF;
-            colorLabels[selectedColor].shadow = true;
+            colorLabels[selectedColor].setTextColor(0xFFFFFFF);
+            colorLabels[selectedColor].setShadow(true);
         }
     }
 
     @Override
-    public void mouseMovedOrButtonReleased(final int mouseX, final int mouseY, final int mouseButton)
+    public void mouseReleased(final int mx, final int my, final int buttonNum)
     {
-        super.mouseMovedOrButtonReleased(mouseX, mouseY, mouseButton);
+        super.mouseReleased(mx, my, buttonNum);
 
         if (activeTool >= 0 && activeTool < 3) // Pen
         {
-            if (isDrawing && mouseButton != -1)
+            if (isDrawing && buttonNum != -1)
             {
                 isDrawing = false;
                 this.mouseButton = -1;
@@ -222,8 +226,8 @@ public class GuiEditFlag
             else if (isDrawing)
             {
                 // divide by pixel scale
-                int xInCanvas = (mouseX - canvasX) / CANVAS_SCALE;
-                int yInCanvas = (mouseY - canvasY) / CANVAS_SCALE;
+                int xInCanvas = (mx - canvasX) / CANVAS_SCALE;
+                int yInCanvas = (my - canvasY) / CANVAS_SCALE;
 
                 byte color = 0;
                 if (this.mouseButton == 0)
@@ -246,7 +250,7 @@ public class GuiEditFlag
         }
         else if (activeTool == 3) // Flood fill
         {
-            if (isDrawing && mouseButton != -1)
+            if (isDrawing && buttonNum != -1)
             {
                 isDrawing = false;
                 this.mouseButton = -1;
@@ -254,13 +258,13 @@ public class GuiEditFlag
         }
         else if (activeTool == 4) // Rectangle
         {
-            if (isDrawing && mouseButton != -1)
+            if (isDrawing && buttonNum != -1)
             {
                 isDrawing = false;
 
                 // divide by pixel scale
-                int xInCanvas = (mouseX - canvasX) / CANVAS_SCALE;
-                int yInCanvas = (mouseY - canvasY) / CANVAS_SCALE;
+                int xInCanvas = (mx - canvasX) / CANVAS_SCALE;
+                int yInCanvas = (my - canvasY) / CANVAS_SCALE;
 
                 byte color = 0;
                 if (this.mouseButton == 0)
@@ -274,13 +278,13 @@ public class GuiEditFlag
         }
         else if (activeTool == 5) // Ellipse
         {
-            if (isDrawing && mouseButton != -1)
+            if (isDrawing && buttonNum != -1)
             {
                 isDrawing = false;
 
                 // divide by pixel scale
-                int xInCanvas = (mouseX - canvasX) / CANVAS_SCALE;
-                int yInCanvas = (mouseY - canvasY) / CANVAS_SCALE;
+                int xInCanvas = (mx - canvasX) / CANVAS_SCALE;
+                int yInCanvas = (my - canvasY) / CANVAS_SCALE;
 
                 byte color = 0;
                 if (this.mouseButton == 0)
@@ -294,13 +298,13 @@ public class GuiEditFlag
         }
         else if (activeTool == 6) // Line
         {
-            if (isDrawing && mouseButton != -1)
+            if (isDrawing && buttonNum != -1)
             {
                 isDrawing = false;
 
                 // divide by pixel scale
-                int xInCanvas = (mouseX - canvasX) / CANVAS_SCALE;
-                int yInCanvas = (mouseY - canvasY) / CANVAS_SCALE;
+                int xInCanvas = (mx - canvasX) / CANVAS_SCALE;
+                int yInCanvas = (my - canvasY) / CANVAS_SCALE;
 
                 byte color = 0;
                 if (this.mouseButton == 0)
@@ -318,7 +322,7 @@ public class GuiEditFlag
     protected void drawGuiContainerBackgroundLayer(float f) 
     {
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/flag_editor.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/flag_editor.png").bind();
         int j = (width - xSize) / 2;
         int k = (height - ySize) / 2;
         drawTexturedModalRect(j, k, 0, 0, xSize, ySize);
@@ -326,13 +330,13 @@ public class GuiEditFlag
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick)
+    public void render(int xm, int ym, float partialTick)
     {
-        super.drawScreen(mouseX, mouseY, partialTick);
+        super.render(xm, ym, partialTick);
         drawOverlaySurface.clear();
 
-        int xInCanvas = (mouseX - canvasX) / CANVAS_SCALE;
-        int yInCanvas = (mouseY - canvasY) / CANVAS_SCALE;
+        int xInCanvas = (xm - canvasX) / CANVAS_SCALE;
+        int yInCanvas = (ym - canvasY) / CANVAS_SCALE;
         byte color = (byte) (selectedColor + 1);
         if (this.mouseButton == 1) color = 4;
 
@@ -383,13 +387,13 @@ public class GuiEditFlag
 
     @Override
     protected void drawGuiContainerForegroundLayer() {
-        fontRenderer.drawString(I18n.getInstance().translateKey("gui.edit_flag.label.inventory"), 8, (ySize - 96) + 2, 0xFF404040);
+        font.drawString(I18n.getInstance().translateKey("gui.edit_flag.label.inventory"), 8, (ySize - 96) + 2, 0xFF404040);
     }
 
     @Override
-    public void keyTyped(char c, int keyCode, int mouseX, int mouseY) 
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
-        if (keyCode == Keyboard.KEY_ESCAPE || mc.gameSettings.keyInventory.isKeyboardKey(keyCode) || keyCode == Keyboard.KEY_BACK)
+        if (eventKey == Keyboard.KEY_ESCAPE || mc.gameSettings.keyInventory.isKeyboardKey(eventKey) || eventKey == Keyboard.KEY_BACK)
         {
     		// Flag packet needs to be sent before the close screen packet is sent!
     		if(mc.theWorld.isClientSide) {
@@ -398,15 +402,15 @@ public class GuiEditFlag
             mc.thePlayer.closeScreen();
         }
 
-        if (keyCode == Keyboard.KEY_1 || keyCode == Keyboard.KEY_2 || keyCode == Keyboard.KEY_3) {
-            colorLabels[selectedColor].textColor = 0xFF404040;
-            colorLabels[selectedColor].shadow = false;
-            selectedColor = keyCode - Keyboard.KEY_1;
-            colorLabels[selectedColor].textColor = 0xFFFFFFFF;
-            colorLabels[selectedColor].shadow = true;
+        if (eventKey == Keyboard.KEY_1 || eventKey == Keyboard.KEY_2 || eventKey == Keyboard.KEY_3) {
+            colorLabels[selectedColor].setTextColor(0xFF404040);
+            colorLabels[selectedColor].setShadow(false);
+            selectedColor = eventKey - Keyboard.KEY_1;
+            colorLabels[selectedColor].setTextColor(0xFFFFFFFF);
+            colorLabels[selectedColor].setShadow(true);
 
         }
-        super.keyTyped(c, keyCode, mouseX, mouseY);
+        super.keyPressed(eventCharacter, eventKey, mx, my);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/GuiFurnace.java b/src/main/java/net/minecraft/client/gui/container/FurnaceScreen.java
similarity index 73%
rename from src/main/java/net/minecraft/client/gui/GuiFurnace.java
rename to src/main/java/net/minecraft/client/gui/container/FurnaceScreen.java
index 325ea10d7..ba4e905d4 100644
--- a/src/main/java/net/minecraft/client/gui/GuiFurnace.java
+++ b/src/main/java/net/minecraft/client/gui/container/FurnaceScreen.java
@@ -1,4 +1,4 @@
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.container;
 
 import net.minecraft.client.input.controller.ControllerInput;
 import net.minecraft.core.block.entity.BlastFurnaceBlockEntity;
@@ -8,10 +8,10 @@ import net.minecraft.core.player.inventory.menu.FurnaceMenu;
 import net.minecraft.core.player.inventory.container.Inventory;
 import org.lwjgl.opengl.GL11;
 
-public class GuiFurnace extends GuiContainer
+public class FurnaceScreen extends AbstractContainerScreen
 {
 
-    public GuiFurnace(Inventory inventoryplayer, FurnaceBlockEntity tileentityfurnace)
+    public FurnaceScreen(Inventory inventoryplayer, FurnaceBlockEntity tileentityfurnace)
     {
         super(new FurnaceMenu(inventoryplayer, tileentityfurnace));
         furnaceInventory = tileentityfurnace;
@@ -22,20 +22,20 @@ public class GuiFurnace extends GuiContainer
     {
         I18n i18n = I18n.getInstance();
         if(furnaceInventory instanceof BlastFurnaceBlockEntity) {
-            fontRenderer.drawString(i18n.translateKey("gui.furnace.blast.label.blast_furnace"), 60, 6, 0x404040);
+            font.drawString(i18n.translateKey("gui.furnace.blast.label.blast_furnace"), 60, 6, 0x404040);
         } else {
-            fontRenderer.drawString(i18n.translateKey("gui.furnace.label.furnace"), 60, 6, 0x404040);
+            font.drawString(i18n.translateKey("gui.furnace.label.furnace"), 60, 6, 0x404040);
         }
-        fontRenderer.drawString(i18n.translateKey("gui.furnace.label.inventory"), 8, (ySize - 96) + 2, 0x404040);
+        font.drawString(i18n.translateKey("gui.furnace.label.inventory"), 8, (ySize - 96) + 2, 0x404040);
     }
 
     @Override
 	protected void drawGuiContainerBackgroundLayer(float f)
     {
         if(furnaceInventory instanceof BlastFurnaceBlockEntity) {
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/blastfurnace.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/blastfurnace.png").bind();
         } else {
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/furnace.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/furnace.png").bind();
         }
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         int x = (width - xSize) / 2;
@@ -59,7 +59,7 @@ public class GuiFurnace extends GuiContainer
     }
     @Override
     public void guiSpecificControllerInput(ControllerInput controller){
-        controller.craftingGuiHandler.handleFurnace(this);
+        controller.inventoryHandler.handleFurnace(this);
     }
 
     private final FurnaceBlockEntity furnaceInventory;
diff --git a/src/main/java/net/minecraft/client/gui/GuiInventory.java b/src/main/java/net/minecraft/client/gui/container/InventoryScreen.java
similarity index 78%
rename from src/main/java/net/minecraft/client/gui/GuiInventory.java
rename to src/main/java/net/minecraft/client/gui/container/InventoryScreen.java
index 17c899895..656915880 100644
--- a/src/main/java/net/minecraft/client/gui/GuiInventory.java
+++ b/src/main/java/net/minecraft/client/gui/container/InventoryScreen.java
@@ -1,11 +1,14 @@
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.container;
 
 import static org.lwjgl.opengl.GL11.*;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import net.minecraft.client.gui.options.GuiOptionButton;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.GuiElement;
+import net.minecraft.client.gui.ListLayout;
+import net.minecraft.client.gui.options.OverlayButtonElement;
 import net.minecraft.client.input.controller.ControllerInput;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.achievement.Achievements;
@@ -30,10 +33,10 @@ import org.lwjgl.opengl.GL12;
 //            RenderEngine, LocalPlayer, RenderHelper, RenderManager,
 //            GuiButton, GuiAchievements, GuiStats
 
-public class GuiInventory extends GuiContainer
+public class InventoryScreen extends AbstractContainerScreen
 {
 	
-	private GuiButton armorButton;
+	private ButtonElement armorButton;
     protected int armourValuesFloat = 130;
     protected int armourButtonFloatX = 20;
 	protected ListLayout overlayButtonsLayout = new ListLayout(this).setAlign(0.5, 0.5).setVertical(false).setElementSize(11, 11).setOffset(-(xSize / 2), -(ySize / 2) - 10).setMargin(1);
@@ -41,23 +44,23 @@ public class GuiInventory extends GuiContainer
 	
 	private DamageType hoveredDamageType;
 
-    public GuiInventory(Player player)
+    public InventoryScreen(Player player)
     {
         super(player.inventorySlots);
-        allowIngameInput = true;
+        passEvents = true;
         player.addStat(Achievements.OPEN_INVENTORY, 1);
     }
 
     @Override
 	public void init()
     {
-        controlList.clear();
+        buttons.clear();
 
 
-        armorButton = new GuiButton(100, width / 2 - armourButtonFloatX, height / 2 - 74, 9, 9, "");
+        armorButton = new ButtonElement(100, width / 2 - armourButtonFloatX, height / 2 - 74, 9, 9, "");
         armorButton.visible = false;
         checkForArmor();
-        controlList.add(armorButton);
+        buttons.add(armorButton);
 
 		updateOverlayButtons();
     }
@@ -112,57 +115,57 @@ public class GuiInventory extends GuiContainer
         overlayButtonsLayout.elements.clear();
         
         if(compass) {
-        	overlayButtonsLayout.addElement(new GuiOptionButton<>(settings, settings.overlayShowCoords));
+        	overlayButtonsLayout.addElement(new OverlayButtonElement<>(settings, settings.overlayShowCoords));
         	uvs.add(0);
-        	overlayButtonsLayout.addElement(new GuiOptionButton<>(settings, settings.overlayShowDirection));
+        	overlayButtonsLayout.addElement(new OverlayButtonElement<>(settings, settings.overlayShowDirection));
         	uvs.add(1);
         }
         if(clock) {
-        	overlayButtonsLayout.addElement(new GuiOptionButton<>(settings, settings.overlayShowTime));
+        	overlayButtonsLayout.addElement(new OverlayButtonElement<>(settings, settings.overlayShowTime));
         	uvs.add(2);
         }
         if(rotaryCalendar) {
-        	overlayButtonsLayout.addElement(new GuiOptionButton<>(settings, settings.overlayShowSeason));
+        	overlayButtonsLayout.addElement(new OverlayButtonElement<>(settings, settings.overlayShowSeason));
         	uvs.add(3);
-        	overlayButtonsLayout.addElement(new GuiOptionButton<>(settings, settings.overlayShowWeather));
+        	overlayButtonsLayout.addElement(new OverlayButtonElement<>(settings, settings.overlayShowWeather));
         	uvs.add(4);
-        	overlayButtonsLayout.addElement(new GuiOptionButton<>(settings, settings.overlayShowBiome));
+        	overlayButtonsLayout.addElement(new OverlayButtonElement<>(settings, settings.overlayShowBiome));
         	uvs.add(5);
         }
         
         overlayButtonsLayout.updateElementPositions();
         
         for (GuiElement element : overlayButtonsLayout.elements) {
-    		GuiButton button = (GuiButton) element;
+    		ButtonElement button = (ButtonElement) element;
     		button.visible = false;
-    		controlList.add(button);
+    		buttons.add(button);
         }
     }
 
     @Override
 	protected void drawGuiContainerForegroundLayer()
     {
-        fontRenderer.drawString(I18n.getInstance().translateKey("gui.inventory.label.crafting"), 86, 16, 0x404040);
+        font.drawString(I18n.getInstance().translateKey("gui.inventory.label.crafting"), 86, 16, 0x404040);
     }
 
     @Override
-	public void drawScreen(int mouseX, int mouseY, float partialTick)
+	public void render(int xm, int ym, float partialTick)
     {
-        super.drawScreen(mouseX, mouseY, partialTick);
-        xSize_lo = mouseX;
-        ySize_lo = mouseY;
+        super.render(xm, ym, partialTick);
+        xSize_lo = xm;
+        ySize_lo = ym;
 
         if(mc.gameSettings.armorProtectionOverlay.value && armorButton.enabled) {
-        	drawProtectionOverlay(mouseX, mouseY);
+        	drawProtectionOverlay(xm, ym);
         }
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/inventory.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/inventory.png").bind();
         
         glColor4d(1.0, 1.0, 1.0, 1.0);
         glDisable(GL_BLEND);
         glEnable(GL_TEXTURE_2D);
         
         if(armorButton.enabled) {
-            if(armorButton.isHovered(mouseX, mouseY)) {
+            if(armorButton.isHovered(xm, ym)) {
             	drawTexturedModalRect(armorButton.xPosition, armorButton.yPosition, 185, 0, armorButton.width, armorButton.height);
             }else {
             	drawTexturedModalRect(armorButton.xPosition, armorButton.yPosition, 176, 0, armorButton.width, armorButton.height);
@@ -170,7 +173,7 @@ public class GuiInventory extends GuiContainer
         }
         
         for(int i=0; i < overlayButtonsLayout.elements.size(); i++) {
-        	GuiOptionButton<?> button = (GuiOptionButton<?>) overlayButtonsLayout.elements.get(i);
+        	OverlayButtonElement<?> button = (OverlayButtonElement<?>) overlayButtonsLayout.elements.get(i);
         	drawTexturedModalRect(button.xPosition + 1, button.yPosition + 1, 176, 9 + 9 * uvs.get(i), 9, 9);
         	boolean val = true;
         	if(button.option instanceof BooleanOption) val = (Boolean) button.option.value;
@@ -178,10 +181,10 @@ public class GuiInventory extends GuiContainer
         }
 
         for(int i=0; i < overlayButtonsLayout.elements.size(); i++) {
-        	GuiOptionButton<?> button = (GuiOptionButton<?>) overlayButtonsLayout.elements.get(i);
-        	if(button.isHovered(mouseX, mouseY))
+        	OverlayButtonElement<?> button = (OverlayButtonElement<?>) overlayButtonsLayout.elements.get(i);
+        	if(button.isHovered(xm, ym))
             {
-                guiTooltip.render(button.option.getDisplayStringName() + ": " + button.displayString, mouseX, mouseY, 8, -8);
+                tooltipElement.render(button.option.getDisplayStringName() + ": " + button.displayString, xm, ym, 8, -8);
         	}
         }
         
@@ -249,7 +252,7 @@ public class GuiInventory extends GuiContainer
 
         	String str = I18n.getInstance().translateKey(hoveredDamageType.getLanguageKey()) + ":\n" + protection + " / 100";
         	
-        	guiTooltip.render(str, mouseX, mouseY, 8, -8);
+        	tooltipElement.render(str, mouseX, mouseY, 8, -8);
         }
     }
 
@@ -257,7 +260,7 @@ public class GuiInventory extends GuiContainer
 	protected void drawGuiContainerBackgroundLayer(float f)
     {
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/inventory.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/inventory.png").bind();
         int j = (width - xSize) / 2;
         int k = (height - ySize) / 2;
         drawTexturedModalRect(j, k, 0, 0, xSize, ySize);
@@ -295,7 +298,7 @@ public class GuiInventory extends GuiContainer
     }
 
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
         if (button == armorButton) {
         	mc.gameSettings.armorProtectionOverlay.toggle();
@@ -304,7 +307,7 @@ public class GuiInventory extends GuiContainer
 
     @Override
     public void guiSpecificControllerInput(ControllerInput controller){
-        controller.craftingGuiHandler.handleInventory(this);
+        controller.inventoryHandler.handleInventory(this);
     }
 
     protected float xSize_lo;
diff --git a/src/main/java/net/minecraft/client/gui/GuiInventoryCreative.java b/src/main/java/net/minecraft/client/gui/container/InventoryScreenCreative.java
similarity index 76%
rename from src/main/java/net/minecraft/client/gui/GuiInventoryCreative.java
rename to src/main/java/net/minecraft/client/gui/container/InventoryScreenCreative.java
index 6666bf4ef..6bf894b2a 100644
--- a/src/main/java/net/minecraft/client/gui/GuiInventoryCreative.java
+++ b/src/main/java/net/minecraft/client/gui/container/InventoryScreenCreative.java
@@ -1,9 +1,11 @@
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.container;
 
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.TextFieldElement;
 import net.minecraft.client.input.controller.ControllerInput;
 import net.minecraft.core.InventoryAction;
 import net.minecraft.core.entity.player.Player;
-import net.minecraft.client.gui.options.GuiOptionsButton;
+import net.minecraft.client.gui.options.OptionsButtonElement;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.player.inventory.menu.CreativeInventoryMenu;
 import net.minecraft.client.render.Lighting;
@@ -13,19 +15,19 @@ import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.GL11;
 
-import net.minecraft.client.gui.GuiTextField.ITextChangeListener;
+import net.minecraft.client.gui.TextFieldElement.ITextChangeListener;
 import org.lwjgl.opengl.GL12;
 
-public class GuiInventoryCreative extends GuiInventory implements ITextChangeListener
+public class InventoryScreenCreative extends InventoryScreen implements ITextChangeListener
 {
-	protected GuiButton lastPageButton;
-	protected GuiButton nextPageButton;
-	protected GuiOptionsButton clearSearchButton;
-	protected GuiTextField searchField;
+	protected ButtonElement lastPageButton;
+	protected ButtonElement nextPageButton;
+	protected OptionsButtonElement clearSearchButton;
+	protected TextFieldElement searchField;
 	protected CreativeInventoryMenu container;
 	protected String pageString = "1/1";
 	
-	public GuiInventoryCreative(Player entityplayer)
+	public InventoryScreenCreative(Player entityplayer)
 	{
 		super(entityplayer);
 		xSize = 298;
@@ -39,10 +41,10 @@ public class GuiInventoryCreative extends GuiInventory implements ITextChangeLis
 	public void init()
 	{
 		super.init();
-		controlList.add(lastPageButton = new GuiButton(500, 0, 0, 20, 20, "<"));
-		controlList.add(nextPageButton = new GuiButton(501, 0, 0, 20, 20, ">"));
-		controlList.add(clearSearchButton = new GuiOptionsButton(0, 0, 10, 12, 20, "X"));
-		searchField = new GuiTextField(this, fontRenderer, 0, 0, 96, 18, container.searchText, I18n.getInstance().translateKey("gui.inventory.creative.label.search"));
+		buttons.add(lastPageButton = new ButtonElement(500, 0, 0, 20, 20, "<"));
+		buttons.add(nextPageButton = new ButtonElement(501, 0, 0, 20, 20, ">"));
+		buttons.add(clearSearchButton = new OptionsButtonElement(0, 0, 10, 12, 20, "X"));
+		searchField = new TextFieldElement(this, font, 0, 0, 96, 18, container.searchText, I18n.getInstance().translateKey("gui.inventory.creative.label.search"));
 		searchField.drawBackground =false;
 		searchField.setMaxStringLength(14);
 		searchField.setTextChangeListener(this);
@@ -79,9 +81,9 @@ public class GuiInventoryCreative extends GuiInventory implements ITextChangeLis
 	}
 
 	@Override
-	public void onClosed()
+	public void removed()
 	{
-		super.onClosed();
+		super.removed();
 		Keyboard.enableRepeatEvents(false);
 	}
 
@@ -94,9 +96,9 @@ public class GuiInventoryCreative extends GuiInventory implements ITextChangeLis
 	}
 	
     @Override
-	protected void buttonPressed(GuiButton button)
+	protected void buttonClicked(ButtonElement button)
     {
-		super.buttonPressed(button);
+		super.buttonClicked(button);
     	if (!button.enabled)
     	{
     		return;
@@ -131,28 +133,28 @@ public class GuiInventoryCreative extends GuiInventory implements ITextChangeLis
 	
     
     @Override
-	public void mouseClicked(int mouseX, int mouseY, int mouseButton)
+	public void mouseClicked(int mx, int my, int buttonNum)
     {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
-        searchField.mouseClicked(mouseX, mouseY, mouseButton);
+        super.mouseClicked(mx, my, buttonNum);
+        searchField.mouseClicked(mx, my, buttonNum);
     }
     
     @Override
-	public void keyTyped(char c, int i, int mouseX, int mouseY)
+	public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
-    	if (searchField.isFocused && i != Keyboard.KEY_ESCAPE)
+    	if (searchField.isFocused && eventKey != Keyboard.KEY_ESCAPE)
     	{
-    		searchField.textboxKeyTyped(c, i);
+    		searchField.textboxKeyTyped(eventCharacter, eventKey);
     		container.searchPage(searchField.getText());
     		updatePageSwitcher();
     	}
-    	else if (!searchField.isFocused && c == 't')
+    	else if (!searchField.isFocused && eventCharacter == 't')
     	{
     		searchField.setFocused(true);
     	}
     	else
     	{
-    		super.keyTyped(c, i, mouseX, mouseY);    		
+    		super.keyPressed(eventCharacter, eventKey, mx, my);
     	}
     }
     
@@ -160,7 +162,7 @@ public class GuiInventoryCreative extends GuiInventory implements ITextChangeLis
 	protected void drawGuiContainerForegroundLayer()
     {
     	super.drawGuiContainerForegroundLayer();
-    	drawStringCenteredNoShadow(fontRenderer, pageString, 238, 146, 0x404040);
+    	drawStringCenteredNoShadow(font, pageString, 238, 146, 0x404040);
     }
 	
     @Override
@@ -169,7 +171,7 @@ public class GuiInventoryCreative extends GuiInventory implements ITextChangeLis
 		scroll(Mouse.getDWheel());
 
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-		mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/creative.png").bind();
+		mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/creative.png").bind();
         int x = (width - xSize) / 2;
         int y = (height - ySize) / 2;
         lastPageButton.xPosition = x + 182;
@@ -216,7 +218,7 @@ public class GuiInventoryCreative extends GuiInventory implements ITextChangeLis
     }
 
 	@Override
-    public void textChanged(GuiTextField textField) {
+    public void textChanged(TextFieldElement textField) {
 		container.searchPage(textField.getText());
 		updatePageSwitcher();
 	}
diff --git a/src/main/java/net/minecraft/client/gui/GuiTrommel.java b/src/main/java/net/minecraft/client/gui/container/TrommelScreen.java
similarity index 73%
rename from src/main/java/net/minecraft/client/gui/GuiTrommel.java
rename to src/main/java/net/minecraft/client/gui/container/TrommelScreen.java
index 76e24e647..a8fa756ff 100644
--- a/src/main/java/net/minecraft/client/gui/GuiTrommel.java
+++ b/src/main/java/net/minecraft/client/gui/container/TrommelScreen.java
@@ -1,4 +1,4 @@
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.container;
 
 import net.minecraft.core.block.entity.TrommelBlockEntity;
 import net.minecraft.core.lang.I18n;
@@ -10,10 +10,10 @@ import org.lwjgl.opengl.GL11;
 //            GuiContainer, ContainerFurnace, FontRenderer, RenderEngine,
 //            FurnaceBlockEntity, InventoryPlayer
 
-public class GuiTrommel extends GuiContainer
+public class TrommelScreen extends AbstractContainerScreen
 {
 
-    public GuiTrommel(Inventory inventoryplayer, TrommelBlockEntity tileentitytrommel)
+    public TrommelScreen(Inventory inventoryplayer, TrommelBlockEntity tileentitytrommel)
     {
         super(new TrommelMenu(inventoryplayer, tileentitytrommel));
         ySize = 192;
@@ -23,15 +23,15 @@ public class GuiTrommel extends GuiContainer
     @Override
 	protected void drawGuiContainerForegroundLayer()
     {
-            fontRenderer.drawString(I18n.getInstance().translateKey("gui.trommel.label.trommel"), 60, 6, 0x404040);
-        fontRenderer.drawString(I18n.getInstance().translateKey("gui.trommel.label.inventory"), 8, (ySize - 96) + 2, 0x404040);
+            font.drawString(I18n.getInstance().translateKey("gui.trommel.label.trommel"), 60, 6, 0x404040);
+        font.drawString(I18n.getInstance().translateKey("gui.trommel.label.inventory"), 8, (ySize - 96) + 2, 0x404040);
     }
 
     @Override
 	protected void drawGuiContainerBackgroundLayer(float f)
     {
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/trommel.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/trommel.png").bind();
         int j = (width - xSize) / 2;
         int k = (height - ySize) / 2;
         drawTexturedModalRect(j, k, 0, 0, xSize, ySize);
diff --git a/src/main/java/net/minecraft/client/gui/createworld/ButtonComponent.java b/src/main/java/net/minecraft/client/gui/createworld/ButtonComponent.java
index 34e983b56..2bf5c0d93 100644
--- a/src/main/java/net/minecraft/client/gui/createworld/ButtonComponent.java
+++ b/src/main/java/net/minecraft/client/gui/createworld/ButtonComponent.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.createworld;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.client.gui.paged.PageComponent;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.sound.SoundCategory;
@@ -20,12 +20,12 @@ public abstract class ButtonComponent
 
     private final String translationKey;
 
-    protected final GuiButton resetButton;
+    protected final ButtonElement resetButton;
 
     public ButtonComponent(String translationKey)
     {
         this.translationKey = translationKey;
-        this.resetButton = new GuiButton(0, 0, 0, 20, 20, "")
+        this.resetButton = new ButtonElement(0, 0, 0, 20, 20, "")
             .setTextures("minecraft:gui/misc/icon_reset", "minecraft:gui/misc/icon_reset_highlighted", "minecraft:gui/misc/icon_reset");
     }
 
@@ -42,7 +42,7 @@ public abstract class ButtonComponent
     @Override
     public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY)
     {
-        FontRenderer fr = mc.fontRenderer;
+        Font fr = mc.font;
         String translated = I18n.getInstance().translateKey(translationKey);
         int textColor = 0xFFFFFFFF;
         if (relativeMouseX >= 0 && relativeMouseX <= width && relativeMouseY >= COMPONENT_SPACING && relativeMouseY <= getHeight() - COMPONENT_SPACING) {
diff --git a/src/main/java/net/minecraft/client/gui/createworld/GuiCreateWorld.java b/src/main/java/net/minecraft/client/gui/createworld/CreateWorldScreen.java
similarity index 66%
rename from src/main/java/net/minecraft/client/gui/createworld/GuiCreateWorld.java
rename to src/main/java/net/minecraft/client/gui/createworld/CreateWorldScreen.java
index fc852217c..1d7a97662 100644
--- a/src/main/java/net/minecraft/client/gui/createworld/GuiCreateWorld.java
+++ b/src/main/java/net/minecraft/client/gui/createworld/CreateWorldScreen.java
@@ -1,11 +1,11 @@
 package net.minecraft.client.gui.createworld;
 
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.paged.GuiPaged;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.paged.PagedScreen;
 
-public class GuiCreateWorld
-    extends GuiPaged {
-    public GuiCreateWorld(GuiScreen parent) {
+public class CreateWorldScreen
+    extends PagedScreen {
+    public CreateWorldScreen(Screen parent) {
         super(
             parent,
             CreateWorldPageRegistry.getInstance(),
diff --git a/src/main/java/net/minecraft/client/gui/createworld/TextFieldComponent.java b/src/main/java/net/minecraft/client/gui/createworld/TextFieldComponent.java
index 8aff0bfd9..eaad53240 100644
--- a/src/main/java/net/minecraft/client/gui/createworld/TextFieldComponent.java
+++ b/src/main/java/net/minecraft/client/gui/createworld/TextFieldComponent.java
@@ -1,15 +1,12 @@
 package net.minecraft.client.gui.createworld;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiTextField;
-import net.minecraft.client.gui.GuiTexturedButton;
+import net.minecraft.client.gui.TextFieldElement;
 import net.minecraft.client.gui.paged.CallbackComponent;
 import net.minecraft.client.gui.paged.OnValueChangedCallback;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.lang.I18n;
-import net.minecraft.core.sound.SoundCategory;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.opengl.GL11;
 
@@ -24,7 +21,7 @@ public class TextFieldComponent
 
     private final String translationKey;
 
-    private final GuiTextField textField;
+    private final TextFieldElement textField;
 
     private OnValueChangedCallback<String> callback = null;
 
@@ -32,9 +29,9 @@ public class TextFieldComponent
     {
         this.translationKey = translationKey;
 
-        this.textField = new GuiTextField(
+        this.textField = new TextFieldElement(
             null,
-            mc.fontRenderer,
+            mc.font,
             0, 0,
             BUTTON_WIDTH,
             18,
@@ -52,7 +49,7 @@ public class TextFieldComponent
     @Override
     public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY)
     {
-        FontRenderer fr = mc.fontRenderer;
+        Font fr = mc.font;
         String translated = I18n.getInstance().translateKey(translationKey);
         int textColor = 0xFFFFFFFF;
         if (relativeMouseX >= 0 && relativeMouseX <= width && relativeMouseY >= COMPONENT_SPACING && relativeMouseY <= getHeight() - COMPONENT_SPACING) {
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/GuidebookPage.java b/src/main/java/net/minecraft/client/gui/guidebook/GuidebookPage.java
index e3bad2858..08e74cfb9 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/GuidebookPage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/GuidebookPage.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.guidebook;
 
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import org.lwjgl.opengl.GL11;
 
 public abstract class GuidebookPage
@@ -19,24 +19,24 @@ public abstract class GuidebookPage
         return this.section;
     }
 
-    protected void renderBackground(RenderEngine re, int x, int y) {
+    protected void renderBackground(TextureManager re, int x, int y) {
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         re.bindTexture(re.loadTexture("/assets/minecraft/textures/gui/container/guidebook/guidebook.png"));
         drawTexturedModalRect(x, y, 0, 0, width, height);
     }
 
-    protected abstract void renderForeground(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks);
+    protected abstract void renderForeground(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks);
 
     public boolean drawHeaders() {
         return true;
     }
 
-    public void render(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    public void render(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         renderBackground(re, x, y);
         renderForeground(re, fr, x, y, mouseX, mouseY, partialTicks);
     }
 
-    protected void renderOverlay(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) { };
+    protected void renderOverlay(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) { };
 
     public void onMouseDown(int x, int y, int mouseX, int mouseY, int button) { }
 
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/GuiGuidebook.java b/src/main/java/net/minecraft/client/gui/guidebook/GuidebookScreen.java
similarity index 82%
rename from src/main/java/net/minecraft/client/gui/guidebook/GuiGuidebook.java
rename to src/main/java/net/minecraft/client/gui/guidebook/GuidebookScreen.java
index e78e5077d..0bf98c479 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/GuiGuidebook.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/GuidebookScreen.java
@@ -2,15 +2,15 @@ package net.minecraft.client.gui.guidebook;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.GuiTooltip;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.guidebook.search.SearchPage;
 import net.minecraft.client.gui.guidebook.search.SearchSection;
 import net.minecraft.client.input.controller.ControllerInput;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.Lighting;
 import net.minecraft.client.render.OpenGLHelper;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.entity.ItemEntityRenderer;
 import net.minecraft.client.render.item.model.ItemModelDispatcher;
 import net.minecraft.client.render.tessellator.Tessellator;
@@ -26,8 +26,8 @@ import org.lwjgl.opengl.GL12;
 import java.util.List;
 import java.util.Random;
 
-public class GuiGuidebook
-    extends GuiScreen {
+public class GuidebookScreen
+    extends Screen {
     private static final int TABS_PER_SIDE = 8;
     private static PageManager pageManager = null;
     public static PageManager getPageManager() {
@@ -40,13 +40,13 @@ public class GuiGuidebook
 
     private final int xSize = 158 * 2;
     private final int ySize = 220;
-    private final GuiTooltip tooltip = new GuiTooltip(Minecraft.getMinecraft(this));
+    private final TooltipElement tooltip = new TooltipElement(Minecraft.getMinecraft(this));
     private Tab[] tabs = new Tab[TABS_PER_SIDE * 2];
 
     private GuidebookPage lastPage = null;
     private boolean canPlaySound = true;
 
-    public GuiGuidebook() {
+    public GuidebookScreen() {
         super();
 
         getPageManager();
@@ -61,8 +61,8 @@ public class GuiGuidebook
     }
 
     @Override
-    public void onClosed() {
-        super.onClosed();
+    public void removed() {
+        super.removed();
 
         Keyboard.enableRepeatEvents(false);
     }
@@ -136,12 +136,12 @@ public class GuiGuidebook
     }
 
     @Override
-    public boolean pausesGame() {
+    public boolean isPauseScreen() {
         return false;
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float renderPartialTicks) {
+    public void render(int xm, int ym, float renderPartialTicks) {
         lastPage = pageManager.getLeftPage();
         scroll(Mouse.getDWheel());
 
@@ -153,13 +153,13 @@ public class GuiGuidebook
             xOffset = 158 / 2;
         }
 
-        drawDefaultBackground();
-        drawTabs(mouseX, mouseY);
-        drawCurrentPages(mouseX, mouseY, xOffset, renderPartialTicks);
+        renderBackground();
+        drawTabs(xm, ym);
+        drawCurrentPages(xm, ym, xOffset, renderPartialTicks);
         drawHeaders(xOffset);
-        drawCurrentPageOverlays(mouseX,mouseY,xOffset,renderPartialTicks);
-        drawPageTurnIndicator(mouseX, mouseY, xOffset);
-        drawTooltip(mouseX, mouseY);
+        drawCurrentPageOverlays(xm, ym,xOffset,renderPartialTicks);
+        drawPageTurnIndicator(xm, ym, xOffset);
+        drawTooltip(xm, ym);
     }
 
     private void scroll(int direction) {
@@ -177,17 +177,17 @@ public class GuiGuidebook
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
+    public void mouseClicked(int mx, int my, int buttonNum) {
+        super.mouseClicked(mx, my, buttonNum);
 
         // Handle back button
-        if (mouseButton == 3) {
+        if (buttonNum == 3) {
             pageManager.goBack();
             playPageSound();
             updateTabList();
             return;
         }
-        if (mouseButton == 4) {
+        if (buttonNum == 4) {
             pageManager.goForward();
             playPageSound();
             updateTabList();
@@ -210,13 +210,13 @@ public class GuiGuidebook
         int right = width / 2 + xSize / 2 + xOffset;
 
         if (pageManager.getLeftPage() != null && pageManager.hasPreviousPage()) {
-            if (mouseX >= left && mouseX <= left + size && mouseY >= top && mouseY <= top + size) {
+            if (mx >= left && mx <= left + size && my >= top && my <= top + size) {
                 pageManager.offsetPage(-2);
                 playPageSound();
                 updateTabList();
                 return;
             }
-            if (mouseX >= left && mouseX <= left + size && mouseY >= bottom - size && mouseY <= bottom) {
+            if (mx >= left && mx <= left + size && my >= bottom - size && my <= bottom) {
                 pageManager.offsetPage(-2);
                 playPageSound();
                 updateTabList();
@@ -224,13 +224,13 @@ public class GuiGuidebook
             }
         }
         if (pageManager.getRightPage() != null && pageManager.hasNextPage()) {
-            if (mouseX >= right - size && mouseX <= right && mouseY >= top && mouseY <= top + size) {
+            if (mx >= right - size && mx <= right && my >= top && my <= top + size) {
                 pageManager.offsetPage(2);
                 playPageSound();
                 updateTabList();
                 return;
             }
-            if (mouseX >= right - size && mouseX <= right && mouseY >= bottom - size && mouseY <= bottom) {
+            if (mx >= right - size && mx <= right && my >= bottom - size && my <= bottom) {
                 pageManager.offsetPage(2);
                 playPageSound();
                 updateTabList();
@@ -238,23 +238,23 @@ public class GuiGuidebook
             }
         }
 
-        if (pageManager.getLeftPage() != null && mouseX > left && mouseX < left + xSize / 2 && mouseY > top && mouseY < bottom) {
-            pageManager.getLeftPage().onMouseDown(left, top, mouseX, mouseY, mouseButton);
+        if (pageManager.getLeftPage() != null && mx > left && mx < left + xSize / 2 && my > top && my < bottom) {
+            pageManager.getLeftPage().onMouseDown(left, top, mx, my, buttonNum);
             updateTabList();
             return;
         }
-        if (pageManager.getRightPage() != null && mouseX > left + xSize / 2 && mouseX < right && mouseY > top && mouseY < bottom) {
-            pageManager.getRightPage().onMouseDown(left + xSize / 2, top, mouseX, mouseY, mouseButton);
+        if (pageManager.getRightPage() != null && mx > left + xSize / 2 && mx < right && my > top && my < bottom) {
+            pageManager.getRightPage().onMouseDown(left + xSize / 2, top, mx, my, buttonNum);
             updateTabList();
             return;
         }
 
-        handleTabClicks(mouseX, mouseY);
+        handleTabClicks(mx, my);
     }
 
     @Override
-    public void keyTyped(char c, int key, int mouseX, int mouseY) {
-        if(key != Keyboard.KEY_BACK) super.keyTyped(c, key, mouseX, mouseY);
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
+        if(eventKey != Keyboard.KEY_BACK) super.keyPressed(eventCharacter, eventKey, mx, my);
 
         int xOffset = 0;
         if (pageManager.getLeftPage() == null) {
@@ -268,22 +268,22 @@ public class GuiGuidebook
         int left = width / 2 - xSize / 2 + xOffset;
 
         if (allowArrowKeyNavigation) {
-            if (key == Keyboard.KEY_LEFT) {
+            if (eventKey == Keyboard.KEY_LEFT) {
                 pageManager.offsetPage(-2);
                 updateTabList();
             }
-            if (key == Keyboard.KEY_RIGHT) {
+            if (eventKey == Keyboard.KEY_RIGHT) {
                 pageManager.offsetPage(2);
                 updateTabList();
             }
         }
 
         if (pageManager.getLeftPage() != null) {
-            pageManager.getLeftPage().keyTyped(c, key, left, top, mouseX, mouseY);
+            pageManager.getLeftPage().keyTyped(eventCharacter, eventKey, left, top, mx, my);
             updateTabList();
         }
         if (pageManager.getRightPage() != null) {
-            pageManager.getRightPage().keyTyped(c, key, left + xSize / 2, top, mouseX, mouseY);
+            pageManager.getRightPage().keyTyped(eventCharacter, eventKey, left + xSize / 2, top, mx, my);
             updateTabList();
         }
     }
@@ -383,7 +383,7 @@ public class GuiGuidebook
     private void drawTabs(int mouseX, int mouseY) {
         for (Tab tab : tabs) {
             if (tab == null) break;
-            tab.render(mc.renderEngine, mc.fontRenderer, mouseX, mouseY);
+            tab.render(mc.textureManager, mc.font, mouseX, mouseY);
         }
     }
 
@@ -406,10 +406,10 @@ public class GuiGuidebook
         GuidebookPage rightPage = pageManager.getRightPage();
 
         if (leftPage != null) {
-            leftPage.render(mc.renderEngine, mc.fontRenderer, left, top, mouseX, mouseY, partialTicks);
+            leftPage.render(mc.textureManager, mc.font, left, top, mouseX, mouseY, partialTicks);
         }
         if (rightPage != null) {
-            rightPage.render(mc.renderEngine, mc.fontRenderer, right - 158, top, mouseX, mouseY, partialTicks);
+            rightPage.render(mc.textureManager, mc.font, right - 158, top, mouseX, mouseY, partialTicks);
         }
     }
 
@@ -423,10 +423,10 @@ public class GuiGuidebook
         GuidebookPage rightPage = pageManager.getRightPage();
 
         if (leftPage != null) {
-            leftPage.renderOverlay(mc.renderEngine, mc.fontRenderer,left,top,mouseX,mouseY,partialTicks);
+            leftPage.renderOverlay(mc.textureManager, mc.font,left,top,mouseX,mouseY,partialTicks);
         }
         if (rightPage != null) {
-            rightPage.renderOverlay(mc.renderEngine, mc.fontRenderer,right - 158,top,mouseX,mouseY,partialTicks);
+            rightPage.renderOverlay(mc.textureManager, mc.font,right - 158,top,mouseX,mouseY,partialTicks);
         }
     }
 
@@ -440,13 +440,13 @@ public class GuiGuidebook
 
         //find a way how to display the total number of pages properly maybe
         if (leftPage != null && leftPage.drawHeaders()) {
-            drawStringNoShadow(fontRenderer, String.valueOf(pageManager.getPageIndex(leftPage)) /*+ "/" + pageManager.getNumPages()*/, left + 12, bottom - 20, 0xFF000000);
-            drawStringCenteredNoShadow(fontRenderer, I18n.getInstance().translateKey(pageManager.getLeftPage().getSection().getTranslationKey()), left + 158 / 2, bottom - 20, 0xFF808080);
+            drawStringNoShadow(font, String.valueOf(pageManager.getPageIndex(leftPage)) /*+ "/" + pageManager.getNumPages()*/, left + 12, bottom - 20, 0xFF000000);
+            drawStringCenteredNoShadow(font, I18n.getInstance().translateKey(pageManager.getLeftPage().getSection().getTranslationKey()), left + 158 / 2, bottom - 20, 0xFF808080);
         }
         if (rightPage != null && rightPage.drawHeaders()) {
             String str = String.valueOf(pageManager.getPageIndex(rightPage)); /*+ "/" + pageManager.getNumPages();*/
-            drawStringNoShadow(fontRenderer, str, right - 12 - fontRenderer.getStringWidth(str), bottom - 20, 0xFF000000);
-            drawStringCenteredNoShadow(fontRenderer, I18n.getInstance().translateKey(pageManager.getRightPage().getSection().getTranslationKey()), right - 158 / 2, bottom - 20, 0xFF808080);
+            drawStringNoShadow(font, str, right - 12 - font.getStringWidth(str), bottom - 20, 0xFF000000);
+            drawStringCenteredNoShadow(font, I18n.getInstance().translateKey(pageManager.getRightPage().getSection().getTranslationKey()), right - 158 / 2, bottom - 20, 0xFF808080);
         }
     }
 
@@ -458,7 +458,7 @@ public class GuiGuidebook
         int left = width / 2 - xSize / 2 + xOffset;
         int right = width / 2 + xSize / 2 + xOffset;
 
-        mc.renderEngine.bindTexture(mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/container/guidebook/guidebook.png"));
+        mc.textureManager.bindTexture(mc.textureManager.loadTexture("/assets/minecraft/textures/gui/container/guidebook/guidebook.png"));
 
         GL11.glColor4f(1, 1, 1, 1);
         if (pageManager.getLeftPage() != null && pageManager.hasPreviousPage()) {
@@ -514,7 +514,7 @@ public class GuiGuidebook
             this.active = active;
         }
 
-        public void render(RenderEngine re, FontRenderer fr, int mouseX, int mouseY) {
+        public void render(TextureManager re, Font fr, int mouseX, int mouseY) {
             boolean mouseOver = mouseOver(mouseX, mouseY);
 
             re.bindTexture(re.loadTexture("/assets/minecraft/textures/gui/container/guidebook/guidebook.png"));
@@ -559,7 +559,7 @@ public class GuiGuidebook
             }
         }
 
-        public void renderTooltip(GuiTooltip tooltip, int mouseX, int mouseY) {
+        public void renderTooltip(TooltipElement tooltip, int mouseX, int mouseY) {
             if (mouseOver(mouseX, mouseY)) {
                 tooltip.render(I18n.getInstance().translateKey(section.getTranslationKey()), mouseX, mouseY, 8, -8);
             }
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/PageNavigationStack.java b/src/main/java/net/minecraft/client/gui/guidebook/PageNavigationStack.java
index 82071ad91..68aa577a0 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/PageNavigationStack.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/PageNavigationStack.java
@@ -1,8 +1,12 @@
 package net.minecraft.client.gui.guidebook;
 
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
+
 import java.util.Stack;
 
 public class PageNavigationStack {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private final int maxSize;
     private final Stack<Integer> stack = new Stack<>();
     private int stackPointer = 0;
@@ -45,12 +49,12 @@ public class PageNavigationStack {
 
     public void goBack() {
         decSP();
-        System.out.println(stackPointer + "/" + (stack.size() - 1));
+        LOGGER.debug("{}/{}", stackPointer, stack.size() - 1);
     }
 
     public void goForward() {
         incSP();
-        System.out.println(stackPointer + "/" + (stack.size() - 1));
+        LOGGER.debug("{}/{}", stackPointer, stack.size() - 1);
     }
 
 }
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/RecipePage.java b/src/main/java/net/minecraft/client/gui/guidebook/RecipePage.java
index 8014bd6ee..f34b35f32 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/RecipePage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/RecipePage.java
@@ -1,9 +1,6 @@
 package net.minecraft.client.gui.guidebook;
 
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
 import net.minecraft.core.data.registry.recipe.RecipeEntryBase;
-import net.minecraft.core.data.registry.recipe.entry.RecipeEntryCrafting;
 
 import java.util.List;
 
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/cover/CoverPage.java b/src/main/java/net/minecraft/client/gui/guidebook/cover/CoverPage.java
index ddc897956..41e88577d 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/cover/CoverPage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/cover/CoverPage.java
@@ -2,8 +2,8 @@ package net.minecraft.client.gui.guidebook.cover;
 
 import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.core.Global;
 
 public class CoverPage
@@ -18,13 +18,13 @@ public class CoverPage
     }
 
     @Override
-    public void renderBackground(RenderEngine re, int x, int y) {
+    public void renderBackground(TextureManager re, int x, int y) {
         re.bindTexture(re.loadTexture("/assets/minecraft/textures/gui/container/guidebook/cover.png"));
         drawTexturedModalRect(x, y, 0, 0, 158, 220);
     }
 
     @Override
-    public void renderForeground(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    public void renderForeground(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         drawStringCenteredNoShadow(fr, Global.VERSION, x + 84, y + 151, (getSection().getForegroundColor() & 0xFCFCFC) >> 2);
         drawStringCenteredNoShadow(fr, Global.VERSION, x + 84, y + 150, getSection().getForegroundColor());
     }
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/crafting/CraftingPage.java b/src/main/java/net/minecraft/client/gui/guidebook/crafting/CraftingPage.java
index ac8937515..c1d084552 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/crafting/CraftingPage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/crafting/CraftingPage.java
@@ -1,17 +1,17 @@
 package net.minecraft.client.gui.guidebook.crafting;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiRenderItem;
-import net.minecraft.client.gui.GuiTooltip;
-import net.minecraft.client.gui.guidebook.GuiGuidebook;
+import net.minecraft.client.gui.ItemElement;
+import net.minecraft.client.gui.TooltipElement;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.gui.guidebook.GuidebookSections;
 import net.minecraft.client.gui.guidebook.PageManager;
 import net.minecraft.client.gui.guidebook.RecipePage;
 import net.minecraft.client.gui.guidebook.search.SearchPage;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.data.registry.recipe.RecipeSymbol;
 import net.minecraft.core.data.registry.recipe.SearchQuery;
@@ -35,8 +35,8 @@ public class CraftingPage
 
     public List<GuidebookSlot> slots;
     public Map<RecipeEntryCrafting<?,?>,List<GuidebookSlot>> map;
-    private final GuiTooltip guiTooltip;
-    private final GuiRenderItem guiRenderItem;
+    private final TooltipElement tooltipElement;
+    private final ItemElement itemElement;
     private static final Minecraft mc = Minecraft.getMinecraft(GuidebookPage.class);
     private static Player player;
     private static long ticks = 0;
@@ -48,8 +48,8 @@ public class CraftingPage
         this.map = new HashMap<>();
         player = mc.thePlayer;
         player.addStat(Achievements.OPEN_GUIDEBOOK,1);
-        guiTooltip = new GuiTooltip(mc);
-        guiRenderItem = new GuiRenderItem(mc);
+        tooltipElement = new TooltipElement(mc);
+        itemElement = new ItemElement(mc);
         int recipeAmount = 0;
         int xOffset = 32;
         int yOffset = 12;
@@ -172,7 +172,7 @@ public class CraftingPage
     }
 
     @Override
-    protected void renderForeground(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderForeground(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         if(recipes.isEmpty()){
             drawStringCenteredNoShadow(fr,"No recipes found :(" ,x+width/2,y+height/2,0xFF808080);
         }
@@ -190,7 +190,7 @@ public class CraftingPage
             }
             drawSlot(x+slot.x -1,y+slot.y -1,0xFFFFFFFF);
             if(getIsMouseOverSlot(slot,x,y,mouseX,mouseY)) mouseOverSlot = slot;
-            guiRenderItem.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
+            itemElement.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
         }
     }
 
@@ -212,8 +212,8 @@ public class CraftingPage
                     String query = "r:"+hoveringSlot.getItem().getDisplayName()+"!";
                     PageManager.searchQuery = SearchQuery.resolve(query);
                     SearchPage.searchField.setText(query);
-                    GuiGuidebook.getPageManager().updatePages();
-                    GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+                    GuidebookScreen.getPageManager().updatePages();
+                    GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
                 }
             }
         } else if (mc.gameSettings.keyShowUsage.isKeyboardKey(key)) {
@@ -226,21 +226,21 @@ public class CraftingPage
                     String query = "u:" + hoveringSlot.getItem().getDisplayName() + "!";
                     PageManager.searchQuery = SearchQuery.resolve(query);
                     SearchPage.searchField.setText(query);
-                    GuiGuidebook.getPageManager().updatePages();
-                    GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+                    GuidebookScreen.getPageManager().updatePages();
+                    GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
                 }
             }
         }
     }
 
     @Override
-    public void render(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    public void render(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         super.render(re, fr, x, y, mouseX, mouseY, partialTicks);
 
     }
 
     @Override
-    protected void renderBackground(RenderEngine re, int x, int y) {
+    protected void renderBackground(TextureManager re, int x, int y) {
         super.renderBackground(re, x, y);
         re.bindTexture(re.loadTexture("/assets/minecraft/textures/gui/container/guidebook/guidebook.png"));
         for (int i = 1; i <= recipes.size(); i++) {
@@ -251,7 +251,7 @@ public class CraftingPage
     }
 
     @Override
-    protected void renderOverlay(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderOverlay(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         super.renderOverlay(re, fr, x, y, mouseX, mouseY, partialTicks);
         GuidebookSlot mouseOverSlot = null;
         for (GuidebookSlot slot : slots) {
@@ -260,10 +260,10 @@ public class CraftingPage
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = guiTooltip.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
-                    guiTooltip.render(str, mouseX, mouseY, 8, -8);
+                    tooltipElement.render(str, mouseX, mouseY, 8, -8);
                 }
             }
         }
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/index/IndexPage.java b/src/main/java/net/minecraft/client/gui/guidebook/index/IndexPage.java
index a3ea8981d..bb25150a4 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/index/IndexPage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/index/IndexPage.java
@@ -1,11 +1,11 @@
 package net.minecraft.client.gui.guidebook.index;
 
-import net.minecraft.client.gui.guidebook.GuiGuidebook;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.gui.guidebook.PageManager;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.core.lang.I18n;
 import org.lwjgl.opengl.GL11;
 
@@ -27,7 +27,7 @@ public class IndexPage
     }
 
     @Override
-    protected void renderForeground(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderForeground(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         int yOffset = 10;
         for (int i = startIndex; i < startIndex + LINES_PER_PAGE && i < lines.size() / 2; i++) {
             int j = i - startIndex;
@@ -66,7 +66,7 @@ public class IndexPage
     @Override
     public void onMouseDown(int x, int y, int mouseX, int mouseY, int button) {
         super.onMouseDown(x, y, mouseX, mouseY, button);
-        PageManager pageManager = GuiGuidebook.getPageManager();
+        PageManager pageManager = GuidebookScreen.getPageManager();
 
         int yOffset = 10;
         for (int i = startIndex; i < startIndex + LINES_PER_PAGE && i < lines.size(); i++) {
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/mobs/MobPage.java b/src/main/java/net/minecraft/client/gui/guidebook/mobs/MobPage.java
index fd44d2cd8..fd208ccdb 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/mobs/MobPage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/mobs/MobPage.java
@@ -1,8 +1,9 @@
 package net.minecraft.client.gui.guidebook.mobs;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiRenderItem;
-import net.minecraft.client.gui.GuiTooltip;
+import net.minecraft.client.gui.ItemElement;
+import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.render.*;
@@ -22,11 +23,13 @@ import net.minecraft.core.world.World;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
+import org.slf4j.Logger;
 
 import java.util.*;
 
 public class MobPage
     extends GuidebookPage {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private final Class<? extends Entity> mobClass;
     private final MobInfoRegistry.MobInfo mobInfo;
     private final Mob example;
@@ -35,8 +38,8 @@ public class MobPage
     private List<GuidebookSlot> slots;
     private Map<MobInfoRegistry.MobDrop, GuidebookSlot> dropSlotMap;
     private static final Minecraft mc = Minecraft.getMinecraft(GuidebookPage.class);
-    private static final GuiRenderItem guiRenderItem = new GuiRenderItem(mc);
-    private static final GuiTooltip guiTooltip = new GuiTooltip(mc);
+    private static final ItemElement itemElement = new ItemElement(mc);
+    private static final TooltipElement tooltipElement = new TooltipElement(mc);
     private boolean discovered;
 
 
@@ -50,7 +53,7 @@ public class MobPage
         try {
             example = (Mob) mobClass.getConstructor(World.class).newInstance((Object)null);
         } catch (Exception e) {
-            e.printStackTrace();
+            LOGGER.error("Failed to create example instance of mob '{}'!", mobClass.getSimpleName(), e);
         }
         this.example = example;
         if (example != null) example.setSkinVariant(0);
@@ -69,7 +72,7 @@ public class MobPage
         discovered = mc.statsCounter.readStat(StatList.mobEncounterStats.get(EntityDispatcher.classToKeyMap.get(mobClass))) > 0;
     }
 
-    private static String[] createDescLines(FontRenderer fr, String languageKey) {
+    private static String[] createDescLines(Font fr, String languageKey) {
         String[] words = I18n.getInstance().translateKey(languageKey).split(" ");
         List<String> lines = new ArrayList<>();
         StringBuilder line = new StringBuilder();
@@ -97,14 +100,14 @@ public class MobPage
     }
 
     @Override
-    protected void renderBackground(RenderEngine re, int x, int y) {
+    protected void renderBackground(TextureManager re, int x, int y) {
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         re.bindTexture(re.loadTexture("/assets/minecraft/textures/gui/container/guidebook/mob.png"));
         drawTexturedModalRect(x, y, 0, 0, 158, 220);
     }
 
     @Override
-    protected void renderForeground(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderForeground(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         discovered = mc.statsCounter.readStat(StatList.mobEncounterStats.get(EntityDispatcher.classToKeyMap.get(mobClass))) > 0;
         if (mc.thePlayer.getGamemode() == Gamemode.creative || !mc.gameSettings.hideUndiscoveredItems.value) discovered = true;
 
@@ -192,7 +195,7 @@ public class MobPage
                         drawSlot(x + 7 + (i % 7) * 21, yOffset + (i / 7) * 20, 0xFFFFFFFF);
                         GL11.glPushMatrix();
                         GL11.glTranslatef(0, 0, 50f);
-                        guiRenderItem.render(slot.getItem(), x + 8 + (i % 7) * 21, yOffset + 1 + (i / 7) * 20, mouseOver, slot);
+                        itemElement.render(slot.getItem(), x + 8 + (i % 7) * 21, yOffset + 1 + (i / 7) * 20, mouseOver, slot);
                         GL11.glPopMatrix();
                         if (slot.getIsDiscovered(mc.thePlayer)) {
                             String amountString = drop.getMinAmount() == drop.getMaxAmount() ? String.valueOf(drop.getMinAmount()) : drop.getMinAmount() + "-" + drop.getMaxAmount();
@@ -283,7 +286,7 @@ public class MobPage
     }
 
     @Override
-    protected void renderOverlay(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderOverlay(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         super.renderOverlay(re, fr, x, y, mouseX, mouseY, partialTicks);
         if (slots == null) return;
         GuidebookSlot mouseOverSlot = null;
@@ -293,10 +296,10 @@ public class MobPage
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = guiTooltip.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
-                    guiTooltip.render(str, mouseX, mouseY, 8, -8);
+                    tooltipElement.render(str, mouseX, mouseY, 8, -8);
                 }
             }
         }
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/search/SearchPage.java b/src/main/java/net/minecraft/client/gui/guidebook/search/SearchPage.java
index 3e0b70782..b0d9790b7 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/search/SearchPage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/search/SearchPage.java
@@ -1,18 +1,18 @@
 package net.minecraft.client.gui.guidebook.search;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiTextField;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.TextFieldElement;
 import net.minecraft.client.gui.guidebook.*;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.core.data.registry.recipe.SearchQuery;
 import net.minecraft.core.net.command.TextFormatting;
 
 public class SearchPage extends GuidebookPage {
 
-    public static final GuiTextField searchField = new GuiTextField(null, Minecraft.getMinecraft(SearchPage.class).fontRenderer,0,0,120,20,"","Search...");
-    public final GuiButton searchClearButton = new GuiButton(0,0,0,20,20,"X");
+    public static final TextFieldElement searchField = new TextFieldElement(null, Minecraft.getMinecraft(SearchPage.class).font,0,0,120,20,"","Search...");
+    public final ButtonElement searchClearButton = new ButtonElement(0,0,0,20,20,"X");
     private final Minecraft mc = Minecraft.getMinecraft(SearchPage.class);
 
     public SearchPage(GuidebookSection section) {
@@ -20,7 +20,7 @@ public class SearchPage extends GuidebookPage {
     }
 
     @Override
-    protected void renderForeground(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderForeground(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         searchField.xPosition = x + width/2 - searchField.width/2 - 10;
         searchField.yPosition = y + height/2 - searchField.height/2 - 70;
         searchClearButton.xPosition = searchField.xPosition + searchField.width + 5;
@@ -29,7 +29,7 @@ public class SearchPage extends GuidebookPage {
         searchClearButton.drawButton(mc,mouseX,mouseY);
 
         int results = 0;
-        for (GuidebookPage page : GuiGuidebook.getPageManager().getPages()) {
+        for (GuidebookPage page : GuidebookScreen.getPageManager().getPages()) {
             if (page instanceof RecipePage) {
                 results += ((RecipePage<?>) page).recipes.size();
             }
@@ -71,12 +71,12 @@ public class SearchPage extends GuidebookPage {
         searchField.mouseClicked(mouseX,mouseY,button);
         if(searchField.isFocused){
             PageManager.searchQuery = SearchQuery.resolve(searchField.getText());
-            GuiGuidebook.getPageManager().updatePages();
+            GuidebookScreen.getPageManager().updatePages();
         }
         if(searchClearButton.mouseClicked(mc,mouseX,mouseY)){
             searchField.setText("");
             PageManager.searchQuery = SearchQuery.resolve(searchField.getText());
-            GuiGuidebook.getPageManager().updatePages();
+            GuidebookScreen.getPageManager().updatePages();
         }
     }
 
@@ -85,7 +85,7 @@ public class SearchPage extends GuidebookPage {
         if(searchField.isFocused) {
             searchField.textboxKeyTyped(c, key);
             PageManager.searchQuery = SearchQuery.resolve(searchField.getText());
-            GuiGuidebook.getPageManager().updatePages();
+            GuidebookScreen.getPageManager().updatePages();
         }
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/smelting/BlastSmeltingPage.java b/src/main/java/net/minecraft/client/gui/guidebook/smelting/BlastSmeltingPage.java
index 4311a3a2b..25779dde6 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/smelting/BlastSmeltingPage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/smelting/BlastSmeltingPage.java
@@ -1,17 +1,17 @@
 package net.minecraft.client.gui.guidebook.smelting;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiRenderItem;
-import net.minecraft.client.gui.GuiTooltip;
-import net.minecraft.client.gui.guidebook.GuiGuidebook;
+import net.minecraft.client.gui.ItemElement;
+import net.minecraft.client.gui.TooltipElement;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.gui.guidebook.GuidebookSections;
 import net.minecraft.client.gui.guidebook.PageManager;
 import net.minecraft.client.gui.guidebook.RecipePage;
 import net.minecraft.client.gui.guidebook.search.SearchPage;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.data.registry.recipe.RecipeSymbol;
 import net.minecraft.core.data.registry.recipe.SearchQuery;
@@ -32,8 +32,8 @@ public class BlastSmeltingPage
     public static final int RECIPES_PER_PAGE = 6;
     public List<GuidebookSlot> slots;
     public Map<RecipeEntryBlastFurnace,List<GuidebookSlot>> map;
-    private final GuiTooltip guiTooltip;
-    private final GuiRenderItem guiRenderItem;
+    private final TooltipElement tooltipElement;
+    private final ItemElement itemElement;
     private static final Minecraft mc = Minecraft.getMinecraft(GuidebookPage.class);
     private static Player player;
     private static long ticks = 0;
@@ -44,8 +44,8 @@ public class BlastSmeltingPage
         this.map = new HashMap<>();
         player = mc.thePlayer;
         player.addStat(Achievements.OPEN_GUIDEBOOK,1);
-        guiTooltip = new GuiTooltip(mc);
-        guiRenderItem = new GuiRenderItem(mc);
+        tooltipElement = new TooltipElement(mc);
+        itemElement = new ItemElement(mc);
 
         for (RecipeEntryBlastFurnace recipe : recipes) {
             List<GuidebookSlot> recipeSlots = new ArrayList<>();
@@ -57,7 +57,7 @@ public class BlastSmeltingPage
     }
 
     @Override
-    protected void renderForeground(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderForeground(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         if(recipes.isEmpty()){
             drawStringCenteredNoShadow(fr,"No recipes found :(" ,x+width/2,y+height/2,0xFF808080);
         }
@@ -72,7 +72,7 @@ public class BlastSmeltingPage
             }
             drawSlot(x+slot.x -1,y+slot.y -1,0xFFFFFFFF);
             if(getIsMouseOverSlot(slot,x,y,mouseX,mouseY)) mouseOverSlot = slot;
-            guiRenderItem.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
+            itemElement.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
         }
     }
 
@@ -94,8 +94,8 @@ public class BlastSmeltingPage
                     String query = "r:"+hoveringSlot.getItem().getDisplayName()+"!";
                     PageManager.searchQuery = SearchQuery.resolve(query);
                     SearchPage.searchField.setText(query);
-                    GuiGuidebook.getPageManager().updatePages();
-                    GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+                    GuidebookScreen.getPageManager().updatePages();
+                    GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
                 }
             }
         } else if (mc.gameSettings.keyShowUsage.isKeyboardKey(key)) {
@@ -108,21 +108,21 @@ public class BlastSmeltingPage
                     String query = "u:" + hoveringSlot.getItem().getDisplayName() + "!";
                     PageManager.searchQuery = SearchQuery.resolve(query);
                     SearchPage.searchField.setText(query);
-                    GuiGuidebook.getPageManager().updatePages();
-                    GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+                    GuidebookScreen.getPageManager().updatePages();
+                    GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
                 }
             }
         }
     }
 
     @Override
-    public void render(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    public void render(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         super.render(re, fr, x, y, mouseX, mouseY, partialTicks);
 
     }
 
     @Override
-    protected void renderBackground(RenderEngine re, int x, int y) {
+    protected void renderBackground(TextureManager re, int x, int y) {
         super.renderBackground(re, x, y);
         re.bindTexture(re.loadTexture("/assets/minecraft/textures/gui/container/guidebook/guidebook.png"));
         for (int i = 1; i <= recipes.size(); i++) {
@@ -133,7 +133,7 @@ public class BlastSmeltingPage
     }
 
     @Override
-    protected void renderOverlay(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderOverlay(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         super.renderOverlay(re, fr, x, y, mouseX, mouseY, partialTicks);
         GuidebookSlot mouseOverSlot = null;
         for (GuidebookSlot slot : slots) {
@@ -142,10 +142,10 @@ public class BlastSmeltingPage
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = guiTooltip.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
-                    guiTooltip.render(str, mouseX, mouseY, 8, -8);
+                    tooltipElement.render(str, mouseX, mouseY, 8, -8);
                 }
             }
         }
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/smelting/SmeltingPage.java b/src/main/java/net/minecraft/client/gui/guidebook/smelting/SmeltingPage.java
index b2b49bbc0..29faa9f19 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/smelting/SmeltingPage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/smelting/SmeltingPage.java
@@ -1,17 +1,17 @@
 package net.minecraft.client.gui.guidebook.smelting;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiRenderItem;
-import net.minecraft.client.gui.GuiTooltip;
-import net.minecraft.client.gui.guidebook.GuiGuidebook;
+import net.minecraft.client.gui.ItemElement;
+import net.minecraft.client.gui.TooltipElement;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.gui.guidebook.GuidebookSections;
 import net.minecraft.client.gui.guidebook.PageManager;
 import net.minecraft.client.gui.guidebook.RecipePage;
 import net.minecraft.client.gui.guidebook.search.SearchPage;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.data.registry.recipe.RecipeSymbol;
 import net.minecraft.core.data.registry.recipe.SearchQuery;
@@ -32,8 +32,8 @@ public class SmeltingPage
     public static final int RECIPES_PER_PAGE = 6;
     public List<GuidebookSlot> slots;
     public Map<RecipeEntryFurnace,List<GuidebookSlot>> map;
-    private final GuiTooltip guiTooltip;
-    private final GuiRenderItem guiRenderItem;
+    private final TooltipElement tooltipElement;
+    private final ItemElement itemElement;
     private static final Minecraft mc = Minecraft.getMinecraft(GuidebookPage.class);
     private static Player player;
     private static long ticks = 0;
@@ -44,8 +44,8 @@ public class SmeltingPage
         this.map = new HashMap<>();
         player = mc.thePlayer;
         player.addStat(Achievements.OPEN_GUIDEBOOK,1);
-        guiTooltip = new GuiTooltip(mc);
-        guiRenderItem = new GuiRenderItem(mc);
+        tooltipElement = new TooltipElement(mc);
+        itemElement = new ItemElement(mc);
 
         for (RecipeEntryFurnace recipe : recipes) {
             List<GuidebookSlot> recipeSlots = new ArrayList<>();
@@ -57,7 +57,7 @@ public class SmeltingPage
     }
 
     @Override
-    protected void renderForeground(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderForeground(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         if(recipes.isEmpty()){
             drawStringCenteredNoShadow(fr,"No recipes found :(" ,x+width/2,y+height/2,0xFF808080);
         }
@@ -72,7 +72,7 @@ public class SmeltingPage
             }
             drawSlot(x+slot.x -1,y+slot.y -1,0xFFFFFFFF);
             if(getIsMouseOverSlot(slot,x,y,mouseX,mouseY)) mouseOverSlot = slot;
-            guiRenderItem.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
+            itemElement.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
         }
     }
 
@@ -94,8 +94,8 @@ public class SmeltingPage
                     String query = "r:"+hoveringSlot.getItem().getDisplayName()+"!";
                     PageManager.searchQuery = SearchQuery.resolve(query);
                     SearchPage.searchField.setText(query);
-                    GuiGuidebook.getPageManager().updatePages();
-                    GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+                    GuidebookScreen.getPageManager().updatePages();
+                    GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
                 }
             }
         } else if (mc.gameSettings.keyShowUsage.isKeyboardKey(key)) {
@@ -108,21 +108,21 @@ public class SmeltingPage
                     String query = "u:" + hoveringSlot.getItem().getDisplayName() + "!";
                     PageManager.searchQuery = SearchQuery.resolve(query);
                     SearchPage.searchField.setText(query);
-                    GuiGuidebook.getPageManager().updatePages();
-                    GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+                    GuidebookScreen.getPageManager().updatePages();
+                    GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
                 }
             }
         }
     }
 
     @Override
-    public void render(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    public void render(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         super.render(re, fr, x, y, mouseX, mouseY, partialTicks);
 
     }
 
     @Override
-    protected void renderBackground(RenderEngine re, int x, int y) {
+    protected void renderBackground(TextureManager re, int x, int y) {
         super.renderBackground(re, x, y);
         re.bindTexture(re.loadTexture("/assets/minecraft/textures/gui/container/guidebook/guidebook.png"));
         for (int i = 1; i <= recipes.size(); i++) {
@@ -133,7 +133,7 @@ public class SmeltingPage
     }
 
     @Override
-    protected void renderOverlay(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderOverlay(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         super.renderOverlay(re, fr, x, y, mouseX, mouseY, partialTicks);
         GuidebookSlot mouseOverSlot = null;
         for (GuidebookSlot slot : slots) {
@@ -142,10 +142,10 @@ public class SmeltingPage
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = guiTooltip.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
-                    guiTooltip.render(str, mouseX, mouseY, 8, -8);
+                    tooltipElement.render(str, mouseX, mouseY, 8, -8);
                 }
             }
         }
diff --git a/src/main/java/net/minecraft/client/gui/guidebook/trommeling/TrommelPage.java b/src/main/java/net/minecraft/client/gui/guidebook/trommeling/TrommelPage.java
index 30395d2c9..43beb1898 100644
--- a/src/main/java/net/minecraft/client/gui/guidebook/trommeling/TrommelPage.java
+++ b/src/main/java/net/minecraft/client/gui/guidebook/trommeling/TrommelPage.java
@@ -1,17 +1,17 @@
 package net.minecraft.client.gui.guidebook.trommeling;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiRenderItem;
-import net.minecraft.client.gui.GuiTooltip;
-import net.minecraft.client.gui.guidebook.GuiGuidebook;
+import net.minecraft.client.gui.ItemElement;
+import net.minecraft.client.gui.TooltipElement;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.gui.guidebook.GuidebookPage;
 import net.minecraft.client.gui.guidebook.GuidebookSection;
 import net.minecraft.client.gui.guidebook.GuidebookSections;
 import net.minecraft.client.gui.guidebook.PageManager;
 import net.minecraft.client.gui.guidebook.RecipePage;
 import net.minecraft.client.gui.guidebook.search.SearchPage;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.core.WeightedRandomBag;
 import net.minecraft.core.WeightedRandomLootObject;
 import net.minecraft.core.achievement.Achievements;
@@ -35,8 +35,8 @@ public class TrommelPage
     public static final int RECIPES_PER_PAGE = 3;
     public List<GuidebookSlot> slots;
     public Map<RecipeEntryTrommel,List<GuidebookSlot>> map;
-    private final GuiTooltip guiTooltip;
-    private final GuiRenderItem guiRenderItem;
+    private final TooltipElement tooltipElement;
+    private final ItemElement itemElement;
     private static final Minecraft mc = Minecraft.getMinecraft(GuidebookPage.class);
     private static Player player;
     private static long ticks = 0;
@@ -49,8 +49,8 @@ public class TrommelPage
         this.map = new HashMap<>();
         player = mc.thePlayer;
         player.addStat(Achievements.OPEN_GUIDEBOOK,1);
-        guiTooltip = new GuiTooltip(mc);
-        guiRenderItem = new GuiRenderItem(mc);
+        tooltipElement = new TooltipElement(mc);
+        itemElement = new ItemElement(mc);
         int recipeAmount = 0;
         int yOffset = 8;
         for (RecipeEntryTrommel recipe : recipes) {
@@ -79,7 +79,7 @@ public class TrommelPage
     }
 
     @Override
-    protected void renderForeground(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderForeground(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         if(recipes.isEmpty()){
             drawStringCenteredNoShadow(fr,"No recipes found :(" ,x+width/2,y+height/2,0xFF808080);
         }
@@ -120,7 +120,7 @@ public class TrommelPage
             }
             drawSlot(x+slot.x -1,y+slot.y -1,0xFFFFFFFF);
             if(getIsMouseOverSlot(slot,x,y,mouseX,mouseY)) mouseOverSlot = slot;
-            guiRenderItem.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
+            itemElement.render(slot.getItem(),x+slot.x,y+slot.y,mouseOverSlot == slot,slot);
         }
     }
 
@@ -142,8 +142,8 @@ public class TrommelPage
                     String query = "r:"+hoveringSlot.getItem().getDisplayName()+"!";
                     PageManager.searchQuery = SearchQuery.resolve(query);
                     SearchPage.searchField.setText(query);
-                    GuiGuidebook.getPageManager().updatePages();
-                    GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+                    GuidebookScreen.getPageManager().updatePages();
+                    GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
                 }
             }
         } else if (mc.gameSettings.keyShowUsage.isKeyboardKey(key)) {
@@ -156,21 +156,21 @@ public class TrommelPage
                     String query = "u:" + hoveringSlot.getItem().getDisplayName() + "!";
                     PageManager.searchQuery = SearchQuery.resolve(query);
                     SearchPage.searchField.setText(query);
-                    GuiGuidebook.getPageManager().updatePages();
-                    GuiGuidebook.getPageManager().setCurrentPage(GuiGuidebook.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
+                    GuidebookScreen.getPageManager().updatePages();
+                    GuidebookScreen.getPageManager().setCurrentPage(GuidebookScreen.getPageManager().getSectionIndex(GuidebookSections.CRAFTING), true);
                 }
             }
         }
     }
 
     @Override
-    public void render(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    public void render(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         super.render(re, fr, x, y, mouseX, mouseY, partialTicks);
 
     }
 
     @Override
-    protected void renderBackground(RenderEngine re, int x, int y) {
+    protected void renderBackground(TextureManager re, int x, int y) {
         super.renderBackground(re, x, y);
         re.bindTexture(re.loadTexture("/assets/minecraft/textures/gui/container/guidebook/guidebook.png"));
         for (int i = 1; i <= recipes.size(); i++) {
@@ -181,7 +181,7 @@ public class TrommelPage
     }
 
     @Override
-    protected void renderOverlay(RenderEngine re, FontRenderer fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
+    protected void renderOverlay(TextureManager re, Font fr, int x, int y, int mouseX, int mouseY, float partialTicks) {
         super.renderOverlay(re, fr, x, y, mouseX, mouseY, partialTicks);
         GuidebookSlot mouseOverSlot = null;
         for (GuidebookSlot slot : slots) {
@@ -190,10 +190,10 @@ public class TrommelPage
             if (mouseOverSlot != null && mouseOverSlot.hasItem())
             {
                 boolean showDescription = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) || mc.gameSettings.alwaysShowDescriptions.value;
-                String str = guiTooltip.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
+                String str = tooltipElement.getTooltipText(mouseOverSlot.getItem(), showDescription, mouseOverSlot);
                 if(!str.isEmpty())
                 {
-                    guiTooltip.render(str, mouseX, mouseY, 8, -8);
+                    tooltipElement.render(str, mouseX, mouseY, 8, -8);
                 }
             }
         }
diff --git a/src/main/java/net/minecraft/client/gui/GuiIngameDoom.java b/src/main/java/net/minecraft/client/gui/hud/DoomIngameHud.java
similarity index 85%
rename from src/main/java/net/minecraft/client/gui/GuiIngameDoom.java
rename to src/main/java/net/minecraft/client/gui/hud/DoomIngameHud.java
index 81376bfe5..a736165e0 100644
--- a/src/main/java/net/minecraft/client/gui/GuiIngameDoom.java
+++ b/src/main/java/net/minecraft/client/gui/hud/DoomIngameHud.java
@@ -1,339 +1,338 @@
-package net.minecraft.client.gui;
-
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.texture.stitcher.TextureRegistry;
-import net.minecraft.core.block.Blocks;
-import net.minecraft.core.item.ItemStack;
-import net.minecraft.core.net.command.TextFormatting;
-import org.lwjgl.opengl.GL11;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class GuiIngameDoom
-    extends GuiIngame
-{
-    private static final int[] NUMBER_WIDTHS = {
-            9, 7, 9, 9, 11, 9, 9, 9, 9, 9
-    };
-    private static final int[] NUMBER_US = {
-            0, 9, 16, 25, 34, 45, 54, 63, 72, 81
-    };
-
-    public GuiIngameDoom(Minecraft minecraft) {
-        super(minecraft);
-    }
-
-    @Override
-    public void renderGameOverlay(float partialTicks, boolean flag, int mouseX, int mouseY)
-    {
-        if (mc.currentScreen instanceof GuiPhotoMode) return;
-
-        int width = mc.resolution.scaledWidth;
-        int height = mc.resolution.scaledHeight;
-
-        FontRenderer fontrenderer = mc.fontRenderer;
-        mc.worldRenderer.setupScaledResolution();
-
-        GL11.glEnable(GL11.GL_BLEND);
-        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-
-        // Render vignette
-        if (mc.gameSettings.immersiveMode.drawVignette() && mc.gameSettings.vignette.value)
-        {
-            renderVignette(mc.thePlayer.getBrightness(partialTicks), width, height);
-        }
-
-        // Render pumpkin overlay
-        ItemStack headSlotItem = mc.thePlayer.inventory.armorItemInSlot(3);
-        if (mc.gameSettings.thirdPersonView.value == 0 && headSlotItem != null && headSlotItem.itemID == Blocks.PUMPKIN_CARVED_IDLE.id)
-        {
-            renderPumpkinBlur(width, height);
-        }
-
-        // Render portal overlay
-        float portalIntensity = mc.thePlayer.prevTimeInPortal + (mc.thePlayer.timeInPortal - mc.thePlayer.prevTimeInPortal) * partialTicks;
-        if (portalIntensity > 0.0F)
-        {
-            renderPortalOverlay(portalIntensity, width, height);
-        }
-
-        drawBackground();
-        drawFace();
-        drawAmmo();
-        drawHealth();
-        drawArmsButtons();
-        drawArmor();
-        drawHotbarIndicator();
-        drawStacks();
-
-        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-
-        if (mc.gameSettings.immersiveMode.drawCrosshair() && mc.gameSettings.thirdPersonView.value == 0)
-        {
-            // Render crosshair
-            GL11.glEnable(GL11.GL_BLEND);
-            GL11.glBlendFunc(GL11.GL_ONE_MINUS_DST_COLOR, GL11.GL_ONE_MINUS_SRC_COLOR);
-            drawGuiIcon(width/2 - 7, height/2 - 7, 15, 15, TextureRegistry.getTexture("minecraft:gui/hud/crosshair"));
-            GL11.glDisable(GL11.GL_BLEND);
-        }
-    }
-
-    private void drawBackground()
-    {
-        int width = mc.resolution.scaledWidth;
-        int height = mc.resolution.scaledHeight;
-
-        GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/hud/doom.png").bind();
-
-        // Draw main hotbar
-        drawTexturedModalRect(width / 2 - 197, height - 43, 0, 0, 197, 43);
-        drawTexturedModalRect(width / 2, height - 43, 0, 43, 197, 43);
-
-        // Draw sides
-        drawTexturedModalRect(0d, height - 43, 0, 86, width / 2 - 197, 43, 1, 43);
-        drawTexturedModalRect(width / 2d + 197d, height - 43, 0, 86, width - (width / 2 + 197), 43, 1, 43);
-    }
-
-    private void drawFace()
-    {
-        int width = mc.resolution.scaledWidth;
-        int height = mc.resolution.scaledHeight;
-
-        Face face = Face.NEUTRAL;
-        if (mc.thePlayer.getGamemode().isPlayerInvulnerable())
-        {
-            face = Face.GOD;
-        }
-        else if (mc.thePlayer.getHealth() == 0)
-        {
-            face = Face.DEAD;
-        }
-        else if (mc.thePlayer.hurtTime > 0)
-        {
-            face = Face.PAIN;
-        }
-        else if (updateCounter % 200 > 175)
-        {
-            face = Face.LOOK_RIGHT;
-        }
-        else if (updateCounter % 200 > 150)
-        {
-            face = Face.LOOK_LEFT;
-        }
-
-        drawTexturedModalRect(width / 2 - 16, height - 36, face.u, face.v, 32, 32);
-    }
-
-    private void drawAmmo()
-    {
-        int width = mc.resolution.scaledWidth;
-        int height = mc.resolution.scaledHeight;
-
-        ItemStack stack = mc.thePlayer.getHeldItem();
-        if (stack == null) return;
-        int ammo = stack.stackSize;
-
-        drawNumber(ammo, width / 2 - 160, height - 32);
-    }
-
-    private void drawHealth()
-    {
-        int width = mc.resolution.scaledWidth;
-        int height = mc.resolution.scaledHeight;
-
-        float healthPercentage = mc.thePlayer.getHealth() / (float)mc.thePlayer.getMaxHealth();
-        int health = (int)(healthPercentage * 100);
-        if (health < 0) health = 0;
-
-        drawNumber(health, width / 2 - 116, height - 32);
-    }
-
-    private void drawNumber(int i, int x, int y)
-    {
-        GL11.glColor4f(1f, 1f, 1f, 1f);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/hud/doom.png").bind();
-
-        List<Integer> parts = new ArrayList<>();
-
-        int prev = 0;
-        int mult = 1;
-        while (i / mult != 0)
-        {
-            int lowerDigits = i % (mult * 10);
-            int digit = lowerDigits - prev;
-            prev += digit;
-            parts.add(digit / mult);
-            mult *= 10;
-        }
-
-        for (int digit : parts)
-        {
-            int width = NUMBER_WIDTHS[digit];
-            int u = NUMBER_US[digit];
-            int v = 209;
-            x -= width;
-            drawTexturedModalRect(x, y, u, v, width, 15);
-            x -= 1;
-        }
-    }
-
-    private void drawArmsButtons()
-    {
-        int width = mc.resolution.scaledWidth;
-        int height = mc.resolution.scaledHeight;
-
-        int i = 1;
-        int activeSlot = mc.thePlayer.inventory.currentItem % 9;
-        for (int y = 0; y < 2; y++)
-        {
-            for (int x = 0; x < 5; x++)
-            {
-                if (i >= 10) continue;
-
-                int px = width / 2 - 90 + 14 * x;
-                int py = height - 38 + 14 * y;
-
-                drawArmsButton(px, py, i, i - 1 == activeSlot);
-
-                i++;
-            }
-        }
-    }
-
-    private void drawArmsButton(int x, int y, int number, boolean active)
-    {
-        GL11.glColor4f(1f, 1f, 1f, 1f);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/hud/doom.png").bind();
-
-        int u = 13;
-        int v = 196;
-        int textColor = 0xFFFFFFFF;
-
-        if (active)
-        {
-            u = 0;
-            textColor = 0xFFA0A0A0;
-        }
-
-        drawTexturedModalRect(x, y, u, v, 13, 13);
-        drawString(fontrenderer, Integer.toString(number % 10), x + 4, y + 3, textColor);
-    }
-
-    private void drawArmor()
-    {
-        int width = mc.resolution.scaledWidth;
-        int height = mc.resolution.scaledHeight;
-
-        float armorPercentage = mc.thePlayer.getPlayerProtectionAmount() / 20f;
-        int armor = (int)(armorPercentage * 100);
-
-        drawNumber(armor, width / 2 + 48, height - 32);
-    }
-
-    private void drawHotbarIndicator()
-    {
-//        GL11.glColor4f(1f, 1f, 1f, 1f);
-//        GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.renderEngine.getTexture("/assets/minecraft/textures/gui/doom.png"));
-
-        int width = mc.resolution.scaledWidth;
-        int height = mc.resolution.scaledHeight;
-
-        int x = width / 2 + 76;
-        int y = height - 36;
-
-        int selectedHotbar = ((mc.thePlayer.inventory.hotbarOffset + 27) % 36) / 9;
-
-        drawTexturedModalRect(x, y + 9 * selectedHotbar, 0, 129, 6, 6);
-    }
-
-    private void drawStacks()
-    {
-        int width = mc.resolution.scaledWidth;
-        int height = mc.resolution.scaledHeight;
-
-        int currentItem = mc.thePlayer.inventory.currentItem;
-        int wrappedCurrentItem = mc.thePlayer.inventory.currentItem % 9;
-
-        int offset = 0;
-        if (wrappedCurrentItem >= 5)
-        {
-            offset = 3 - (8 - wrappedCurrentItem);
-        }
-
-        int q = 0;
-        for (int i = currentItem - offset; i < currentItem - offset + 4; i++)
-        {
-            ItemStack stack = mc.thePlayer.inventory.getItem(i);
-            int x = width / 2 + 94;
-            int y = height - 37 + q * 9;
-
-            drawItemStack(stack, x, y, i == currentItem);
-
-            q++;
-        }
-    }
-
-    private void drawItemStack(ItemStack stack, int x, int y, boolean selected)
-    {
-        if (stack == null) return;
-        String name = stack.getDisplayName();
-        
-        if (name.length() >= 10) name = name.substring(0, 10);
-        name = name.toUpperCase();
-        if (selected)
-        {
-            drawString(fontrenderer, TextFormatting.get(stack.getDisplayColor()) + name, x, y, 0xFFFFFFFF);
-        }
-        else
-        {
-            drawStringNoShadow(fontrenderer, name, x, y, 0xFF404040);
-        }
-
-        int maxStackSize = stack.getMaxStackSize();
-        int stackSize = stack.stackSize;
-
-        // Draw stack size
-        if (stackSize < 10)
-        {
-            drawString(fontrenderer, Integer.toString(stackSize), x + 70, y, 0xFFFFFFA0);
-        }
-        else
-        {
-            drawString(fontrenderer, Integer.toString(stackSize), x + 64, y, 0xFFFFFFA0);
-        }
-
-        // Draw max stack size
-        if (maxStackSize < 10)
-        {
-            drawString(fontrenderer, Integer.toString(maxStackSize), x + 88, y, 0xFFFFFFA0);
-        }
-        else
-        {
-            drawString(fontrenderer, Integer.toString(maxStackSize), x + 82, y, 0xFFFFFFA0);
-        }
-    }
-
-    private enum Face
-    {
-        NEUTRAL(0, 224),
-        LOOK_RIGHT(32, 224),
-        LOOK_LEFT(64, 224),
-        GRIN(96, 224),
-        PAIN(128, 224),
-        BIG_PAIN(160, 224),
-        GOD(192, 224),
-        DEAD(224, 224);
-
-        public final int u;
-        public final int v;
-
-        Face(int u, int v)
-        {
-            this.u = u;
-            this.v = v;
-        }
-    }
-}
+package net.minecraft.client.gui.hud;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.PhotoModeScreen;
+import net.minecraft.client.render.texture.stitcher.TextureRegistry;
+import net.minecraft.core.block.Blocks;
+import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.net.command.TextFormatting;
+import org.lwjgl.opengl.GL11;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DoomIngameHud
+    extends IngameHud
+{
+    private static final int[] NUMBER_WIDTHS = {
+            9, 7, 9, 9, 11, 9, 9, 9, 9, 9
+    };
+    private static final int[] NUMBER_US = {
+            0, 9, 16, 25, 34, 45, 54, 63, 72, 81
+    };
+
+    public DoomIngameHud(Minecraft minecraft) {
+        super(minecraft);
+    }
+
+    @Override
+    public void renderGameOverlay(float partialTicks, boolean flag, int mouseX, int mouseY)
+    {
+        if (mc.currentScreen instanceof PhotoModeScreen) return;
+
+        int width = mc.resolution.scaledWidth;
+        int height = mc.resolution.scaledHeight;
+
+        mc.worldRenderer.setupScaledResolution();
+
+        GL11.glEnable(GL11.GL_BLEND);
+        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+        // Render vignette
+        if (mc.gameSettings.immersiveMode.drawVignette() && mc.gameSettings.vignette.value)
+        {
+            renderVignette(mc.thePlayer.getBrightness(partialTicks), width, height);
+        }
+
+        // Render pumpkin overlay
+        ItemStack headSlotItem = mc.thePlayer.inventory.armorItemInSlot(3);
+        if (mc.gameSettings.thirdPersonView.value == 0 && headSlotItem != null && headSlotItem.itemID == Blocks.PUMPKIN_CARVED_IDLE.id)
+        {
+            renderPumpkinBlur(width, height);
+        }
+
+        // Render portal overlay
+        float portalIntensity = mc.thePlayer.prevTimeInPortal + (mc.thePlayer.timeInPortal - mc.thePlayer.prevTimeInPortal) * partialTicks;
+        if (portalIntensity > 0.0F)
+        {
+            renderPortalOverlay(portalIntensity, width, height);
+        }
+
+        drawBackground();
+        drawFace();
+        drawAmmo();
+        drawHealth();
+        drawArmsButtons();
+        drawArmor();
+        drawHotbarIndicator();
+        drawStacks();
+
+        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+
+        if (mc.gameSettings.immersiveMode.drawCrosshair() && mc.gameSettings.thirdPersonView.value == 0)
+        {
+            // Render crosshair
+            GL11.glEnable(GL11.GL_BLEND);
+            GL11.glBlendFunc(GL11.GL_ONE_MINUS_DST_COLOR, GL11.GL_ONE_MINUS_SRC_COLOR);
+            drawGuiIcon(width/2 - 7, height/2 - 7, 15, 15, TextureRegistry.getTexture("minecraft:gui/hud/crosshair"));
+            GL11.glDisable(GL11.GL_BLEND);
+        }
+    }
+
+    private void drawBackground()
+    {
+        int width = mc.resolution.scaledWidth;
+        int height = mc.resolution.scaledHeight;
+
+        GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/hud/doom.png").bind();
+
+        // Draw main hotbar
+        drawTexturedModalRect(width / 2 - 197, height - 43, 0, 0, 197, 43);
+        drawTexturedModalRect(width / 2, height - 43, 0, 43, 197, 43);
+
+        // Draw sides
+        drawTexturedModalRect(0d, height - 43, 0, 86, width / 2 - 197, 43, 1, 43);
+        drawTexturedModalRect(width / 2d + 197d, height - 43, 0, 86, width - (width / 2 + 197), 43, 1, 43);
+    }
+
+    private void drawFace()
+    {
+        int width = mc.resolution.scaledWidth;
+        int height = mc.resolution.scaledHeight;
+
+        Face face = Face.NEUTRAL;
+        if (mc.thePlayer.getGamemode().isPlayerInvulnerable())
+        {
+            face = Face.GOD;
+        }
+        else if (mc.thePlayer.getHealth() == 0)
+        {
+            face = Face.DEAD;
+        }
+        else if (mc.thePlayer.hurtTime > 0)
+        {
+            face = Face.PAIN;
+        }
+        else if (updateCounter % 200 > 175)
+        {
+            face = Face.LOOK_RIGHT;
+        }
+        else if (updateCounter % 200 > 150)
+        {
+            face = Face.LOOK_LEFT;
+        }
+
+        drawTexturedModalRect(width / 2 - 16, height - 36, face.u, face.v, 32, 32);
+    }
+
+    private void drawAmmo()
+    {
+        int width = mc.resolution.scaledWidth;
+        int height = mc.resolution.scaledHeight;
+
+        ItemStack stack = mc.thePlayer.getHeldItem();
+        if (stack == null) return;
+        int ammo = stack.stackSize;
+
+        drawNumber(ammo, width / 2 - 160, height - 32);
+    }
+
+    private void drawHealth()
+    {
+        int width = mc.resolution.scaledWidth;
+        int height = mc.resolution.scaledHeight;
+
+        float healthPercentage = mc.thePlayer.getHealth() / (float)mc.thePlayer.getMaxHealth();
+        int health = (int)(healthPercentage * 100);
+        if (health < 0) health = 0;
+
+        drawNumber(health, width / 2 - 116, height - 32);
+    }
+
+    private void drawNumber(int i, int x, int y)
+    {
+        GL11.glColor4f(1f, 1f, 1f, 1f);
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/hud/doom.png").bind();
+
+        List<Integer> parts = new ArrayList<>();
+
+        int prev = 0;
+        int mult = 1;
+        while (i / mult != 0)
+        {
+            int lowerDigits = i % (mult * 10);
+            int digit = lowerDigits - prev;
+            prev += digit;
+            parts.add(digit / mult);
+            mult *= 10;
+        }
+
+        for (int digit : parts)
+        {
+            int width = NUMBER_WIDTHS[digit];
+            int u = NUMBER_US[digit];
+            int v = 209;
+            x -= width;
+            drawTexturedModalRect(x, y, u, v, width, 15);
+            x -= 1;
+        }
+    }
+
+    private void drawArmsButtons()
+    {
+        int width = mc.resolution.scaledWidth;
+        int height = mc.resolution.scaledHeight;
+
+        int i = 1;
+        int activeSlot = mc.thePlayer.inventory.currentItem % 9;
+        for (int y = 0; y < 2; y++)
+        {
+            for (int x = 0; x < 5; x++)
+            {
+                if (i >= 10) continue;
+
+                int px = width / 2 - 90 + 14 * x;
+                int py = height - 38 + 14 * y;
+
+                drawArmsButton(px, py, i, i - 1 == activeSlot);
+
+                i++;
+            }
+        }
+    }
+
+    private void drawArmsButton(int x, int y, int number, boolean active)
+    {
+        GL11.glColor4f(1f, 1f, 1f, 1f);
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/hud/doom.png").bind();
+
+        int u = 13;
+        int v = 196;
+        int textColor = 0xFFFFFFFF;
+
+        if (active)
+        {
+            u = 0;
+            textColor = 0xFFA0A0A0;
+        }
+
+        drawTexturedModalRect(x, y, u, v, 13, 13);
+        drawString(font, Integer.toString(number % 10), x + 4, y + 3, textColor);
+    }
+
+    private void drawArmor()
+    {
+        int width = mc.resolution.scaledWidth;
+        int height = mc.resolution.scaledHeight;
+
+        float armorPercentage = mc.thePlayer.getPlayerProtectionAmount() / 20f;
+        int armor = (int)(armorPercentage * 100);
+
+        drawNumber(armor, width / 2 + 48, height - 32);
+    }
+
+    private void drawHotbarIndicator()
+    {
+//        GL11.glColor4f(1f, 1f, 1f, 1f);
+//        GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.renderEngine.getTexture("/assets/minecraft/textures/gui/doom.png"));
+
+        int width = mc.resolution.scaledWidth;
+        int height = mc.resolution.scaledHeight;
+
+        int x = width / 2 + 76;
+        int y = height - 36;
+
+        int selectedHotbar = ((mc.thePlayer.inventory.hotbarOffset + 27) % 36) / 9;
+
+        drawTexturedModalRect(x, y + 9 * selectedHotbar, 0, 129, 6, 6);
+    }
+
+    private void drawStacks()
+    {
+        int width = mc.resolution.scaledWidth;
+        int height = mc.resolution.scaledHeight;
+
+        int currentItem = mc.thePlayer.inventory.currentItem;
+        int wrappedCurrentItem = mc.thePlayer.inventory.currentItem % 9;
+
+        int offset = 0;
+        if (wrappedCurrentItem >= 5)
+        {
+            offset = 3 - (8 - wrappedCurrentItem);
+        }
+
+        int q = 0;
+        for (int i = currentItem - offset; i < currentItem - offset + 4; i++)
+        {
+            ItemStack stack = mc.thePlayer.inventory.getItem(i);
+            int x = width / 2 + 94;
+            int y = height - 37 + q * 9;
+
+            drawItemStack(stack, x, y, i == currentItem);
+
+            q++;
+        }
+    }
+
+    private void drawItemStack(ItemStack stack, int x, int y, boolean selected)
+    {
+        if (stack == null) return;
+        String name = stack.getDisplayName();
+        
+        if (name.length() >= 10) name = name.substring(0, 10);
+        name = name.toUpperCase();
+        if (selected)
+        {
+            drawString(font, TextFormatting.get(stack.getDisplayColor()) + name, x, y, 0xFFFFFFFF);
+        }
+        else
+        {
+            drawStringNoShadow(font, name, x, y, 0xFF404040);
+        }
+
+        int maxStackSize = stack.getMaxStackSize();
+        int stackSize = stack.stackSize;
+
+        // Draw stack size
+        if (stackSize < 10)
+        {
+            drawString(font, Integer.toString(stackSize), x + 70, y, 0xFFFFFFA0);
+        }
+        else
+        {
+            drawString(font, Integer.toString(stackSize), x + 64, y, 0xFFFFFFA0);
+        }
+
+        // Draw max stack size
+        if (maxStackSize < 10)
+        {
+            drawString(font, Integer.toString(maxStackSize), x + 88, y, 0xFFFFFFA0);
+        }
+        else
+        {
+            drawString(font, Integer.toString(maxStackSize), x + 82, y, 0xFFFFFFA0);
+        }
+    }
+
+    private enum Face
+    {
+        NEUTRAL(0, 224),
+        LOOK_RIGHT(32, 224),
+        LOOK_LEFT(64, 224),
+        GRIN(96, 224),
+        PAIN(128, 224),
+        BIG_PAIN(160, 224),
+        GOD(192, 224),
+        DEAD(224, 224);
+
+        public final int u;
+        public final int v;
+
+        Face(int u, int v)
+        {
+            this.u = u;
+            this.v = v;
+        }
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/GuiIngame.java b/src/main/java/net/minecraft/client/gui/hud/IngameHud.java
similarity index 88%
rename from src/main/java/net/minecraft/client/gui/GuiIngame.java
rename to src/main/java/net/minecraft/client/gui/hud/IngameHud.java
index 35a761ce0..81ef82248 100644
--- a/src/main/java/net/minecraft/client/gui/GuiIngame.java
+++ b/src/main/java/net/minecraft/client/gui/hud/IngameHud.java
@@ -1,4 +1,4 @@
-package net.minecraft.client.gui;
+package net.minecraft.client.gui.hud;
 
 import static net.minecraft.core.util.helper.Utils.*;
 import static org.lwjgl.opengl.GL11.*;
@@ -9,13 +9,18 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.entity.player.MultiplayerLocalPlayer;
+import net.minecraft.client.gui.ChatScreen;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.HeldItemTooltipElement;
+import net.minecraft.client.gui.PhotoModeScreen;
 import org.lwjgl.opengl.GL11;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.hud.HudComponent;
-import net.minecraft.client.gui.hud.HudComponents;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.gui.hud.component.HudComponent;
+import net.minecraft.client.gui.hud.component.HudComponents;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.Lighting;
 import net.minecraft.client.render.dynamictexture.DynamicTexture;
 import net.minecraft.client.render.entity.ItemEntityRenderer;
@@ -45,10 +50,11 @@ import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.season.Season;
 import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.wind.WindProvider;
+import org.slf4j.Logger;
 
-public class GuiIngame extends Gui
+public class IngameHud extends Gui
 {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static final String[] directions = new String[]{"North", "East", "South", "West"};
 
     public static ItemEntityRenderer itemRenderer = new ItemEntityRenderer();
@@ -60,27 +66,27 @@ public class GuiIngame extends Gui
     private boolean colorString = false;
     public float damageGuiPartialTime;
     float prevVignetteBrightness = 1.0f;
-    protected FontRenderer fontrenderer;
+    protected Font font;
     public int chatScroll = 0;
 
-    public final GuiHeldItemTooltip guiHeldItemTooltip;
+    public final HeldItemTooltipElement heldItemTooltipElement;
 
-    public GuiIngame(Minecraft minecraft)
+    public IngameHud(Minecraft minecraft)
     {
         this.mc = minecraft;
-        this.fontrenderer = mc.fontRenderer;
-        this.guiHeldItemTooltip = new GuiHeldItemTooltip(mc);
+        this.font = mc.font;
+        this.heldItemTooltipElement = new HeldItemTooltipElement(mc);
     }
 
     public void renderGameOverlay(float partialTicks, boolean flag, int mouseX, int mouseY)
     {
-        if (mc.currentScreen instanceof GuiPhotoMode) return;
+        if (mc.currentScreen instanceof PhotoModeScreen) return;
 
         I18n stringtranslate = I18n.getInstance();
         int width = mc.resolution.scaledWidth;
         int height = mc.resolution.scaledHeight;
         int sp = (int) (mc.gameSettings.screenPadding.value * height / 8);
-        FontRenderer fontrenderer = mc.fontRenderer;
+        Font font = mc.font;
         mc.worldRenderer.setupScaledResolution();
 
         GL11.glEnable(3042 /* GL_BLEND */);
@@ -410,12 +416,12 @@ public class GuiIngame extends Gui
                     } else {
                         color = 0xFFFFFF;
                     }
-                    drawString(fontrenderer, "Better than Adventure! ", tsp, tsp + lineHeight * line, color);
-                    drawString(fontrenderer, Global.VERSION, tsp + fontrenderer.getStringWidth("Better than Adventure! "), tsp + lineHeight * line++, 0xffffff);
+                    drawString(font, "Better than Adventure! ", tsp, tsp + lineHeight * line, color);
+                    drawString(font, Global.VERSION, tsp + font.getStringWidth("Better than Adventure! "), tsp + lineHeight * line++, 0xffffff);
                 }
                 if (mc.gameSettings.fpsInOverlay.value)
                 {
-                    drawString(fontrenderer, mc.debugFPS, tsp, tsp + lineHeight * line++, 0xffffff);
+                    drawString(font, mc.debugFPS, tsp, tsp + lineHeight * line++, 0xffffff);
                 }
                 if (compass)
                 {
@@ -423,24 +429,24 @@ public class GuiIngame extends Gui
                     {
                         if (mc.gameSettings.overlayMode.value == 0)
                         {
-                            drawString(fontrenderer, "x: " + floor10(mc.thePlayer.x) + " y: " + floor10(mc.thePlayer.y) + " z: " + floor10(mc.thePlayer.z), tsp, tsp + lineHeight * line++, 0xffffff);
+                            drawString(font, "x: " + floor10(mc.thePlayer.x) + " y: " + floor10(mc.thePlayer.y) + " z: " + floor10(mc.thePlayer.z), tsp, tsp + lineHeight * line++, 0xffffff);
                         }
                         if (mc.gameSettings.overlayMode.value == 1)
                         {
-                            drawString(fontrenderer, "x: " + floor10(mc.thePlayer.x), tsp, tsp + lineHeight * line++, 0xffffff);
-                            drawString(fontrenderer, "y: " + floor10(mc.thePlayer.y), tsp, tsp + lineHeight * line++, 0xffffff);
-                            drawString(fontrenderer, "z: " + floor10(mc.thePlayer.z), tsp, tsp + lineHeight * line++, 0xffffff);
+                            drawString(font, "x: " + floor10(mc.thePlayer.x), tsp, tsp + lineHeight * line++, 0xffffff);
+                            drawString(font, "y: " + floor10(mc.thePlayer.y), tsp, tsp + lineHeight * line++, 0xffffff);
+                            drawString(font, "z: " + floor10(mc.thePlayer.z), tsp, tsp + lineHeight * line++, 0xffffff);
                         }
                         if (mc.gameSettings.overlayMode.value == 2)
                         {
-                            drawString(fontrenderer, "x: " + floor10(mc.thePlayer.x), tsp, tsp + lineHeight * line++, 0xff8080);
-                            drawString(fontrenderer, "y: " + floor10(mc.thePlayer.y), tsp, tsp + lineHeight * line++, 0x80ff80);
-                            drawString(fontrenderer, "z: " + floor10(mc.thePlayer.z), tsp, tsp + lineHeight * line++, 0x8080ff);
+                            drawString(font, "x: " + floor10(mc.thePlayer.x), tsp, tsp + lineHeight * line++, 0xff8080);
+                            drawString(font, "y: " + floor10(mc.thePlayer.y), tsp, tsp + lineHeight * line++, 0x80ff80);
+                            drawString(font, "z: " + floor10(mc.thePlayer.z), tsp, tsp + lineHeight * line++, 0x8080ff);
                         }
                     }
                     if (mc.gameSettings.overlayShowDirection.value)
                     {
-                        drawString(fontrenderer, getFacingDirection(mc.thePlayer), tsp, tsp + lineHeight * line++, 0xffffff);
+                        drawString(font, getFacingDirection(mc.thePlayer), tsp, tsp + lineHeight * line++, 0xffffff);
                     }
                 }
                 if (clock)
@@ -449,12 +455,12 @@ public class GuiIngame extends Gui
                     {
                         if (mc.gameSettings.overlayMode.value == 0)
                         {
-                            this.drawString(fontrenderer, getTimeString() + " Day " + mc.theWorld.getWorldTime() / Global.DAY_LENGTH_TICKS, tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0xffff80 : 0xffffff);
+                            this.drawString(font, getTimeString() + " Day " + mc.theWorld.getWorldTime() / Global.DAY_LENGTH_TICKS, tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0xffff80 : 0xffffff);
                         }
                         if (mc.gameSettings.overlayMode.value > 0)
                         {
-                            this.drawString(fontrenderer, getTimeString(), tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0xffff80 : 0xffffff);
-                            this.drawString(fontrenderer, "Day " + mc.theWorld.getWorldTime() / Global.DAY_LENGTH_TICKS, tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0xffff80 : 0xffffff);
+                            this.drawString(font, getTimeString(), tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0xffff80 : 0xffffff);
+                            this.drawString(font, "Day " + mc.theWorld.getWorldTime() / Global.DAY_LENGTH_TICKS, tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0xffff80 : 0xffffff);
                         }
                     }
                 }
@@ -465,7 +471,7 @@ public class GuiIngame extends Gui
                         Season season = mc.theWorld.getSeasonManager().getCurrentSeason();
                         if (season != null)
                         {
-                            this.drawString(fontrenderer, season.getTranslatedName(), tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0x80ffff : 0xffffff);
+                            this.drawString(font, season.getTranslatedName(), tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0x80ffff : 0xffffff);
                         }
                     }
                     if (mc.gameSettings.overlayShowWeather.value)
@@ -473,7 +479,7 @@ public class GuiIngame extends Gui
                         Weather weather = mc.theWorld.getCurrentWeather();
                         if (weather != null && weather != mc.theWorld.worldType.getDefaultWeather())
                         {
-                            this.drawString(fontrenderer, weather.getTranslatedName(), tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0xff80ff : 0xffffff);
+                            this.drawString(font, weather.getTranslatedName(), tsp, tsp + lineHeight * line++, mc.gameSettings.overlayMode.value == 2 ? 0xff80ff : 0xffffff);
                         }
                     }
 					if(mc.gameSettings.overlayShowBiome.value)
@@ -482,7 +488,7 @@ public class GuiIngame extends Gui
 						int blockY = MathHelper.floor(mc.thePlayer.y);
 						int blockZ = MathHelper.floor(mc.thePlayer.z);
 						String key = mc.theWorld.getBlockBiome(blockX, blockY, blockZ).translationKey;
-						drawString(fontrenderer, stringtranslate.translateKey(key), tsp, tsp + lineHeight * line++, 0xffffff);
+						drawString(font, stringtranslate.translateKey(key), tsp, tsp + lineHeight * line++, 0xffffff);
 					}
                 }
             }
@@ -498,7 +504,7 @@ public class GuiIngame extends Gui
                 {
                     int x = 2 + sp;
                     int y = height - sp - 64 + i * 16;
-                    ItemModelDispatcher.getInstance().getDispatch(stack).renderItemIntoGui(Tessellator.instance, fontrenderer, mc.renderEngine, stack, x, y, 1.0f);
+                    ItemModelDispatcher.getInstance().getDispatch(stack).renderItemIntoGui(Tessellator.instance, font, mc.textureManager, stack, x, y, 1.0f);
 
                     if (stack.isItemStackDamageable())
                     {
@@ -509,7 +515,7 @@ public class GuiIngame extends Gui
 
                         glDisable(GL_BLEND);
                         glDisable(GL_LIGHTING);
-                        fontrenderer.drawStringWithShadow(String.valueOf((stack.getMaxDamage() - stack.getMetadata()) + 1), x + 20, y + 4, i1);
+                        font.drawStringWithShadow(String.valueOf((stack.getMaxDamage() - stack.getMetadata()) + 1), x + 20, y + 4, i1);
                     }
                 }
             }
@@ -532,11 +538,10 @@ public class GuiIngame extends Gui
                 {
                     renderItem = true;
                     float durability = (heldItemStack.getMaxDamage() - heldItemStack.getMetadata()) / (float) heldItemStack.getMaxDamage();
-
-                    int l = (int) (durability * 255);
-                    final int i1 = 255 - l << 16 | l << 8;
+                    
+                    final int color = Color.HSBtoRGB(durability/3F, 1f, 1f);
                     int remainingDurability = (heldItemStack.getMaxDamage() - heldItemStack.getMetadata()) + 1;
-                    fontrenderer.drawStringWithShadow("" + remainingDurability, x + 18, y + 4, i1);
+                    font.drawStringWithShadow("" + remainingDurability, x + 18, y + 4, color);
                 }
                 else
                 {
@@ -555,7 +560,7 @@ public class GuiIngame extends Gui
 
                     if (renderItem)
                     {
-                        fontrenderer.drawStringWithShadow("" + itemCount, x + 18, y + 4, 0xffffff);
+                        font.drawStringWithShadow("" + itemCount, x + 18, y + 4, 0xffffff);
                     }
                 }
 
@@ -565,7 +570,7 @@ public class GuiIngame extends Gui
                     GL11.glDisable(3042 /* GL_BLEND */);
                     GL11.glEnable(32826 /* GL_RESCALE_NORMAL_EXT */);
                     Lighting.enableInventoryLight();
-                    ItemModelDispatcher.getInstance().getDispatch(heldItemStack).renderItemIntoGui(Tessellator.instance, fontrenderer, mc.renderEngine, heldItemStack, x, y, 1.0f);
+                    ItemModelDispatcher.getInstance().getDispatch(heldItemStack).renderItemIntoGui(Tessellator.instance, font, mc.textureManager, heldItemStack, x, y, 1.0f);
                     Lighting.disable();
                 }
             }
@@ -637,7 +642,7 @@ public class GuiIngame extends Gui
 
     private void drawDebugScreenLine(String string, boolean right, int line, int offset)
     {
-        int width = fontrenderer.getStringWidth(string);
+        int width = font.getStringWidth(string);
         int height = debugLineHeight;
         int x = right ? mc.resolution.scaledWidth - width - 2 : 2;
         int y = 3 + line * debugLineHeight + offset;
@@ -653,7 +658,7 @@ public class GuiIngame extends Gui
         glEnable(GL_TEXTURE_2D);
 
 //		fontrenderer.drawStringWithShadow(string, x, y, 0xFFFFFF);
-        fontrenderer.drawString(string, x, y, 0xFFFFFF);
+        font.drawString(string, x, y, 0xFFFFFF);
     }
 
     private void drawDebugScreenLine(String string)
@@ -696,9 +701,9 @@ public class GuiIngame extends Gui
 
         for (Map.Entry<String, String> a1 : players.entrySet())
         {
-            longestNameWidth = java.lang.Math.max(fontrenderer.getStringWidth(a1.getKey()), longestNameWidth);
+            longestNameWidth = java.lang.Math.max(font.getStringWidth(a1.getKey()), longestNameWidth);
 
-            longestScoreWidth = java.lang.Math.max(fontrenderer.getStringWidth(a1.getValue()), longestScoreWidth);
+            longestScoreWidth = java.lang.Math.max(font.getStringWidth(a1.getValue()), longestScoreWidth);
             playerListScoreStrings.add(a1.getValue());
         }
 
@@ -742,11 +747,11 @@ public class GuiIngame extends Gui
             int posX = listX + x * columnWidth + x * innerPadding + outerPadding;
             int posY = listY + y * lineHeight + y * innerPadding + outerPadding;
 
-            int scoreStringWidth = fontrenderer.getStringWidth(a2.getValue());
+            int scoreStringWidth = font.getStringWidth(a2.getValue());
             drawRect(posX - 2, posY - 2, posX + columnWidth + 2, posY + 10, 0xffa5a5a5);
             drawRect(posX - 1, posY - 1, posX + columnWidth + 1, posY + 9, 0xA8080808);
-            fontrenderer.drawStringWithShadow(a2.getKey(), posX, posY, 0xFFFFFF);
-            fontrenderer.drawStringWithShadow(TextFormatting.YELLOW + a2.getValue(), posX + columnWidth - scoreStringWidth, posY, 0xFFFFFF);
+            font.drawStringWithShadow(a2.getKey(), posX, posY, 0xFFFFFF);
+            font.drawStringWithShadow(TextFormatting.YELLOW + a2.getValue(), posX + columnWidth - scoreStringWidth, posY, 0xFFFFFF);
             i++;
         }
     }
@@ -772,7 +777,7 @@ public class GuiIngame extends Gui
                 {
                     k4 = Color.HSBtoRGB(f2 / 50F, 0.7F, 0.6F) & 0xffffff;
                 }
-                fontrenderer.drawString(recordPlaying, -fontrenderer.getStringWidth(recordPlaying) / 2, -4, k4 + (j3 << 24));
+                font.drawString(recordPlaying, -font.getStringWidth(recordPlaying) / 2, -4, k4 + (j3 << 24));
                 GL11.glDisable(3042 /* GL_BLEND */);
                 GL11.glPopMatrix();
             }
@@ -783,7 +788,7 @@ public class GuiIngame extends Gui
     {
         int messagesToShow = 10;
         boolean ignoreFadeout = false;
-        if (mc.currentScreen instanceof GuiChat)
+        if (mc.currentScreen instanceof ChatScreen)
         {
             int acceptableSize = height - 48 - 48;
             messagesToShow = acceptableSize / 9;
@@ -828,7 +833,7 @@ public class GuiIngame extends Gui
                 String s1 = chatMessageList.get(i).message;
                 drawRect(xPad, y - 1 - sp, xPad + 320, y + 8 - sp, alpha / 2 << 24);
                 GL11.glEnable(GL_BLEND);
-                mc.fontRenderer.drawStringWithShadow(s1, xPad, y - sp, 0xFFFFFF + (alpha << 24));
+                mc.font.drawStringWithShadow(s1, xPad, y - sp, 0xFFFFFF + (alpha << 24));
             }
         }
 
@@ -870,7 +875,7 @@ public class GuiIngame extends Gui
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
         GL11.glDisable(3008 /* GL_ALPHA_TEST */);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/misc/pumpkinblur.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/misc/pumpkinblur.png").bind();
         Tessellator tessellator = Tessellator.instance;
         tessellator.startDrawingQuads();
         tessellator.addVertexWithUV(0.0D, ySize, -90D, 0.0D, 1.0D);
@@ -892,7 +897,7 @@ public class GuiIngame extends Gui
         GL11.glDepthMask(false);
         GL11.glBlendFunc(0, 769);
         GL11.glColor4f(prevVignetteBrightness, prevVignetteBrightness, prevVignetteBrightness, 1.0F);
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/misc/vignette.png").bind();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/misc/vignette.png").bind();
         Tessellator tessellator = Tessellator.instance;
         tessellator.startDrawingQuads();
         tessellator.addVertexWithUV(0.0D, ySize, -90D, 0.0D, 1.0D);
@@ -958,14 +963,14 @@ public class GuiIngame extends Gui
 
     public void addChatMessage(String s)
     {
-        System.out.println("[CHAT] " + s);
+        LOGGER.info("[CHAT] {}", s);
         int i;
         TextFormatting activeFormatting = null;
-        while (mc.fontRenderer.getStringWidth(s) > 320)
+        while (mc.font.getStringWidth(s) > 320)
         {
-            for (i = 1; i < s.length() && mc.fontRenderer.getStringWidth(s.substring(0, i + 1)) <= 320; i++) {
+            for (i = 1; i < s.length() && mc.font.getStringWidth(s.substring(0, i + 1)) <= 320; i++) {
                 char c = s.charAt(i - 1);
-                if (c == '\u00a7') {
+                if (c == '§') {
                     char code = s.charAt(i);
                     for (TextFormatting formatting : TextFormatting.FORMATTINGS) {
                         if (formatting.code == code) {
@@ -977,7 +982,7 @@ public class GuiIngame extends Gui
             }
             addChatMessage(s.substring(0, i));
             if (activeFormatting != null) {
-                s = "" + '\u00a7' + activeFormatting.code + s.substring(i);
+                s = "" + '§' + activeFormatting.code + s.substring(i);
             } else {
                 s = s.substring(i);
             }
diff --git a/src/main/java/net/minecraft/client/gui/hud/ArmorBarComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/ArmorBarComponent.java
similarity index 87%
rename from src/main/java/net/minecraft/client/gui/hud/ArmorBarComponent.java
rename to src/main/java/net/minecraft/client/gui/hud/component/ArmorBarComponent.java
index 80905322f..ec4a3fe79 100644
--- a/src/main/java/net/minecraft/client/gui/hud/ArmorBarComponent.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/ArmorBarComponent.java
@@ -1,8 +1,9 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiIngame;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.component.layout.Layout;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import org.lwjgl.opengl.GL11;
@@ -25,7 +26,7 @@ public class ArmorBarComponent
     }
 
     @Override
-    public void render(Minecraft mc, GuiIngame gui, int xSizeScreen, int ySizeScreen, float partialTick) {
+    public void render(Minecraft mc, IngameHud hud, int xSizeScreen, int ySizeScreen, float partialTick) {
         int x = this.getLayout().getComponentX(mc, this, xSizeScreen);
         int y = this.getLayout().getComponentY(mc, this, ySizeScreen);
 
@@ -41,17 +42,17 @@ public class ArmorBarComponent
                 if (i * 2 + 1 < armorValue)
                 {
                     // Full armor icon
-                    gui.drawGuiIcon(xArmor, y, 9, 9, armor_full);
+                    hud.drawGuiIcon(xArmor, y, 9, 9, armor_full);
                 }
                 if (i * 2 + 1 == armorValue)
                 {
                     // Half armor icon
-                    gui.drawGuiIcon(xArmor, y, 9, 9, armor_half);
+                    hud.drawGuiIcon(xArmor, y, 9, 9, armor_half);
                 }
                 if (i * 2 + 1 > armorValue)
                 {
                     // Empty armor icon
-                    gui.drawGuiIcon(xArmor, y, 9, 9, armor_empty);
+                    hud.drawGuiIcon(xArmor, y, 9, 9, armor_empty);
                 }
             }
         }
diff --git a/src/main/java/net/minecraft/client/gui/hud/ComponentAnchor.java b/src/main/java/net/minecraft/client/gui/hud/component/ComponentAnchor.java
similarity index 92%
rename from src/main/java/net/minecraft/client/gui/hud/ComponentAnchor.java
rename to src/main/java/net/minecraft/client/gui/hud/component/ComponentAnchor.java
index e7c5164df..58d47f18c 100644
--- a/src/main/java/net/minecraft/client/gui/hud/ComponentAnchor.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/ComponentAnchor.java
@@ -1,4 +1,4 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
 
 public enum ComponentAnchor {
     TOP_LEFT(0.0F, 0.0F),
diff --git a/src/main/java/net/minecraft/client/gui/hud/CrosshairComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/CrosshairComponent.java
similarity index 83%
rename from src/main/java/net/minecraft/client/gui/hud/CrosshairComponent.java
rename to src/main/java/net/minecraft/client/gui/hud/component/CrosshairComponent.java
index 866703502..f3fd3d68a 100644
--- a/src/main/java/net/minecraft/client/gui/hud/CrosshairComponent.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/CrosshairComponent.java
@@ -1,8 +1,9 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiIngame;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.component.layout.Layout;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import org.lwjgl.opengl.GL11;
 
@@ -18,7 +19,7 @@ public class CrosshairComponent
     }
 
     @Override
-    public void render(Minecraft mc, GuiIngame gui, int xSizeScreen, int ySizeScreen, float partialTick) {
+    public void render(Minecraft mc, IngameHud hud, int xSizeScreen, int ySizeScreen, float partialTick) {
         int x = this.getLayout().getComponentX(mc, this, xSizeScreen);
         int y = this.getLayout().getComponentY(mc, this, ySizeScreen);
 
@@ -28,7 +29,7 @@ public class CrosshairComponent
         // Render crosshair
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_ONE_MINUS_DST_COLOR, GL11.GL_ONE_MINUS_SRC_COLOR);
-        gui.drawGuiIcon(x, y, 15, 15, TextureRegistry.getTexture("minecraft:gui/hud/crosshair"));
+        hud.drawGuiIcon(x, y, 15, 15, TextureRegistry.getTexture("minecraft:gui/hud/crosshair"));
         GL11.glDisable(GL11.GL_BLEND);
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/hud/FireBarComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/FireBarComponent.java
similarity index 85%
rename from src/main/java/net/minecraft/client/gui/hud/FireBarComponent.java
rename to src/main/java/net/minecraft/client/gui/hud/component/FireBarComponent.java
index f9a177ba9..2969466bf 100644
--- a/src/main/java/net/minecraft/client/gui/hud/FireBarComponent.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/FireBarComponent.java
@@ -1,8 +1,9 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiIngame;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.component.layout.Layout;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import org.lwjgl.opengl.GL11;
 
@@ -18,7 +19,7 @@ public class FireBarComponent
     }
 
     @Override
-    public void render(Minecraft mc, GuiIngame gui, int xSizeScreen, int ySizeScreen, float partialTick) {
+    public void render(Minecraft mc, IngameHud hud, int xSizeScreen, int ySizeScreen, float partialTick) {
         int x = this.getLayout().getComponentX(mc, this, xSizeScreen);
         int y = this.getLayout().getComponentY(mc, this, ySizeScreen);
 
@@ -30,7 +31,7 @@ public class FireBarComponent
         int fireBar = (int) Math.min(fire * 20,20);
 
         for (int i = 0; i < fireBar / 2; i++) {
-            gui.drawGuiIcon(x + i * 8, y, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/fire"));
+            hud.drawGuiIcon(x + i * 8, y, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/fire"));
         }
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/hud/HealthBarComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/HealthBarComponent.java
similarity index 87%
rename from src/main/java/net/minecraft/client/gui/hud/HealthBarComponent.java
rename to src/main/java/net/minecraft/client/gui/hud/component/HealthBarComponent.java
index 289690c39..0933e1d16 100644
--- a/src/main/java/net/minecraft/client/gui/hud/HealthBarComponent.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/HealthBarComponent.java
@@ -1,9 +1,9 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiIngame;
-import net.minecraft.client.render.texture.Texture;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.component.layout.Layout;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.item.IceCreamBucketItem;
 import net.minecraft.core.item.FoodItem;
@@ -26,7 +26,7 @@ public class HealthBarComponent
     }
 
     @Override
-    public void render(Minecraft mc, GuiIngame gui, int xSizeScreen, int ySizeScreen, float partialTick) {
+    public void render(Minecraft mc, IngameHud hud, int xSizeScreen, int ySizeScreen, float partialTick) {
         int x = this.getLayout().getComponentX(mc, this, xSizeScreen);
         int y = this.getLayout().getComponentY(mc, this, ySizeScreen);
 
@@ -41,7 +41,7 @@ public class HealthBarComponent
         }
         int health = mc.thePlayer.getHealth();
         int prevHealth = mc.thePlayer.prevHealth;
-        random.setSeed(gui.updateCounter * 0x4c627L);
+        random.setSeed(hud.updateCounter * 0x4c627L);
         boolean isHardcore = mc.thePlayer.getGamemode() == Gamemode.hardcore;
 
         for (int i = 0; i < 10; i++) {
@@ -57,29 +57,29 @@ public class HealthBarComponent
                 yHeart += random.nextInt(2);
             }
 
-            gui.drawGuiIcon(xHeart, yHeart, 9, 9, heartOffset == 0 ? TextureRegistry.getTexture("minecraft:gui/hud/heart/container") : TextureRegistry.getTexture("minecraft:gui/hud/heart/container_blinking"));
+            hud.drawGuiIcon(xHeart, yHeart, 9, 9, heartOffset == 0 ? TextureRegistry.getTexture("minecraft:gui/hud/heart/container") : TextureRegistry.getTexture("minecraft:gui/hud/heart/container_blinking"));
             if (heartsFlash)
             {
                 if (i * 2 + 1 < prevHealth)
                 {
                     // Half flash heart icon
-                    gui.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "full_blinking"));
+                    hud.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "full_blinking"));
                 }
                 if (i * 2 + 1 == prevHealth)
                 {
                     // Full flash heart icon
-                    gui.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "half_blinking"));
+                    hud.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "half_blinking"));
                 }
             }
             if (i * 2 + 1 < health)
             {
                 // Full heart icon
-                gui.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "full"));
+                hud.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "full"));
             }
             if (i * 2 + 1 == health)
             {
                 // Half heart icon
-                gui.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "half"));
+                hud.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "half"));
             }
             if (mc.thePlayer.inventory.getCurrentItem() != null && (mc.thePlayer.inventory.getCurrentItem().getItem() instanceof FoodItem || mc.thePlayer.inventory.getCurrentItem().getItem() instanceof IceCreamBucketItem) && mc.gameSettings.foodHealthRegenOverlay.value)
             {
@@ -97,15 +97,15 @@ public class HealthBarComponent
                 {
                     if (i * 2 + 1 == health)
                     {
-                        gui.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "preview_half_right"));
+                        hud.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "preview_half_right"));
                     }
                     else if (i * 2 + 1 < health + healing)
                     {
-                        gui.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "preview_full"));
+                        hud.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "preview_full"));
                     }
                     else if (i * 2 + 1 == health + healing)
                     {
-                        gui.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "preview_half"));
+                        hud.drawGuiIcon(xHeart, yHeart, 9, 9, TextureRegistry.getTexture("minecraft:gui/hud/heart/" + (isHardcore ? "hardcore_" : "") + "preview_half"));
                     }
                 }
             }
diff --git a/src/main/java/net/minecraft/client/gui/hud/HotbarComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/HotbarComponent.java
similarity index 91%
rename from src/main/java/net/minecraft/client/gui/hud/HotbarComponent.java
rename to src/main/java/net/minecraft/client/gui/hud/component/HotbarComponent.java
index 352a69c55..6b5f56cea 100644
--- a/src/main/java/net/minecraft/client/gui/hud/HotbarComponent.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/HotbarComponent.java
@@ -1,8 +1,9 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiIngame;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.component.layout.Layout;
 import net.minecraft.client.render.Lighting;
 import net.minecraft.client.render.Scissor;
 import net.minecraft.client.render.item.model.ItemModel;
@@ -51,7 +52,7 @@ public class HotbarComponent
     }
 
     @Override
-    public void render(Minecraft mc, GuiIngame gui, int xSizeScreen, int ySizeScreen, float partialTick) {
+    public void render(Minecraft mc, IngameHud hud, int xSizeScreen, int ySizeScreen, float partialTick) {
         int x = this.getLayout().getComponentX(mc, this, xSizeScreen);
         int y = this.getLayout().getComponentY(mc, this, ySizeScreen);
 
@@ -61,14 +62,14 @@ public class HotbarComponent
         GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Reset color
 
         // Render hotbar
-        gui.drawGuiIcon(x + 5, y, 182, 22, TextureRegistry.getTexture("minecraft:gui/hud/hotbar"));
+        hud.drawGuiIcon(x + 5, y, 182, 22, TextureRegistry.getTexture("minecraft:gui/hud/hotbar"));
 
 
         // Render hotbar switcher and dots
         int selectedHotbar = ((inv.hotbarOffset + 27) % 36) / 9;
         IconCoordinate coordinate = TextureRegistry.getTexture("minecraft:gui/hud/hotbar_selector");
-        gui.drawIconTexture(x, y, x + 6, y + 22, 0, 0, 6, 22, coordinate);
-        gui.drawIconTexture(x, y + selectedHotbar * 5, x + 6, y + selectedHotbar * 5 + 5, 6, selectedHotbar * 5, 12, selectedHotbar * 5 + 5, coordinate);
+        hud.drawIconTexture(x, y, x + 6, y + 22, 0, 0, 6, 22, coordinate);
+        hud.drawIconTexture(x, y + selectedHotbar * 5, x + 6, y + selectedHotbar * 5 + 5, 6, selectedHotbar * 5, 12, selectedHotbar * 5 + 5, coordinate);
 
         // Setup items
         GL11.glEnable(GL11.GL_DEPTH_TEST);
@@ -124,9 +125,9 @@ public class HotbarComponent
         GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Reset color
 
         // Render selector
-        gui.drawGuiIcon((x + 4) + (inv.currentItem % 9) * 20, y - 1, 24, 24, TextureRegistry.getTexture("minecraft:gui/hud/hotbar_selection"));
+        hud.drawGuiIcon((x + 4) + (inv.currentItem % 9) * 20, y - 1, 24, 24, TextureRegistry.getTexture("minecraft:gui/hud/hotbar_selection"));
 
-        gui.guiHeldItemTooltip.updateAndRender(mc, x + 187/2, y - 20);
+        hud.heldItemTooltipElement.updateAndRender(mc, x + 187/2, y - 20);
     }
 
     @Override
@@ -183,17 +184,17 @@ public class HotbarComponent
             GL11.glScalef(1.0F / f2, (f2 + 1.0F) / 2.0F, 1.0F);
             GL11.glTranslatef(-(x + 8), -(y + 12), 0.0F);
         }
-        itemModel.renderItemIntoGui(Tessellator.instance, mc.fontRenderer, mc.renderEngine, itemstack, x, y, 1.0f);
+        itemModel.renderItemIntoGui(Tessellator.instance, mc.font, mc.textureManager, itemstack, x, y, 1.0f);
         if (animProgress > 0.0F)
         {
             GL11.glPopMatrix();
         }
-        itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.fontRenderer, mc.renderEngine, itemstack, x, y, 1.0f);
+        itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.font, mc.textureManager, itemstack, x, y, 1.0f);
     }
 
     private void renderItem(Minecraft mc, ItemStack itemStack, int x, int y) {
         ItemModel itemModel = ItemModelDispatcher.getInstance().getDispatch(itemStack.getItem());
-        itemModel.renderItemIntoGui(Tessellator.instance, mc.fontRenderer, mc.renderEngine, itemStack, x, y, 1.0f);
-        itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.fontRenderer, mc.renderEngine, itemStack, x, y, 1.0f);
+        itemModel.renderItemIntoGui(Tessellator.instance, mc.font, mc.textureManager, itemStack, x, y, 1.0f);
+        itemModel.renderItemOverlayIntoGUI(Tessellator.instance, mc.font, mc.textureManager, itemStack, x, y, 1.0f);
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/hud/HudComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/HudComponent.java
similarity index 81%
rename from src/main/java/net/minecraft/client/gui/hud/HudComponent.java
rename to src/main/java/net/minecraft/client/gui/hud/component/HudComponent.java
index 5451fc0ff..e461591ee 100644
--- a/src/main/java/net/minecraft/client/gui/hud/HudComponent.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/HudComponent.java
@@ -1,9 +1,12 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiHudDesigner;
-import net.minecraft.client.gui.GuiIngame;
+import net.minecraft.client.gui.HudDesignerScreen;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.component.layout.AbsoluteLayout;
+import net.minecraft.client.gui.hud.component.layout.Layout;
+import net.minecraft.client.gui.hud.component.layout.SnapLayout;
 
 public abstract class HudComponent {
     private final String key;
@@ -26,12 +29,12 @@ public abstract class HudComponent {
     }
 
     public int getXSize(Minecraft mc) {
-        if (!(mc.currentScreen instanceof GuiHudDesigner) && !isVisible(mc)) return 0;
+        if (!(mc.currentScreen instanceof HudDesignerScreen) && !isVisible(mc)) return 0;
         return xSize;
     }
 
     public int getYSize(Minecraft mc) {
-        if (!(mc.currentScreen instanceof GuiHudDesigner) && !isVisible(mc)) return 0;
+        if (!(mc.currentScreen instanceof HudDesignerScreen) && !isVisible(mc)) return 0;
         return ySize;
     }
 
@@ -47,7 +50,7 @@ public abstract class HudComponent {
         return layout;
     }
 
-    public abstract void render(Minecraft mc, GuiIngame gui, int xSizeScreen, int ySizeScreen, float partialTick);
+    public abstract void render(Minecraft mc, IngameHud hud, int xSizeScreen, int ySizeScreen, float partialTick);
 
     public abstract void renderPreview(Minecraft mc, Gui gui, Layout layout, int xSizeScreen, int ySizeScreen);
 
diff --git a/src/main/java/net/minecraft/client/gui/hud/HudComponents.java b/src/main/java/net/minecraft/client/gui/hud/component/HudComponents.java
similarity index 83%
rename from src/main/java/net/minecraft/client/gui/hud/HudComponents.java
rename to src/main/java/net/minecraft/client/gui/hud/component/HudComponents.java
index 32bbb9f9b..71ec8c3c2 100644
--- a/src/main/java/net/minecraft/client/gui/hud/HudComponents.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/HudComponents.java
@@ -1,19 +1,26 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
+
+import com.mojang.logging.LogUtils;
+import net.minecraft.client.gui.hud.component.layout.AbsoluteLayout;
+import net.minecraft.client.gui.hud.component.layout.SnapLayout;
+import org.slf4j.Logger;
 
 import java.util.ArrayList;
 import java.util.List;
 
 public class HudComponents {
-    public static final HudComponents INSTANCE = new HudComponents();
+    private static final Logger LOGGER = LogUtils.getLogger();
+
     public static String DEFAULT_LAYOUT = null;
+    public static final HudComponents INSTANCE = new HudComponents();
 
     public static HudComponent register(HudComponent component) {
         INSTANCE.components.add(component);
         return component;
     }
-
     private final List<HudComponent> components = new ArrayList<>();
 
+
     private HudComponents() { }
 
     public List<HudComponent> getComponents() {
@@ -43,7 +50,7 @@ public class HudComponents {
             String key = part.substring(0, part.indexOf('{'));
             HudComponent component = getComponent(key);
             if (component == null) {
-                System.out.println("Unknown component: " + key);
+                LOGGER.warn("Unknown component: {}", key);
                 continue;
             }
             String componentSettings = part.substring(part.indexOf('{') + 1, part.lastIndexOf('}'));
@@ -58,4 +65,5 @@ public class HudComponents {
     public static final HudComponent OXYGEN_BAR = register(new OxygenBarComponent("oxygen_bar", new SnapLayout(HEALTH_BAR, ComponentAnchor.TOP_LEFT, ComponentAnchor.BOTTOM_LEFT)));
     public static final HudComponent FIRE_BAR = register(new FireBarComponent("fire_bar", new SnapLayout(OXYGEN_BAR, ComponentAnchor.TOP_LEFT, ComponentAnchor.BOTTOM_LEFT)));
     public static final HudComponent ROTATION_LOCK = register(new RotationLockComponent("rotation_lock", new SnapLayout(CROSSHAIR, ComponentAnchor.CENTER_RIGHT, ComponentAnchor.CENTER_LEFT)));
+    public static final HudComponent SUBTITLES = register(new SubtitleComponent("subtitles_box", 100, 50, new AbsoluteLayout(1.0f, 0.75f, ComponentAnchor.BOTTOM_RIGHT)));
 }
diff --git a/src/main/java/net/minecraft/client/gui/hud/MovableHudComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/MovableHudComponent.java
similarity index 71%
rename from src/main/java/net/minecraft/client/gui/hud/MovableHudComponent.java
rename to src/main/java/net/minecraft/client/gui/hud/component/MovableHudComponent.java
index 35e6d93ad..f22ce9bfa 100644
--- a/src/main/java/net/minecraft/client/gui/hud/MovableHudComponent.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/MovableHudComponent.java
@@ -1,4 +1,6 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
+
+import net.minecraft.client.gui.hud.component.layout.Layout;
 
 public abstract class MovableHudComponent
     extends HudComponent {
diff --git a/src/main/java/net/minecraft/client/gui/hud/OxygenBarComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/OxygenBarComponent.java
similarity index 87%
rename from src/main/java/net/minecraft/client/gui/hud/OxygenBarComponent.java
rename to src/main/java/net/minecraft/client/gui/hud/component/OxygenBarComponent.java
index 1028528ac..cdd55a32f 100644
--- a/src/main/java/net/minecraft/client/gui/hud/OxygenBarComponent.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/OxygenBarComponent.java
@@ -1,8 +1,9 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiIngame;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.component.layout.Layout;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.block.material.Material;
@@ -24,7 +25,7 @@ public class OxygenBarComponent
     }
 
     @Override
-    public void render(Minecraft mc, GuiIngame gui, int xSizeScreen, int ySizeScreen, float partialTick) {
+    public void render(Minecraft mc, IngameHud hud, int xSizeScreen, int ySizeScreen, float partialTick) {
         int x = this.getLayout().getComponentX(mc, this, xSizeScreen);
         int y = this.getLayout().getComponentY(mc, this, ySizeScreen);
 
@@ -38,11 +39,11 @@ public class OxygenBarComponent
         {
             if (i < numBubbles)
             {
-                gui.drawGuiIcon(x + i * 8, y, 9, 9, air);
+                hud.drawGuiIcon(x + i * 8, y, 9, 9, air);
             }
             else
             {
-                gui.drawGuiIcon(x + i * 8, y, 9, 9, air_pop);
+                hud.drawGuiIcon(x + i * 8, y, 9, 9, air_pop);
             }
         }
     }
diff --git a/src/main/java/net/minecraft/client/gui/hud/RotationLockComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/RotationLockComponent.java
similarity index 90%
rename from src/main/java/net/minecraft/client/gui/hud/RotationLockComponent.java
rename to src/main/java/net/minecraft/client/gui/hud/component/RotationLockComponent.java
index 02cc03dd5..e82b1dcbf 100644
--- a/src/main/java/net/minecraft/client/gui/hud/RotationLockComponent.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/RotationLockComponent.java
@@ -1,8 +1,9 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiIngame;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.component.layout.Layout;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.util.helper.Direction;
@@ -20,7 +21,7 @@ public class RotationLockComponent
     }
 
     @Override
-    public void render(Minecraft mc, GuiIngame gui, int xSizeScreen, int ySizeScreen, float partialTick) {
+    public void render(Minecraft mc, IngameHud hud, int xSizeScreen, int ySizeScreen, float partialTick) {
         // Setup rendering
         GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Reset color
         GL11.glDisable(GL11.GL_BLEND);
@@ -78,10 +79,10 @@ public class RotationLockComponent
         }
 
         String[] dirTextures = new String[]{"down", "up", "back", "front", "left", "right"};
-        gui.drawGuiIcon(x, y, 16, 16, TextureRegistry.getTexture("minecraft:gui/hud/rotation/" + prefix + "_" + dirTextures[dir.getId()]));
+        hud.drawGuiIcon(x, y, 16, 16, TextureRegistry.getTexture("minecraft:gui/hud/rotation/" + prefix + "_" + dirTextures[dir.getId()]));
         dir = Direction.getVerticalDirection(player);
         dirTextures = new String[]{"downer", "upper", "back", "front", "left", "right"};
-        gui.drawGuiIcon(x + 16, y + 4, 8, 8, TextureRegistry.getTexture("minecraft:gui/hud/rotation/" + prefix + "_" + dirTextures[dir.getId()]));
+        hud.drawGuiIcon(x + 16, y + 4, 8, 8, TextureRegistry.getTexture("minecraft:gui/hud/rotation/" + prefix + "_" + dirTextures[dir.getId()]));
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/hud/component/SubtitleComponent.java b/src/main/java/net/minecraft/client/gui/hud/component/SubtitleComponent.java
new file mode 100644
index 000000000..aa427a9c0
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/hud/component/SubtitleComponent.java
@@ -0,0 +1,116 @@
+package net.minecraft.client.gui.hud.component;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.hud.IngameHud;
+import net.minecraft.client.gui.hud.component.layout.Layout;
+import net.minecraft.client.gui.subtitles.SubtitleTracker;
+import net.minecraft.client.sound.SoundRepository;
+import org.lwjgl.opengl.GL11;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.lwjgl.opengl.GL11.GL_ALPHA_TEST;
+import static org.lwjgl.opengl.GL11.GL_BLEND;
+import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
+import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
+
+public class SubtitleComponent extends MovableHudComponent{
+    public SubtitleComponent(String key, int xSize, int ySize, Layout layout) {
+        super(key, xSize, ySize, layout);
+    }
+
+    @Override
+    public boolean isVisible(Minecraft mc) {
+        return mc.gameSettings.subtitles.value;
+    }
+
+    @Override
+    public void render(Minecraft mc, IngameHud hud, int xSizeScreen, int ySizeScreen, float partialTick) {
+        drawChat(mc, hud, new ArrayList<>(mc.subtitleTracker.entryMap.values()), xSizeScreen, ySizeScreen, partialTick);
+    }
+
+    @Override
+    public void renderPreview(Minecraft mc, Gui gui, Layout layout, int xSizeScreen, int ySizeScreen) {
+        List<SubtitleTracker.SubtitleEntry> example = new ArrayList<>();
+        example.add(new SubtitleTracker.SubtitleEntry(SoundRepository.SOUNDS.getSoundEvent("mob.wolf.whine"), 0, 0, 0));
+        example.add(new SubtitleTracker.SubtitleEntry(SoundRepository.SOUNDS.getSoundEvent("random.drr"), 0, 0, 0));
+        example.add(new SubtitleTracker.SubtitleEntry(SoundRepository.SOUNDS.getSoundEvent("random.bow"), 0, 0, 0));
+        drawChat(mc, gui, example, xSizeScreen, ySizeScreen, 0);
+    }
+
+    public void drawChat(Minecraft mc, Gui gui, List<SubtitleTracker.SubtitleEntry> subtitleEntries, int xSizeScreen, int ySizeScreen, float partialTick)
+    {
+        int x = this.getLayout().getComponentX(mc, this, xSizeScreen);
+        int y = this.getLayout().getComponentY(mc, this, ySizeScreen);
+        int width = getXSize(mc);
+        int height = getYSize(mc);
+        int xRight = x + width;
+        int yBottom = y + height;
+        int messagesToShow = height/10;
+        boolean ignoreFadeout = false;
+
+        int maxMessageWidth = 0;
+        for (int i = 0; i < subtitleEntries.size() && i < messagesToShow; i++)
+        {
+            SubtitleTracker.SubtitleEntry entry = subtitleEntries.get(i);
+            if (entry.soundEvent == null) {
+                continue;
+            }
+            int msgWidth = mc.font.getStringWidth(entry.soundEvent.getSubtitleTranslated());
+            if (msgWidth > maxMessageWidth) {
+                maxMessageWidth = msgWidth;
+            }
+        }
+        maxMessageWidth += mc.font.getStringWidth("<") + mc.font.getStringWidth(">");
+
+        GL11.glEnable(GL_BLEND);
+        GL11.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        GL11.glDisable(GL_ALPHA_TEST);
+        for (int i = 0; i < subtitleEntries.size() && i < messagesToShow; i++)
+        {
+            SubtitleTracker.SubtitleEntry entry = subtitleEntries.get(i);
+            if (entry.soundEvent == null) {
+                System.err.println("Null sound event in entry map!");
+                continue;
+            }
+            double fadeAmount = entry.getFadeout();
+            fadeAmount = 1.0D - fadeAmount;
+            fadeAmount *= 10D;
+            if (fadeAmount < 0.0D)
+            {
+                fadeAmount = 0.0D;
+            }
+            if (fadeAmount > 1.0D)
+            {
+                fadeAmount = 1.0D;
+            }
+            fadeAmount *= fadeAmount;
+            int alpha = (int) (255D * fadeAmount);
+            if (ignoreFadeout)
+            {
+                alpha = 255;
+            }
+            if (alpha > 0)
+            {
+                byte xPad = 3;
+                int y2 = -i * 9 - 8;
+                String s1 = entry.soundEvent.getSubtitleTranslated();
+                gui.drawRect(xRight - maxMessageWidth - xPad * 2, yBottom + y2 - 1, xRight, yBottom + y2 + 8, alpha / 2 << 24);
+                GL11.glEnable(GL_BLEND);
+                mc.font.drawCenteredString(s1, xRight - (maxMessageWidth) / 2 - xPad, yBottom + y2, 0xFFFFFF + (alpha << 24));
+                if (mc.thePlayer != null) {
+                    double sin = Math.sin(entry.getRelativeAngle(mc.thePlayer) + Math.PI/2);
+                    if (sin > 0.7) {
+                        mc.font.drawString("<", xRight - maxMessageWidth - xPad, yBottom + y2, 0xFFFFFF + (alpha << 24));
+                    } else if (sin < -0.7) {
+                        mc.font.drawString(">", xRight - mc.font.getStringWidth(">") - xPad/2, yBottom + y2, 0xFFFFFF + (alpha << 24));
+                    }
+                }
+            }
+        }
+        GL11.glEnable(GL_ALPHA_TEST);
+        GL11.glDisable(GL_BLEND);
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/hud/AbsoluteLayout.java b/src/main/java/net/minecraft/client/gui/hud/component/layout/AbsoluteLayout.java
similarity index 91%
rename from src/main/java/net/minecraft/client/gui/hud/AbsoluteLayout.java
rename to src/main/java/net/minecraft/client/gui/hud/component/layout/AbsoluteLayout.java
index bb50c372f..21c1a17b0 100644
--- a/src/main/java/net/minecraft/client/gui/hud/AbsoluteLayout.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/layout/AbsoluteLayout.java
@@ -1,6 +1,8 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component.layout;
 
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.hud.component.ComponentAnchor;
+import net.minecraft.client.gui.hud.component.HudComponent;
 
 public class AbsoluteLayout
     extends Layout {
diff --git a/src/main/java/net/minecraft/client/gui/hud/Layout.java b/src/main/java/net/minecraft/client/gui/hud/component/layout/Layout.java
similarity index 77%
rename from src/main/java/net/minecraft/client/gui/hud/Layout.java
rename to src/main/java/net/minecraft/client/gui/hud/component/layout/Layout.java
index 57c5db591..d040060ee 100644
--- a/src/main/java/net/minecraft/client/gui/hud/Layout.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/layout/Layout.java
@@ -1,6 +1,7 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component.layout;
 
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.hud.component.HudComponent;
 
 public abstract class Layout {
     public abstract int getComponentX(Minecraft mc, HudComponent component, int xSizeScreen);
diff --git a/src/main/java/net/minecraft/client/gui/hud/SnapLayout.java b/src/main/java/net/minecraft/client/gui/hud/component/layout/SnapLayout.java
similarity index 91%
rename from src/main/java/net/minecraft/client/gui/hud/SnapLayout.java
rename to src/main/java/net/minecraft/client/gui/hud/component/layout/SnapLayout.java
index dae93b705..f86a493a2 100644
--- a/src/main/java/net/minecraft/client/gui/hud/SnapLayout.java
+++ b/src/main/java/net/minecraft/client/gui/hud/component/layout/SnapLayout.java
@@ -1,6 +1,9 @@
-package net.minecraft.client.gui.hud;
+package net.minecraft.client.gui.hud.component.layout;
 
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.hud.component.ComponentAnchor;
+import net.minecraft.client.gui.hud.component.HudComponent;
+import net.minecraft.client.gui.hud.component.HudComponents;
 
 public class SnapLayout
     extends Layout {
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/GuiModelViewer.java b/src/main/java/net/minecraft/client/gui/modelviewer/ModelViewerScreen.java
similarity index 69%
rename from src/main/java/net/minecraft/client/gui/modelviewer/GuiModelViewer.java
rename to src/main/java/net/minecraft/client/gui/modelviewer/ModelViewerScreen.java
index 15ef85781..388d47ef9 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/GuiModelViewer.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/ModelViewerScreen.java
@@ -1,18 +1,19 @@
 package net.minecraft.client.gui.modelviewer;
 
 import com.b100.utils.ImageUtils;
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiPhotoMode;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.PhotoModeScreen;
 import net.minecraft.client.gui.modelviewer.categories.BlockCategory;
 import net.minecraft.client.gui.modelviewer.categories.EntityCategory;
 import net.minecraft.client.gui.modelviewer.categories.ModelViewerCategory;
 import net.minecraft.client.gui.modelviewer.categories.ParticleCategory;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerSlider;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerTextField;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
+import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
+import net.minecraft.client.gui.modelviewer.elements.ListenerTextFieldElement;
 import net.minecraft.client.gui.modelviewer.elements.IListenerElement;
-import net.minecraft.client.gui.options.GuiOptions;
+import net.minecraft.client.gui.options.OptionsScreen;
 import net.minecraft.client.gui.options.data.OptionsPages;
 import net.minecraft.client.render.BlockEntityRenderDispatcher;
 import net.minecraft.client.render.shader.PhotoModeRenderer;
@@ -30,6 +31,7 @@ import net.minecraft.core.util.helper.Utils;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.GL11;
+import org.slf4j.Logger;
 
 import java.io.File;
 import java.nio.ByteBuffer;
@@ -49,21 +51,22 @@ import static org.lwjgl.opengl.GL11.glGetError;
 import static org.lwjgl.opengl.GL11.glGetTexImage;
 import static org.lwjgl.opengl.GL11.glGetTexLevelParameteri;
 
-public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField.ITextChangeListener {
-    private GuiListenerButton buttonRotateLeft;
-    private GuiListenerButton buttonRotateRight;
-    private GuiListenerButton buttonCenterScreen;
-    private GuiListenerButton buttonTakeScreenshot;
-    private GuiListenerButton buttonOpenScreenshotFolder;
-    private GuiListenerButton buttonExit;
-    private GuiListenerSlider sliderTilt;
-    private GuiListenerButton buttonShaders;
-    private GuiListenerSlider sliderIntensity;
-    public GuiListenerButton buttonPrevEntry;
-    public GuiListenerButton buttonNextEntry;
-    private GuiListenerButton buttonCategory;
-    private GuiListenerButton buttonReloadTextures;
-    private GuiListenerButton buttonTickToggle;
+public class ModelViewerScreen extends PhotoModeScreen implements ListenerTextFieldElement.ITextChangeListener {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private ListenerButtonElement buttonRotateLeft;
+    private ListenerButtonElement buttonRotateRight;
+    private ListenerButtonElement buttonCenterScreen;
+    private ListenerButtonElement buttonTakeScreenshot;
+    private ListenerButtonElement buttonOpenScreenshotFolder;
+    private ListenerButtonElement buttonExit;
+    private ListenerSliderElement sliderTilt;
+    private ListenerButtonElement buttonShaders;
+    private ListenerSliderElement sliderIntensity;
+    public ListenerButtonElement buttonPrevEntry;
+    public ListenerButtonElement buttonNextEntry;
+    private ListenerButtonElement buttonCategory;
+    private ListenerButtonElement buttonReloadTextures;
+    private ListenerButtonElement buttonTickToggle;
     private final ModelViewerCategory entityCategory = new EntityCategory(this);
     private final ModelViewerCategory particleCategory = new ParticleCategory(this);
     private final ModelViewerCategory blockCategory = new BlockCategory(this);
@@ -78,12 +81,12 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
 
     protected boolean tickProgress = true;
     protected boolean rotateToCamera = true;
-    public GuiModelViewer(){
+    public ModelViewerScreen(){
         this.mc = Minecraft.getMinecraft(this);
         mc.thePlayer.absMoveTo(0.5, 64.5, 0.5, 180, 0);
         mc.thePlayer.noPhysics = true;
-        mc.renderEngine.refreshTexturesAndDisplayErrors();
-        mc.renderEngine.updateDynamicTextures(false);
+        mc.textureManager.refreshTexturesAndDisplayErrors();
+        mc.textureManager.updateDynamicTextures(false);
 
         if(Shaders.enableShaders) {
             photoModeRenderer = new PhotoModeRenderer(mc, this);
@@ -106,61 +109,61 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
     @Override
     public void init()
     {
-        controlList.clear();
+        buttons.clear();
         I18n i18n = I18n.getInstance();
 
-        List<GuiButton> leftSideButtons = new ArrayList<>();
+        List<ButtonElement> leftSideButtons = new ArrayList<>();
 
-        buttonExit = new GuiListenerButton(5, 0, height - 20, 20, 20, "X");
+        buttonExit = new ListenerButtonElement(5, 0, height - 20, 20, 20, "X");
         buttonExit.setActionListener(this::exitToMenu);
 
-        buttonRotateLeft = new GuiListenerButton(0, width / 2 - 49 - 2 - 20, height - 20, 20, 20, "<");
+        buttonRotateLeft = new ListenerButtonElement(0, width / 2 - 49 - 2 - 20, height - 20, 20, 20, "<");
         buttonRotateLeft.setActionListener(() -> {
             iRotationGoal += 1;
             iRotationGoal = (int) iRotationGoal;
         });
-        buttonRotateRight = new GuiListenerButton(1, width / 2 + 49 + 2, height - 20, 20, 20, ">");
+        buttonRotateRight = new ListenerButtonElement(1, width / 2 + 49 + 2, height - 20, 20, 20, ">");
         buttonRotateRight.setActionListener(() -> {
             iRotationGoal -= 1;
             iRotationGoal = (int) iRotationGoal;
         });
-        buttonTakeScreenshot = new GuiListenerButton(4, width / 2 - 49, height - 20, 98, 20, i18n.translateKey("gui.photo_mode.button.take_screenshot"));
+        buttonTakeScreenshot = new ListenerButtonElement(4, width / 2 - 49, height - 20, 98, 20, i18n.translateKey("gui.photo_mode.button.take_screenshot"));
         buttonTakeScreenshot.setActionListener(this::screenShot);
 
-        buttonPrevEntry = new GuiListenerButton(10, width / 2 - 49 - 2 - 20, height - 40 - 2, 20, 20, "<");
+        buttonPrevEntry = new ListenerButtonElement(10, width / 2 - 49 - 2 - 20, height - 40 - 2, 20, 20, "<");
         buttonPrevEntry.setActionListener(() -> currentCategory.cycleCategoryEntry(-1));
-        buttonNextEntry = new GuiListenerButton(11, width / 2 + 49 + 2, height - 40 - 2, 20, 20, ">");
+        buttonNextEntry = new ListenerButtonElement(11, width / 2 + 49 + 2, height - 40 - 2, 20, 20, ">");
         buttonNextEntry.setActionListener(() -> currentCategory.cycleCategoryEntry(1));
-        buttonCategory = new GuiListenerButton(12, width / 2 - 49, height - 40 - 2, 98, 20, i18n.translateKey(currentCategory.getCategoryNameKey()));
+        buttonCategory = new ListenerButtonElement(12, width / 2 - 49, height - 40 - 2, 98, 20, i18n.translateKey(currentCategory.getCategoryNameKey()));
         buttonCategory.setActionListener(() -> setCategory(categories.get((categories.indexOf(currentCategory) + 1) % categories.size())));
         buttonCategory.setOnValueChanged(() -> buttonCategory.displayString = i18n.translateKey(currentCategory.getCategoryNameKey()));
 
-        buttonReloadTextures = new GuiListenerButton(12, 21, height - 20, 98, 20, i18n.translateKey("gui.model_viewer.button.reload_textures"));
-        buttonReloadTextures.setActionListener(() -> mc.renderEngine.refreshTexturesAndDisplayErrors());
-        buttonOpenScreenshotFolder = (GuiListenerButton) new GuiListenerButton(30, buttonReloadTextures.getWidth() + buttonReloadTextures.getX() + 1, buttonReloadTextures.getY(), 20, 20, "")
+        buttonReloadTextures = new ListenerButtonElement(12, 21, height - 20, 98, 20, i18n.translateKey("gui.model_viewer.button.reload_textures"));
+        buttonReloadTextures.setActionListener(() -> mc.textureManager.refreshTexturesAndDisplayErrors());
+        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(() -> Utils.openDirectory(new File(mc.getMinecraftDir(), "")));
 
-        buttonCenterScreen = new GuiListenerButton(10, 0, 0, 120, 20, i18n.translateKey("gui.photo_mode.button.center_camera"));
+        buttonCenterScreen = new ListenerButtonElement(10, 0, 0, 120, 20, i18n.translateKey("gui.photo_mode.button.center_camera"));
         buttonCenterScreen.setActionListener(() -> {
             iPanXGoal = 0;
             iPanYGoal = 0;
         });
 
-        buttonTickToggle = new GuiListenerButton(13, width - 120, 0, 99, 20, i18n.translateKeyAndFormat("gui.model_viewer.button.tickprogress", tickProgress));
+        buttonTickToggle = new ListenerButtonElement(13, width - 120, 0, 99, 20, i18n.translateKeyAndFormat("gui.model_viewer.button.tickprogress", tickProgress));
         buttonTickToggle.setActionListener(() -> tickProgress = !tickProgress);
         buttonTickToggle.setOnValueChanged(() -> buttonTickToggle.displayString = i18n.translateKeyAndFormat("gui.model_viewer.button.tickprogress", tickProgress));
 
-        GuiListenerButton cameraRotateButton = new GuiListenerButton(-1, width - 120, 0, 120, 20, i18n.translateKeyAndFormat("gui.model_viewer.button.rotate", rotateToCamera));
+        ListenerButtonElement cameraRotateButton = new ListenerButtonElement(-1, width - 120, 0, 120, 20, i18n.translateKeyAndFormat("gui.model_viewer.button.rotate", rotateToCamera));
         cameraRotateButton.setActionListener(() -> {
             rotateToCamera = !rotateToCamera;
             cameraRotateButton.displayString = i18n.translateKeyAndFormat("gui.model_viewer.button.rotate", rotateToCamera);
         });
 
-        GuiListenerButton buttonManualTick = new GuiListenerButton(14, width - 21, 0, 20, 20, "+");
+        ListenerButtonElement buttonManualTick = new ListenerButtonElement(14, width - 21, 0, 20, 20, "+");
         buttonManualTick.setActionListener(this::entryTick);
 
-        sliderTilt = new GuiListenerSlider(7, 0, 0, 120, 20, i18n.translateKey("gui.photo_mode.button.tilt.default"), iTiltGoal / 90f);
+        sliderTilt = new ListenerSliderElement(7, 0, 0, 120, 20, i18n.translateKey("gui.photo_mode.button.tilt.default"), iTiltGoal / 90f);
         sliderTilt.setOnValueChanged(() ->{
             // Update tilt slider
             String tilt = i18n.translateKey("gui.photo_mode.button.tilt.default");
@@ -175,7 +178,7 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
             }
         });
         if(Shaders.enableShaders) {
-            buttonShaders = new GuiListenerButton(8, 0, 0, 120, 20, i18n.translateKeyAndFormat("gui.photo_mode.button.shader", i18n.translateKey("gui.photo_mode.button.shader.none")));
+            buttonShaders = new ListenerButtonElement(8, 0, 0, 120, 20, i18n.translateKeyAndFormat("gui.photo_mode.button.shader", i18n.translateKey("gui.photo_mode.button.shader.none")));
             buttonShaders.setActionListener(() -> {
                 boolean ctrl = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL);
                 if (ctrl)
@@ -194,7 +197,7 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
                 activeShader = activeShader.toUpperCase(Locale.ROOT);
                 buttonShaders.displayString = i18n.translateKeyAndFormat("gui.photo_mode.button.shader", activeShader);
             });
-            sliderIntensity = new GuiListenerSlider(9, 0, 0, 120, 20, i18n.translateKeyAndFormat("gui.photo_mode.button.intensity", (int)(intensityValue * 100) + "%"), intensityValue);
+            sliderIntensity = new ListenerSliderElement(9, 0, 0, 120, 20, i18n.translateKeyAndFormat("gui.photo_mode.button.intensity", (int)(intensityValue * 100) + "%"), intensityValue);
             sliderIntensity.setOnValueChanged(() ->{
                 // Update intensity slider
                 sliderIntensity.displayString = i18n.translateKeyAndFormat("gui.photo_mode.button.intensity", (int)(sliderIntensity.sliderValue * 100) + "%");
@@ -212,19 +215,19 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
             mc.setRenderer(photoModeRenderer);
         }
 
-        controlList.add(cameraRotateButton);
-        controlList.add(buttonTickToggle);
+        buttons.add(cameraRotateButton);
+        buttons.add(buttonTickToggle);
 
         int i=0;
-        List<GuiButton> _buttons = new ArrayList<>(controlList);
-        for(GuiButton button : _buttons) {
+        List<ButtonElement> _buttons = new ArrayList<>(buttons);
+        for(ButtonElement button : _buttons) {
             button.yPosition = i++ * 21;
         }
 
-        controlList.add(buttonManualTick);
+        buttons.add(buttonManualTick);
         buttonManualTick.yPosition = buttonTickToggle.yPosition;
 
-        currentCategory.addContextButtons(controlList);
+        currentCategory.addContextButtons(buttons);
 
         leftSideButtons.add(buttonCenterScreen);
         leftSideButtons.add(sliderTilt);
@@ -235,13 +238,13 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
         }
 
         int j = 0;
-        for (GuiButton button: leftSideButtons){
+        for (ButtonElement button: leftSideButtons){
             button.yPosition = j++ * 21;
         }
 
-        controlList.addAll(leftSideButtons);
+        buttons.addAll(leftSideButtons);
 
-        GuiListenerTextField rField = new GuiListenerTextField(this, fontRenderer, 0, j++ * 21, 40, 20, String.valueOf(bgRed), "Red");
+        ListenerTextFieldElement rField = new ListenerTextFieldElement(this, font, 0, j++ * 21, 40, 20, String.valueOf(bgRed), "Red");
         rField.setPrefaceText("R: ");
         rField.setKeyListener(key -> {
             try {
@@ -254,7 +257,7 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
                 bgRed = defaultRed;
             }
         });
-        GuiListenerTextField gField = new GuiListenerTextField(this, fontRenderer, 40, rField.yPosition, 40, 20, String.valueOf(bgGreen), "Green");
+        ListenerTextFieldElement gField = new ListenerTextFieldElement(this, font, 40, rField.yPosition, 40, 20, String.valueOf(bgGreen), "Green");
         gField.setPrefaceText("G: ");
         gField.setKeyListener(key -> {
             try {
@@ -267,7 +270,7 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
                 bgGreen = defaultGreen;
             }
         });
-        GuiListenerTextField bField = new GuiListenerTextField(this, fontRenderer, 80, rField.yPosition, 40, 20, String.valueOf(bgBlue), "Blue");
+        ListenerTextFieldElement bField = new ListenerTextFieldElement(this, font, 80, rField.yPosition, 40, 20, String.valueOf(bgBlue), "Blue");
         bField.setPrefaceText("B: ");
         bField.setKeyListener(key -> {
             try {
@@ -281,19 +284,19 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
             }
         });
 
-        controlList.add(rField);
-        controlList.add(gField);
-        controlList.add(bField);
-
-        controlList.add(buttonRotateLeft);
-        controlList.add(buttonRotateRight);
-        controlList.add(buttonTakeScreenshot);
-        controlList.add(buttonOpenScreenshotFolder);
-        controlList.add(buttonPrevEntry);
-        controlList.add(buttonNextEntry);
-        controlList.add(buttonCategory);
-        controlList.add(buttonReloadTextures);
-        controlList.add(buttonExit);
+        buttons.add(rField);
+        buttons.add(gField);
+        buttons.add(bField);
+
+        buttons.add(buttonRotateLeft);
+        buttons.add(buttonRotateRight);
+        buttons.add(buttonTakeScreenshot);
+        buttons.add(buttonOpenScreenshotFolder);
+        buttons.add(buttonPrevEntry);
+        buttons.add(buttonNextEntry);
+        buttons.add(buttonCategory);
+        buttons.add(buttonReloadTextures);
+        buttons.add(buttonExit);
     }
     private void setCategory(ModelViewerCategory category){
         if (currentCategory != null){
@@ -313,7 +316,7 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
         return id;
     }
     @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick)
+    public void render(int xm, int ym, float partialTick)
     {
         GL11.glViewport(0, 0, mc.resolution.width, mc.resolution.height);
         GL11.glMatrixMode(GL11.GL_PROJECTION);
@@ -371,34 +374,34 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
 
         buttonCenterScreen.enabled = (iPanX != 0 || iPanY != 0) && !(iPanXGoal == 0 && iPanYGoal == 0);
 
-        List<GuiButton> _buttons = new ArrayList<>(controlList);
-        for (GuiButton guibutton : _buttons) {
-            guibutton.drawButton(mc, mouseX, mouseY);
+        List<ButtonElement> _buttons = new ArrayList<>(buttons);
+        for (ButtonElement button : _buttons) {
+            button.drawButton(mc, xm, ym);
         }
 
         scroll(Mouse.getDWheel());
 
         BlockEntityRenderDispatcher.instance.renderTileEntity(Tessellator.instance, new BlockEntity(), -0.5D, -0.75D, -0.5D, partialTick);
 
-        drawStringCentered(fontRenderer, currentCategory.getCurrentDisplayInfo(I18n.getInstance()), width/2, 1, 0xffffff);
+        drawStringCentered(font, currentCategory.getCurrentDisplayInfo(I18n.getInstance()), width/2, 1, 0xffffff);
     }
     @Override
-    public void keyTyped(char c, int key, int mouseX, int mouseY)
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
     {
-        if (key == Keyboard.KEY_ESCAPE) {
+        if (eventKey == Keyboard.KEY_ESCAPE) {
             exitToMenu();
         }
-        List<GuiButton> _buttons = new ArrayList<>(controlList);
-        for (GuiButton button : _buttons){
-            if (button instanceof IListenerElement && button.isHovered(mouseX, mouseY)){
-                ((IListenerElement) button).onKeyTyped(c, key);
+        List<ButtonElement> _buttons = new ArrayList<>(buttons);
+        for (ButtonElement button : _buttons){
+            if (button instanceof IListenerElement && button.isHovered(mx, my)){
+                ((IListenerElement<?>) button).onKeyTyped(eventCharacter, eventKey);
             }
         }
     }
     private void exitToMenu(){
         currentCategory.onClose();
         mc.changeWorld(null);
-        mc.displayGuiScreen(new GuiOptions(null, OptionsPages.DEBUG));
+        mc.displayScreen(new OptionsScreen(null, OptionsPages.DEBUG));
     }
     public static int cycleBlockId(int id, int idOff){
         int id2 = (id + Block.blocksList.length + idOff) % Block.blocksList.length;
@@ -408,7 +411,7 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
         return id2;
     }
     @Override
-    public void onClosed() {
+    public void removed() {
         if(Shaders.enableShaders) {
             mc.setRenderer(previousRenderer);
         }
@@ -418,10 +421,10 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
     public void tick()
     {
         super.tick();
-        List<GuiButton> _buttons = new ArrayList<>(controlList);
-        for (GuiButton button : _buttons){
-            if (button instanceof GuiListenerButton){
-                ((GuiListenerButton) button).tick();
+        List<ButtonElement> _buttons = new ArrayList<>(buttons);
+        for (ButtonElement button : _buttons){
+            if (button instanceof ListenerButtonElement){
+                ((ListenerButtonElement) button).tick();
             }
         }
         if (tickProgress){
@@ -430,20 +433,20 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
         Minecraft.doPartialTick = tickProgress;
     }
     private void entryTick(){
-        mc.renderEngine.updateDynamicTextures(false);
-        mc.effectRenderer.updateEffects();
+        mc.textureManager.updateDynamicTextures(false);
+        mc.particleEngine.tick();
         currentCategory.onTick();
         // TODO this fixes world time based animation, but also ticks things like wind and im not certain on the best way to set wind direction arbitrarily right now
 //        mc.theWorld.getLevelData().setWorldTime(mc.theWorld.getWorldTime() + 1);
     }
     @Override
-    protected void buttonPressed(GuiButton button) {
+    protected void buttonClicked(ButtonElement button) {
         // Overrides the regular GuiPhotomode's method
     }
 
     public long timeLastKeyPressed = System.currentTimeMillis();
     @Override
-    public void textChanged(GuiListenerTextField textField) {
+    public void textChanged(ListenerTextFieldElement textField) {
         timeLastKeyPressed = System.currentTimeMillis();
     }
     public float[] getBackgroundFogColor(){
@@ -453,6 +456,7 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
     public void screenShot(){
         try {
             File screenshotsDir = new File(mc.getMinecraftDir(), "screenshots");
+            //noinspection ResultOfMethodCallIgnored
             screenshotsDir.mkdir();
             Texture texture = ((ShadersRenderer)mc.renderer).getWorldFramebufferTex();
             texture.bind();
@@ -477,10 +481,10 @@ public class GuiModelViewer extends GuiPhotoMode implements GuiListenerTextField
                 ImageUtils.saveExternalImage(Textures.getImage(buffer, w, h, true, true), outPut);
 
             }else {
-                System.out.println("Cannot get pixel data");
+                LOGGER.warn("Cannot get pixel data for screenshot!");
             }
         } catch (Exception e){
-            e.printStackTrace();
+            LOGGER.error("Exception while trying to take Model Viewer ScreenShot", e);
         }
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/BlockCategory.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/BlockCategory.java
index 171038428..f35573bcb 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/BlockCategory.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/BlockCategory.java
@@ -1,13 +1,13 @@
 package net.minecraft.client.gui.modelviewer.categories;
 
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
 import net.minecraft.client.gui.modelviewer.categories.entries.block.BasicBlockEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.block.BlockEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.block.JarEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.block.MobSpawnerEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.block.SignEntry;
-import net.minecraft.client.gui.modelviewer.elements.GuiTextCycle;
+import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.ItemEntity;
@@ -22,9 +22,9 @@ import java.util.List;
 
 public class BlockCategory extends ModelViewerCategory {
     public HashMap<Block, BlockEntry> entryHashMap = new HashMap<>();
-    public GuiTextCycle<Integer> blockIdTextField;
-    public GuiTextCycle<Integer> blockMetaTextField;
-    public BlockCategory(GuiModelViewer modelViewer) {
+    public TextCycleElement<Integer> blockIdTextField;
+    public TextCycleElement<Integer> blockMetaTextField;
+    public BlockCategory(ModelViewerScreen modelViewer) {
         super(modelViewer);
         createEntries();
     }
@@ -59,8 +59,8 @@ public class BlockCategory extends ModelViewerCategory {
     }
 
     @Override
-    public void addContextButtons(List<GuiButton> buttonList) {
-        GuiButton lastButton = buttonList.get(buttonList.size()-1);
+    public void addContextButtons(List<ButtonElement> buttonList) {
+        ButtonElement lastButton = buttonList.get(buttonList.size()-1);
 
         modelViewer.buttonNextEntry.enabled = false;
         modelViewer.buttonPrevEntry.enabled = false;
@@ -69,10 +69,10 @@ public class BlockCategory extends ModelViewerCategory {
         if (blockIdTextField != null){
             wasFocused = blockIdTextField.textField.isFocused;
         }
-        blockIdTextField = new GuiTextCycle<Integer>(modelViewer, mc.fontRenderer, modelViewer.width - 120, lastButton.yPosition + 21, 120, 20, DisplayChunk.displayBlockId) {
+        blockIdTextField = new TextCycleElement<Integer>(modelViewer, mc.font, modelViewer.width - 120, lastButton.yPosition + 21, 120, 20, DisplayChunk.displayBlockId) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
-                return GuiModelViewer.cycleBlockId(current, offset);
+                return ModelViewerScreen.cycleBlockId(current, offset);
             }
 
             @Override
@@ -102,7 +102,7 @@ public class BlockCategory extends ModelViewerCategory {
         if (blockMetaTextField != null){
             wasFocused = blockMetaTextField.textField.isFocused;
         }
-        blockMetaTextField = new GuiTextCycle<Integer>(modelViewer, mc.fontRenderer, modelViewer.width - 120, blockIdTextField.yPosition + 21, 120, 20, 0) {
+        blockMetaTextField = new TextCycleElement<Integer>(modelViewer, mc.font, modelViewer.width - 120, blockIdTextField.yPosition + 21, 120, 20, 0) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
                 return (current + offset) & 0xFF;
@@ -134,9 +134,9 @@ public class BlockCategory extends ModelViewerCategory {
         BlockEntry entry = entryHashMap.get(Block.getBlock(DisplayChunk.displayBlockId));
 
         if (entry != null){
-            List<GuiButton> list = entry.getEntryButtons(mc, modelViewer, mc.theWorld, DisplayChunk.displayBlockMeta);
+            List<ButtonElement> list = entry.getEntryButtons(mc, modelViewer, mc.theWorld, DisplayChunk.displayBlockMeta);
             if (list != null){
-                for (GuiButton button : list) {
+                for (ButtonElement button : list) {
                     button.setX(button.getX() + xPos);
                     button.setY(button.getY() + yPos);
                 }
@@ -195,7 +195,7 @@ public class BlockCategory extends ModelViewerCategory {
         if (_id != id){
             modelViewer.init();
         }
-        mc.effectRenderer.clearEffects(mc.theWorld);
+        mc.particleEngine.setWorld(mc.theWorld);
         mc.renderGlobal.loadRenderers();
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/EntityCategory.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/EntityCategory.java
index eb1600c4f..92f79c0eb 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/EntityCategory.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/EntityCategory.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui.modelviewer.categories;
 
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
 import net.minecraft.client.gui.modelviewer.categories.entries.entity.DispatcherEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.entity.EntityArmoredZombieEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.entity.EntityBoatEntry;
@@ -16,8 +16,8 @@ import net.minecraft.client.gui.modelviewer.categories.entries.entity.EntityShee
 import net.minecraft.client.gui.modelviewer.categories.entries.entity.EntitySlimeEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.entity.EntityTNTEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.entity.EntityWolfEntry;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerTextField;
-import net.minecraft.client.gui.modelviewer.elements.GuiTextCycle;
+import net.minecraft.client.gui.modelviewer.elements.ListenerTextFieldElement;
+import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityDispatcher;
 import net.minecraft.core.entity.Mob;
@@ -33,11 +33,11 @@ import java.util.List;
 public class EntityCategory extends ModelViewerCategory{
     public HashMap<Class<? extends Entity>, EntityEntry<?>> entryMap = new HashMap<>();
     public List<EntityEntry<?>> entryList = new ArrayList<>();
-    public GuiListenerTextField entityName;
-    public GuiTextCycle<Integer> entityVariant;
+    public ListenerTextFieldElement entityName;
+    public TextCycleElement<Integer> entityVariant;
     public EntityEntry<?> currentEntry = EntityEntry.blankEntry;
     public Entity displayEntity;
-    public EntityCategory(GuiModelViewer modelViewer) {
+    public EntityCategory(ModelViewerScreen modelViewer) {
         super(modelViewer);
         createEntries();
     }
@@ -87,11 +87,11 @@ public class EntityCategory extends ModelViewerCategory{
     }
 
     @Override
-    public void addContextButtons(List<GuiButton> buttonList) {
-        GuiButton lastButton = buttonList.get(buttonList.size()-1);
+    public void addContextButtons(List<ButtonElement> buttonList) {
+        ButtonElement lastButton = buttonList.get(buttonList.size()-1);
         boolean isLiving = displayEntity instanceof Mob;
         if (isLiving){
-            entityVariant = new GuiTextCycle<Integer>(modelViewer, mc.fontRenderer, modelViewer.width - 120, lastButton.yPosition + 21, 120, 20, 0) {
+            entityVariant = new TextCycleElement<Integer>(modelViewer, mc.font, modelViewer.width - 120, lastButton.yPosition + 21, 120, 20, 0) {
                 @Override
                 public Integer cycleElement(Integer current, int offset) {
                     return (current + offset) & 0xFF;
@@ -116,7 +116,7 @@ public class EntityCategory extends ModelViewerCategory{
             entityVariant.textField.setPrefaceText("Variant: ");
             buttonList.add(entityVariant);
 
-            entityName = new GuiListenerTextField(modelViewer, mc.fontRenderer, modelViewer.width - 120, entityVariant.yPosition + 21, 120, 20, "", "Nickname");
+            entityName = new ListenerTextFieldElement(modelViewer, mc.font, modelViewer.width - 120, entityVariant.yPosition + 21, 120, 20, "", "Nickname");
             entityName.setTextChangeListener(modelViewer);
             buttonList.add(entityName);
         }
@@ -125,9 +125,9 @@ public class EntityCategory extends ModelViewerCategory{
         int xPos = modelViewer.width;
         int yPos = lastButton.getY() + lastButton.getHeight() + 1;
 
-        List<GuiButton> entryButtons = getEntry(displayEntity).getEntryButtons(mc, modelViewer, displayEntity);
+        List<ButtonElement> entryButtons = getEntry(displayEntity).getEntryButtons(mc, modelViewer, displayEntity);
         if (entryButtons != null){
-            for (GuiButton button : entryButtons) {
+            for (ButtonElement button : entryButtons) {
                 button.setX(button.getX() + xPos);
                 button.setY(button.getY() + yPos);
             }
@@ -190,7 +190,7 @@ public class EntityCategory extends ModelViewerCategory{
                 ((Mob) displayEntity).setSkinVariant(0);
             }
         }
-        mc.effectRenderer.clearEffects(mc.theWorld);
+        mc.particleEngine.setWorld(mc.theWorld);
         modelViewer.init();
     }
     public void removeDisplayEntity(){
@@ -198,6 +198,6 @@ public class EntityCategory extends ModelViewerCategory{
             displayEntity.remove();
             mc.theWorld.loadedEntityList.remove(displayEntity);
         }
-        mc.effectRenderer.clearEffects(mc.theWorld);
+        mc.particleEngine.setWorld(mc.theWorld);
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/ModelViewerCategory.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/ModelViewerCategory.java
index 821e75e33..92c1f75fe 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/ModelViewerCategory.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/ModelViewerCategory.java
@@ -1,22 +1,22 @@
 package net.minecraft.client.gui.modelviewer.categories;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
 import net.minecraft.core.lang.I18n;
 
 import java.util.List;
 
 public abstract class ModelViewerCategory {
-    protected final GuiModelViewer modelViewer;
+    protected final ModelViewerScreen modelViewer;
     protected final Minecraft mc;
-    public ModelViewerCategory(GuiModelViewer modelViewer){
+    public ModelViewerCategory(ModelViewerScreen modelViewer){
         this.modelViewer = modelViewer;
         this.mc = Minecraft.getMinecraft(this);
     }
     public abstract String getCategoryNameKey();
     public abstract String getCurrentDisplayInfo(I18n translator);
-    public abstract void addContextButtons(List<GuiButton> buttonList);
+    public abstract void addContextButtons(List<ButtonElement> buttonList);
     public abstract void cycleCategoryEntry(int offset);
     public abstract void onOpen();
     public abstract void onClose();
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/ParticleCategory.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/ParticleCategory.java
index 4a2a5e530..5d9d2fc1e 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/ParticleCategory.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/ParticleCategory.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.modelviewer.categories;
 
 import net.minecraft.client.entity.particle.ParticleDispatcher;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
 import net.minecraft.client.gui.modelviewer.categories.entries.particle.BlockFXEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.particle.BubbleFXEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.particle.GenericFXEntry;
@@ -11,7 +11,7 @@ import net.minecraft.client.gui.modelviewer.categories.entries.particle.LeafFXEn
 import net.minecraft.client.gui.modelviewer.categories.entries.particle.NoteFXEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.particle.ParticleEntry;
 import net.minecraft.client.gui.modelviewer.categories.entries.particle.RedDustFXEntry;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerSlider;
+import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
 import net.minecraft.core.lang.I18n;
 
 import java.util.ArrayList;
@@ -26,7 +26,7 @@ public class ParticleCategory extends ModelViewerCategory{
     public double spawnRadius = 0;
     public ParticleEntry currentEntry;
 
-    public ParticleCategory(GuiModelViewer modelViewer) {
+    public ParticleCategory(ModelViewerScreen modelViewer) {
         super(modelViewer);
         initEntries();
         entriesList = new ArrayList<>(entryMap.values());
@@ -64,9 +64,9 @@ public class ParticleCategory extends ModelViewerCategory{
     }
 
     @Override
-    public void addContextButtons(List<GuiButton> buttonList) {
-        GuiButton lastButton = buttonList.get(buttonList.size()-1);
-        GuiListenerSlider radiusSlider = new GuiListenerSlider(-1, modelViewer.width - 120, lastButton.yPosition + 21, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.particle.radius.slider", ((int)(spawnRadius * 100))/100f), (float) spawnRadius);
+    public void addContextButtons(List<ButtonElement> buttonList) {
+        ButtonElement lastButton = buttonList.get(buttonList.size()-1);
+        ListenerSliderElement radiusSlider = new ListenerSliderElement(-1, modelViewer.width - 120, lastButton.yPosition + 21, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.particle.radius.slider", ((int)(spawnRadius * 100))/100f), (float) spawnRadius);
         radiusSlider.setOnValueChanged(() ->{
             spawnRadius = radiusSlider.sliderValue;
             radiusSlider.displayString = I18n.getInstance().translateKeyAndFormat("model.category.particle.radius.slider", ((int)(spawnRadius * 100))/100f);
@@ -76,9 +76,9 @@ public class ParticleCategory extends ModelViewerCategory{
         int xPos = modelViewer.width;
         int yPos = radiusSlider.getY() + radiusSlider.getHeight() + 1;
 
-        List<GuiButton> buttons = currentEntry.getEntryButtons(mc, modelViewer);
+        List<ButtonElement> buttons = currentEntry.getEntryButtons(mc, modelViewer);
         if (buttons != null){
-            for (GuiButton button: buttons){
+            for (ButtonElement button: buttons){
                 button.setX(button.getX() + xPos);
                 button.setY(button.getY() + yPos);
             }
@@ -89,7 +89,7 @@ public class ParticleCategory extends ModelViewerCategory{
     @Override
     public void cycleCategoryEntry(int offset) {
         setCurrentEntry(entriesList.get((entriesList.indexOf(currentEntry) + entriesList.size() + offset) % entriesList.size()));
-        mc.effectRenderer.clearEffects(mc.theWorld);
+        mc.particleEngine.setWorld(mc.theWorld);
         modelViewer.init();
     }
 
@@ -101,7 +101,7 @@ public class ParticleCategory extends ModelViewerCategory{
 
     @Override
     public void onClose() {
-        mc.effectRenderer.clearEffects(mc.theWorld);
+        mc.particleEngine.setWorld(mc.theWorld);
         currentEntry.onClose();
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BasicBlockEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BasicBlockEntry.java
index 056256d7a..a7244732d 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BasicBlockEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BasicBlockEntry.java
@@ -1,10 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.block;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
 import java.util.List;
@@ -20,7 +19,7 @@ public class BasicBlockEntry extends BlockEntry{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, World world, int meta) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, World world, int meta) {
         return null;
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntry.java
index 765800e1f..cce7e9a8c 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/BlockEntry.java
@@ -1,10 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.block;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
 import net.minecraft.core.world.World;
 
 import java.util.List;
@@ -16,7 +15,7 @@ public abstract class BlockEntry {
     }
 
     public abstract void onTick(World world, int meta);
-    public abstract List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, World world, int meta);
+    public abstract List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, World world, int meta);
     public abstract void onClose(World world, int meta);
     public abstract void onOpen(World world, int meta);
 }
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/JarEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/JarEntry.java
index 9a20b985f..567fc8e79 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/JarEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/JarEntry.java
@@ -1,10 +1,10 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.block;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
-import net.minecraft.client.gui.modelviewer.elements.GuiTextCycle;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
+import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.FlowerJarBlockEntity;
@@ -26,11 +26,11 @@ public class JarEntry extends BlockEntry{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, World world, int meta) {
-        GuiTextCycle<Integer> jarCycle = new GuiTextCycle<Integer>(parentScreen, mc.fontRenderer, - 120, 0, 120, 20, 0) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, World world, int meta) {
+        TextCycleElement<Integer> jarCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, 0, 120, 20, 0) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
-                return GuiModelViewer.cycleBlockId(current, offset);
+                return ModelViewerScreen.cycleBlockId(current, offset);
             }
 
             @Override
@@ -53,7 +53,7 @@ public class JarEntry extends BlockEntry{
         jarCycle.textField.setPlaceholder("Jar ID");
         jarCycle.setOnValueChanged(() -> ((FlowerJarBlockEntity)DisplayChunk.displayBlockEntity).flowerInPot = jarCycle.getCurrentElement());
 
-        return new ArrayList<GuiButton>(){{add(jarCycle);}};
+        return new ArrayList<ButtonElement>(){{add(jarCycle);}};
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/MobSpawnerEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/MobSpawnerEntry.java
index a88e0de49..fa872f3e8 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/MobSpawnerEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/MobSpawnerEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.block;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListSelectorButton;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListSelectorButtonElement;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.MobSpawnerBlockEntity;
 import net.minecraft.core.entity.EntityDispatcher;
@@ -36,17 +36,17 @@ public class MobSpawnerEntry extends BlockEntry{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, World world, int meta) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, World world, int meta) {
         List<String> ids = new ArrayList<>(EntityDispatcher.keyToClassMap.keySet());
         ids.remove("mob");
-        GuiListSelectorButton<String> dispatcherIds = new GuiListSelectorButton<String>(-1, -120, 0, 120, 20, I18n.getInstance().translateKey("model.category.block.spawner.button.id"), ids, "Pig") {
+        ListSelectorButtonElement<String> dispatcherIds = new ListSelectorButtonElement<String>(-1, -120, 0, 120, 20, I18n.getInstance().translateKey("model.category.block.spawner.button.id"), ids, "Pig") {
             @Override
             public String getNameFromElement(String element) {
                 return element;
             }
         };
         dispatcherIds.setOnValueChanged(() -> ((MobSpawnerBlockEntity)DisplayChunk.displayBlockEntity).setMobId(dispatcherIds.getCurrentElement()));
-        return new ArrayList<GuiButton>(){{add(dispatcherIds);}};
+        return new ArrayList<ButtonElement>(){{add(dispatcherIds);}};
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/SignEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/SignEntry.java
index 0789f9652..e8282894e 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/SignEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/block/SignEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.block;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerTextField;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerTextFieldElement;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.entity.SignBlockEntity;
 import net.minecraft.core.world.World;
@@ -23,17 +23,17 @@ public class SignEntry extends BlockEntry{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, World world, int meta) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, World world, int meta) {
         SignBlockEntity sign = (SignBlockEntity)DisplayChunk.displayBlockEntity;
-        GuiListenerTextField line1 = new GuiListenerTextField(parentScreen, mc.fontRenderer, -120, 0,                       120, 20, "", "Line 1");
-        GuiListenerTextField line2 = new GuiListenerTextField(parentScreen, mc.fontRenderer, -120, line1.yPosition + 21,    120, 20, "", "Line 2");
-        GuiListenerTextField line3 = new GuiListenerTextField(parentScreen, mc.fontRenderer, -120, line2.yPosition + 21,    120, 20, "", "Line 3");
-        GuiListenerTextField line4 = new GuiListenerTextField(parentScreen, mc.fontRenderer, -120, line3.yPosition + 21,    120, 20, "", "Line 4");
+        ListenerTextFieldElement line1 = new ListenerTextFieldElement(parentScreen, mc.font, -120, 0,                       120, 20, "", "Line 1");
+        ListenerTextFieldElement line2 = new ListenerTextFieldElement(parentScreen, mc.font, -120, line1.yPosition + 21,    120, 20, "", "Line 2");
+        ListenerTextFieldElement line3 = new ListenerTextFieldElement(parentScreen, mc.font, -120, line2.yPosition + 21,    120, 20, "", "Line 3");
+        ListenerTextFieldElement line4 = new ListenerTextFieldElement(parentScreen, mc.font, -120, line3.yPosition + 21,    120, 20, "", "Line 4");
         line1.setOnValueChanged(() -> sign.signText[0] = line1.getText());
         line2.setOnValueChanged(() -> sign.signText[1] = line2.getText());
         line3.setOnValueChanged(() -> sign.signText[2] = line3.getText());
         line4.setOnValueChanged(() -> sign.signText[3] = line4.getText());
-        return new ArrayList<GuiButton>(){
+        return new ArrayList<ButtonElement>(){
             {
                 add(line1);
                 add(line2);
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/BlankEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/BlankEntry.java
index 9766af221..0067a45f5 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/BlankEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/BlankEntry.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.world.World;
 
@@ -15,7 +15,7 @@ public class BlankEntry extends EntityEntry<Entity> {
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, Entity entity) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, Entity entity) {
         return null;
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/DispatcherEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/DispatcherEntry.java
index f0ac1a7cf..420c7c293 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/DispatcherEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/DispatcherEntry.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityDispatcher;
 import net.minecraft.core.world.World;
@@ -20,7 +20,7 @@ public class DispatcherEntry extends EntityEntry<Entity> {
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, Entity entity) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, Entity entity) {
         return null;
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityArmoredZombieEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityArmoredZombieEntry.java
index 7ec452b4b..1b5d031e0 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityArmoredZombieEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityArmoredZombieEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.core.entity.monster.ZombieArmoredMob;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
@@ -18,9 +18,9 @@ public class EntityArmoredZombieEntry extends EntityEntry<ZombieArmoredMob>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, ZombieArmoredMob armoredZombie) {
-        List<GuiButton> buttonList = new ArrayList<>();
-        GuiListenerButton swordButton = new GuiListenerButton(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.armored_zombie.button.sword", false));
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, ZombieArmoredMob armoredZombie) {
+        List<ButtonElement> buttonList = new ArrayList<>();
+        ListenerButtonElement swordButton = new ListenerButtonElement(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.armored_zombie.button.sword", false));
         swordButton.setActionListener(() -> {
             boolean hasSword1 = armoredZombie.getHeldItem() != null;
             armoredZombie.setHoldingSword(!hasSword1);
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityBoatEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityBoatEntry.java
index c9085d1b9..882226a60 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityBoatEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityBoatEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.core.block.entity.FlagBlockEntity;
 import net.minecraft.core.entity.vehicle.BoatEntity;
 import net.minecraft.core.lang.I18n;
@@ -19,8 +19,8 @@ public class EntityBoatEntry extends EntityEntry<BoatEntity>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, BoatEntity entity) {
-        GuiListenerButton flagButton = new GuiListenerButton(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.boat.button.flag", false));
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, BoatEntity entity) {
+        ListenerButtonElement flagButton = new ListenerButtonElement(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.boat.button.flag", false));
         flagButton.setActionListener(() -> {
             boolean flag;
             if (entity.tileEntityFlag == null){
@@ -32,7 +32,7 @@ public class EntityBoatEntry extends EntityEntry<BoatEntity>{
             }
             flagButton.displayString = I18n.getInstance().translateKeyAndFormat("model.category.entity.boat.button.flag", flag);
         });
-        return new ArrayList<GuiButton>(){{add(flagButton);}};
+        return new ArrayList<ButtonElement>(){{add(flagButton);}};
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityCreeperEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityCreeperEntry.java
index c495ec7ba..c6095b9e4 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityCreeperEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityCreeperEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.core.entity.monster.CreeperMob;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
@@ -18,10 +18,10 @@ public class EntityCreeperEntry extends EntityEntry<CreeperMob>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, CreeperMob creeper) {
-        List<GuiButton> buttonList = new ArrayList<>();
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, CreeperMob creeper) {
+        List<ButtonElement> buttonList = new ArrayList<>();
         boolean isCharged = creeper.getPowered();
-        GuiListenerButton chargedToggle = new GuiListenerButton(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.creeper.button.charged", isCharged));
+        ListenerButtonElement chargedToggle = new ListenerButtonElement(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.creeper.button.charged", isCharged));
         chargedToggle.setActionListener(() -> {
             boolean isCharged1 = creeper.getPowered();
             isCharged1 = !isCharged1;
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityEntry.java
index 7cfbb1c7c..ed91ab52f 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityEntry.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.world.World;
 
@@ -12,7 +12,7 @@ public abstract class EntityEntry<T extends Entity>{
     public static final EntityEntry<Entity> blankEntry = new BlankEntry();
     public EntityEntry(){}
     public abstract void onTick(T entity);
-    public abstract List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, T entity);
+    public abstract List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, T entity);
     public abstract T getEntityInstance(Minecraft mc, World world);
     public abstract void onOpen();
     public abstract void onClose();
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFallingSandEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFallingSandEntry.java
index 12258c0f6..525817d01 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFallingSandEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFallingSandEntry.java
@@ -1,10 +1,10 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
-import net.minecraft.client.gui.modelviewer.elements.GuiTextCycle;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
+import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
 import net.minecraft.core.block.Block;
 
 import net.minecraft.core.entity.FallingBlockEntity;
@@ -20,11 +20,11 @@ public class EntityFallingSandEntry extends EntityEntry<FallingBlockEntity>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, FallingBlockEntity sand) {
-        GuiTextCycle<Integer> blockIdCycle = new GuiTextCycle<Integer>(parentScreen, mc.fontRenderer, - 120, 0, 120, 20, sand.blockID) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, FallingBlockEntity sand) {
+        TextCycleElement<Integer> blockIdCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, 0, 120, 20, sand.blockID) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
-                return GuiModelViewer.cycleBlockId(current, offset);
+                return ModelViewerScreen.cycleBlockId(current, offset);
             }
 
             @Override
@@ -44,7 +44,7 @@ public class EntityFallingSandEntry extends EntityEntry<FallingBlockEntity>{
         blockIdCycle.textField.setPrefaceText("ID: ");
         blockIdCycle.textField.setPlaceholder("Block ID");
         blockIdCycle.setOnValueChanged(() -> sand.blockID = blockIdCycle.getCurrentElement());
-        return new ArrayList<GuiButton>(){{add(blockIdCycle);}};
+        return new ArrayList<ButtonElement>(){{add(blockIdCycle);}};
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFireflyEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFireflyEntry.java
index f310e30f3..0206ac0e8 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFireflyEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityFireflyEntry.java
@@ -1,10 +1,10 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListSelectorButton;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerSlider;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListSelectorButtonElement;
+import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
 import net.minecraft.core.entity.animal.FireflyClusterMob;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
@@ -27,15 +27,15 @@ public class EntityFireflyEntry extends EntityEntry<FireflyClusterMob>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, FireflyClusterMob fireflyCluster) {
-        List<GuiButton> buttonList = new ArrayList<>();
-        GuiListenerSlider slider = new GuiListenerSlider(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.fireflycluster.slider.size", 0), 0f);
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, FireflyClusterMob fireflyCluster) {
+        List<ButtonElement> buttonList = new ArrayList<>();
+        ListenerSliderElement slider = new ListenerSliderElement(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.fireflycluster.slider.size", 0), 0f);
         slider.setOnValueChanged(() -> {
             fireflyCluster.setClusterSize((int) (slider.sliderValue * (fireflyCluster.maxClusterSize)));
             slider.displayString = I18n.getInstance().translateKeyAndFormat("model.category.entity.fireflycluster.slider.size", fireflyCluster.getClusterSize());
         });
 
-        GuiListSelectorButton<FireflyClusterMob.FireflyColor> button = new GuiListSelectorButton<FireflyClusterMob.FireflyColor>(-1, - 120, slider.yPosition + 21, 120, 20, I18n.getInstance().translateKey("model.category.entity.fireflycluster.button.cycle"), FireflyClusterMob.FireflyColor.fireFlyColors.values(), FireflyClusterMob.FireflyColor.GREEN) {
+        ListSelectorButtonElement<FireflyClusterMob.FireflyColor> button = new ListSelectorButtonElement<FireflyClusterMob.FireflyColor>(-1, - 120, slider.yPosition + 21, 120, 20, I18n.getInstance().translateKey("model.category.entity.fireflycluster.button.cycle"), FireflyClusterMob.FireflyColor.fireFlyColors.values(), FireflyClusterMob.FireflyColor.GREEN) {
             @Override
             public String getNameFromElement(FireflyClusterMob.FireflyColor element) {
                 return element.getParticleName();
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityItemEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityItemEntry.java
index 8aada06d3..d13ea3380 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityItemEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityItemEntry.java
@@ -1,11 +1,11 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerSlider;
-import net.minecraft.client.gui.modelviewer.elements.GuiTextCycle;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
+import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.entity.ItemEntity;
 import net.minecraft.core.item.Item;
@@ -24,13 +24,13 @@ public class EntityItemEntry extends EntityEntry<ItemEntity>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, ItemEntity itemEntity) {
-        List<GuiButton> buttonList = new ArrayList<>();
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, ItemEntity itemEntity) {
+        List<ButtonElement> buttonList = new ArrayList<>();
         itemEntity.item = Blocks.STONE.getDefaultStack();
-        GuiTextCycle<Integer> itemIdCycle = new GuiTextCycle<Integer>(parentScreen, mc.fontRenderer, - 120, 0, 120, 20, 1) {
+        TextCycleElement<Integer> itemIdCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, 0, 120, 20, 1) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
-                return GuiModelViewer.cycleItemId(current, offset);
+                return ModelViewerScreen.cycleItemId(current, offset);
             }
 
             @Override
@@ -50,7 +50,7 @@ public class EntityItemEntry extends EntityEntry<ItemEntity>{
         itemIdCycle.textField.setPrefaceText("ID: ");
         itemIdCycle.textField.setPlaceholder("Item ID");
 
-        GuiTextCycle<Integer> metaCycle = new GuiTextCycle<Integer>(parentScreen, mc.fontRenderer, - 120, itemIdCycle.yPosition + 21, 120, 20, 0) {
+        TextCycleElement<Integer> metaCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, itemIdCycle.yPosition + 21, 120, 20, 0) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
                 return (current + offset) & 0x3FFF;
@@ -72,7 +72,7 @@ public class EntityItemEntry extends EntityEntry<ItemEntity>{
         };
         metaCycle.textField.setPrefaceText("Meta: ");
         metaCycle.textField.setPlaceholder("Meta");
-        GuiListenerSlider sizeSlider = new GuiListenerSlider(-1, - 120, metaCycle.yPosition + 21,120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.item.slider.size", 1), 1/64f);
+        ListenerSliderElement sizeSlider = new ListenerSliderElement(-1, - 120, metaCycle.yPosition + 21,120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.item.slider.size", 1), 1/64f);
 
         itemIdCycle.setOnValueChanged(() -> itemEntity.item = new ItemStack(itemIdCycle.getCurrentElement(), (int) (sizeSlider.sliderValue * 64), metaCycle.getCurrentElement()));
         metaCycle.setOnValueChanged(() -> itemEntity.item = new ItemStack(itemIdCycle.getCurrentElement(), (int) (sizeSlider.sliderValue * 64), metaCycle.getCurrentElement()));
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityMinecartEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityMinecartEntry.java
index 1d64b63d9..8668dc062 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityMinecartEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityMinecartEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
 import net.minecraft.core.entity.vehicle.MinecartEntity;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
@@ -19,10 +19,10 @@ public class EntityMinecartEntry extends EntityEntry<MinecartEntity>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, MinecartEntity minecart) {
-        GuiListenerButton button = new GuiListenerButton(-1, - 120, 0, 120, 20, I18n.getInstance().translateKey("model.category.entity.minecart.button.cycle"));
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, MinecartEntity minecart) {
+        ListenerButtonElement button = new ListenerButtonElement(-1, - 120, 0, 120, 20, I18n.getInstance().translateKey("model.category.entity.minecart.button.cycle"));
         button.setActionListener(() -> minecart.type = (minecart.type + 3 + (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) ? -1 : 1)) % 3);
-        return new ArrayList<GuiButton>(){{add(button);}};
+        return new ArrayList<ButtonElement>(){{add(button);}};
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityPaintingEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityPaintingEntry.java
index 8e0122dce..94dc7c958 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityPaintingEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityPaintingEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerSlider;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
 import net.minecraft.core.entity.PaintingEntity;
 import net.minecraft.core.enums.ArtType;
 import net.minecraft.core.world.World;
@@ -18,13 +18,13 @@ public class EntityPaintingEntry extends EntityEntry<PaintingEntity>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, PaintingEntity painting) {
-        GuiListenerSlider slider = new GuiListenerSlider(-1, - 120, 0, 120, 20, painting.art.key, 0f);
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, PaintingEntity painting) {
+        ListenerSliderElement slider = new ListenerSliderElement(-1, - 120, 0, 120, 20, painting.art.key, 0f);
         slider.setOnValueChanged(() -> {
             painting.art = ArtType.values.get((int) (slider.sliderValue * (ArtType.values.size() - 1)));
             slider.displayString = painting.art.key;
         });
-        return new ArrayList<GuiButton>(){{add(slider);}};
+        return new ArrayList<ButtonElement>(){{add(slider);}};
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntitySheepEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntitySheepEntry.java
index 7c4fd4fc6..af51cb4bf 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntitySheepEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntitySheepEntry.java
@@ -1,11 +1,10 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerSlider;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
 import net.minecraft.core.entity.animal.SheepMob;
-import net.minecraft.core.item.DyeItem;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.helper.DyeColor;
 import net.minecraft.core.world.World;
@@ -20,9 +19,9 @@ public class EntitySheepEntry extends EntityEntry<SheepMob>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, SheepMob sheep) {
-        List<GuiButton> buttonList = new ArrayList<>();
-        GuiListenerSlider slider = new GuiListenerSlider(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.sheep.slider.color", "White"), 0f);
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, SheepMob sheep) {
+        List<ButtonElement> buttonList = new ArrayList<>();
+        ListenerSliderElement slider = new ListenerSliderElement(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.sheep.slider.color", "White"), 0f);
         slider.setOnValueChanged(() -> {
             sheep.setFleeceColor(DyeColor.colorFromBlockMeta((int) (slider.sliderValue * 15)));
             String color = sheep.getFleeceColor().colorID;
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntitySlimeEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntitySlimeEntry.java
index 1da73ad79..978362242 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntitySlimeEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntitySlimeEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerSlider;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
 import net.minecraft.core.entity.monster.SlimeMob;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
@@ -18,9 +18,9 @@ public class EntitySlimeEntry extends EntityEntry<SlimeMob>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, SlimeMob entity) {
-        List<GuiButton> buttonList = new ArrayList<>();
-        GuiListenerSlider slider = new GuiListenerSlider(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.slime.slider.size", 1), 0f);
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, SlimeMob entity) {
+        List<ButtonElement> buttonList = new ArrayList<>();
+        ListenerSliderElement slider = new ListenerSliderElement(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.slime.slider.size", 1), 0f);
         slider.setOnValueChanged(() -> {
             entity.setSlimeSize((int) (slider.sliderValue * 4) + 1);
             slider.displayString = I18n.getInstance().translateKeyAndFormat("model.category.entity.slime.slider.size", entity.getSlimeSize());
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityTNTEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityTNTEntry.java
index 102fb5a7c..37dfdb1b1 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityTNTEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityTNTEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerSlider;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
 import net.minecraft.core.entity.TNTPrimedEntity;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
@@ -18,14 +18,14 @@ public class EntityTNTEntry extends EntityEntry<TNTPrimedEntity>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, TNTPrimedEntity tnt) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, TNTPrimedEntity tnt) {
         tnt.fuse = 80;
-        GuiListenerSlider slider = new GuiListenerSlider(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.tnt.slider.fuse", 80), 1f);
+        ListenerSliderElement slider = new ListenerSliderElement(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.tnt.slider.fuse", 80), 1f);
         slider.setOnValueChanged(() -> {
             tnt.fuse = (int) (slider.sliderValue * 80);
             slider.displayString = I18n.getInstance().translateKeyAndFormat("model.category.entity.tnt.slider.fuse", tnt.fuse);
         });
-        return new ArrayList<GuiButton>(){{add(slider);}};
+        return new ArrayList<ButtonElement>(){{add(slider);}};
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityWolfEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityWolfEntry.java
index d63598723..1bf36df72 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityWolfEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/entity/EntityWolfEntry.java
@@ -1,15 +1,14 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.entity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
-import net.minecraft.client.gui.modelviewer.elements.GuiListSelectorButton;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
-import net.minecraft.client.gui.modelviewer.elements.GuiTextCycle;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
+import net.minecraft.client.gui.modelviewer.elements.ListSelectorButtonElement;
+import net.minecraft.client.gui.modelviewer.elements.ListenerButtonElement;
+import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
 import net.minecraft.core.entity.animal.WolfMob;
 import net.minecraft.core.item.Item;
-import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.material.ArmorMaterial;
 import net.minecraft.core.lang.I18n;
@@ -31,10 +30,10 @@ public class EntityWolfEntry extends EntityEntry<WolfMob>{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen, WolfMob entityWolf) {
-        List<GuiButton> buttonList = new ArrayList<>();
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen, WolfMob entityWolf) {
+        List<ButtonElement> buttonList = new ArrayList<>();
         boolean isTamed = entityWolf.isWolfTamed();
-        GuiListenerButton tamed = new GuiListenerButton(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.wolf.button.tamed", isTamed));
+        ListenerButtonElement tamed = new ListenerButtonElement(-1, - 120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.wolf.button.tamed", isTamed));
         tamed.setActionListener(() -> {
             boolean _tamed = !entityWolf.isWolfTamed();
             entityWolf.setWolfTamed(_tamed);
@@ -42,7 +41,7 @@ public class EntityWolfEntry extends EntityEntry<WolfMob>{
         });
 
         boolean isSitting = entityWolf.isWolfSitting();
-        GuiListenerButton sitting = new GuiListenerButton(-1, - 120, tamed.yPosition + 21, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.wolf.button.sitting", isSitting));
+        ListenerButtonElement sitting = new ListenerButtonElement(-1, - 120, tamed.yPosition + 21, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.wolf.button.sitting", isSitting));
         sitting.setActionListener(() -> {
             boolean _sitting = !entityWolf.isWolfSitting();
             entityWolf.setWolfSitting(_sitting);
@@ -50,14 +49,14 @@ public class EntityWolfEntry extends EntityEntry<WolfMob>{
         });
 
         boolean isAngry = entityWolf.isWolfAngry();
-        GuiListenerButton angry = new GuiListenerButton(-1, - 120, sitting.yPosition + 21, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.wolf.button.angry", isAngry));
+        ListenerButtonElement angry = new ListenerButtonElement(-1, - 120, sitting.yPosition + 21, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.wolf.button.angry", isAngry));
         angry.setActionListener(() -> {
             boolean _angry = !entityWolf.isWolfAngry();
             entityWolf.setWolfAngry(_angry);
             angry.displayString = I18n.getInstance().translateKeyAndFormat("model.category.entity.wolf.button.angry", _angry);
         });
 
-        GuiListSelectorButton<ArmorMaterial> armor = new GuiListSelectorButton<ArmorMaterial>(-1, - 120, angry.yPosition + 21, 120, 20, I18n.getInstance().translateKey("model.category.entity.wolf.button.armor"), armorMaterials,null) {
+        ListSelectorButtonElement<ArmorMaterial> armor = new ListSelectorButtonElement<ArmorMaterial>(-1, - 120, angry.yPosition + 21, 120, 20, I18n.getInstance().translateKey("model.category.entity.wolf.button.armor"), armorMaterials,null) {
             @Override
             public String getNameFromElement(ArmorMaterial element) {
                 return element == null ? "none" : element.identifier.toString();
@@ -69,12 +68,12 @@ public class EntityWolfEntry extends EntityEntry<WolfMob>{
         });
 
         entityWolf.setWolfHeldItem(null);
-        GuiListenerButton hasItem = new GuiListenerButton(-1, - 120, armor.yPosition + 21, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.wolf.button.item", false));
+        ListenerButtonElement hasItem = new ListenerButtonElement(-1, - 120, armor.yPosition + 21, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.entity.wolf.button.item", false));
 
-        GuiTextCycle<Integer> itemIdCycle = new GuiTextCycle<Integer>(parentScreen, mc.fontRenderer, - 120, hasItem.yPosition + 21, 120, 20, 1) {
+        TextCycleElement<Integer> itemIdCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, hasItem.yPosition + 21, 120, 20, 1) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
-                return GuiModelViewer.cycleItemId(current, offset);
+                return ModelViewerScreen.cycleItemId(current, offset);
             }
 
             @Override
@@ -98,7 +97,7 @@ public class EntityWolfEntry extends EntityEntry<WolfMob>{
         itemIdCycle.textField.setPrefaceText("ID: ");
         itemIdCycle.textField.setPlaceholder("Item ID");
 
-        GuiTextCycle<Integer> metaCycle = new GuiTextCycle<Integer>(parentScreen, mc.fontRenderer, - 120, itemIdCycle.yPosition + 21, 120, 20, 0) {
+        TextCycleElement<Integer> metaCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, itemIdCycle.yPosition + 21, 120, 20, 0) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
                 return (current + offset) & 0x3FFF;
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/BlockFXEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/BlockFXEntry.java
index bed996f35..d489910d2 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/BlockFXEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/BlockFXEntry.java
@@ -2,11 +2,11 @@ package net.minecraft.client.gui.modelviewer.categories.entries.particle;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.particle.TerrainParticle;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
-import net.minecraft.client.gui.modelviewer.elements.GuiListSelectorButton;
-import net.minecraft.client.gui.modelviewer.elements.GuiTextCycle;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
+import net.minecraft.client.gui.modelviewer.elements.ListSelectorButtonElement;
+import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.lang.I18n;
@@ -27,12 +27,12 @@ public class BlockFXEntry extends GenericFXEntry{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen) {
-        List<GuiButton> buttonList = super.getEntryButtons(mc, parentScreen);
-        GuiTextCycle<Integer> blockIdCycle = new GuiTextCycle<Integer>(parentScreen, mc.fontRenderer, - 120, buttonList.get(buttonList.size()-1).getY() + 21, 120, 20, blockId) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen) {
+        List<ButtonElement> buttonList = super.getEntryButtons(mc, parentScreen);
+        TextCycleElement<Integer> blockIdCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, buttonList.get(buttonList.size()-1).getY() + 21, 120, 20, blockId) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
-                return GuiModelViewer.cycleBlockId(current, offset);
+                return ModelViewerScreen.cycleBlockId(current, offset);
             }
 
             @Override
@@ -54,7 +54,7 @@ public class BlockFXEntry extends GenericFXEntry{
         blockIdCycle.setOnValueChanged(() -> blockId = blockIdCycle.getCurrentElement());
         buttonList.add(blockIdCycle);
 
-        GuiTextCycle<Integer> metaCycle = new GuiTextCycle<Integer>(parentScreen, mc.fontRenderer, - 120, blockIdCycle.getY() + 21, 120, 20, 0) {
+        TextCycleElement<Integer> metaCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, blockIdCycle.getY() + 21, 120, 20, 0) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
                 return (current + offset) & 0x3FFF;
@@ -79,7 +79,7 @@ public class BlockFXEntry extends GenericFXEntry{
         metaCycle.setOnValueChanged(() -> meta = metaCycle.getCurrentElement());
         buttonList.add(metaCycle);
 
-        GuiListSelectorButton<Side> sideButton = new GuiListSelectorButton<Side>(-1, -120, metaCycle.getY() + 21, 120, 20, I18n.getInstance().translateKey("model.category.particle.block.side"), Arrays.asList(Side.sides), side) {
+        ListSelectorButtonElement<Side> sideButton = new ListSelectorButtonElement<Side>(-1, -120, metaCycle.getY() + 21, 120, 20, I18n.getInstance().translateKey("model.category.particle.block.side"), Arrays.asList(Side.sides), side) {
             @Override
             public String getNameFromElement(Side element) {
                 return element.name();
@@ -93,7 +93,7 @@ public class BlockFXEntry extends GenericFXEntry{
 
     @Override
     public void spawnParticle(Minecraft mc, World world, double x, double y, double z) {
-        mc.effectRenderer.addEffect(new TerrainParticle(world, x, y, z, motionX,motionY,motionZ, Block.getBlock(blockId), side.getId(), meta));
+        mc.particleEngine.add(new TerrainParticle(world, x, y, z, motionX,motionY,motionZ, Block.getBlock(blockId), side, meta));
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/BubbleFXEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/BubbleFXEntry.java
index c76bebe6b..8cda62029 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/BubbleFXEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/BubbleFXEntry.java
@@ -10,6 +10,6 @@ public class BubbleFXEntry extends GenericFXEntry{
     }
     @Override
     public void spawnParticle(Minecraft mc, World world, double x, double y, double z) {
-        mc.effectRenderer.addEffect(new BubbleParticle(world, x, y, z, motionX, motionY, motionZ, false));
+        mc.particleEngine.add(new BubbleParticle(world, x, y, z, motionX, motionY, motionZ, false));
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/GenericFXEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/GenericFXEntry.java
index 3d0c226e3..2f13bd2a1 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/GenericFXEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/GenericFXEntry.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.particle;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerTextField;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerTextFieldElement;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
 import org.lwjgl.input.Keyboard;
@@ -36,30 +36,30 @@ public class GenericFXEntry extends ParticleEntry{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen) {
-        List<GuiButton> buttons = new ArrayList<>();
-        GuiListenerTextField mxField = new GuiListenerTextField(parentScreen, mc.fontRenderer, -120, 0, 120, 20, String.valueOf(motionX), "Motion X");
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen) {
+        List<ButtonElement> buttons = new ArrayList<>();
+        ListenerTextFieldElement mxField = new ListenerTextFieldElement(parentScreen, mc.font, -120, 0, 120, 20, String.valueOf(motionX), "Motion X");
         mxField.setPrefaceText("Motion X: ");
         mxField.setOnValueChanged(() ->{
             try {
                 motionX = Double.parseDouble(mxField.getText());
             } catch (Exception ignored){}
         });
-        GuiListenerTextField myField = new GuiListenerTextField(parentScreen, mc.fontRenderer, -120, mxField.yPosition + 21, 120, 20, String.valueOf(motionY), "Motion Y");
+        ListenerTextFieldElement myField = new ListenerTextFieldElement(parentScreen, mc.font, -120, mxField.yPosition + 21, 120, 20, String.valueOf(motionY), "Motion Y");
         myField.setPrefaceText("Motion Y: ");
         myField.setOnValueChanged(() ->{
             try {
                 motionY = Double.parseDouble(myField.getText());
             } catch (Exception ignored){}
         });
-        GuiListenerTextField mzField = new GuiListenerTextField(parentScreen, mc.fontRenderer, -120, myField.yPosition + 21, 120, 20, String.valueOf(motionZ), "Motion Z");
+        ListenerTextFieldElement mzField = new ListenerTextFieldElement(parentScreen, mc.font, -120, myField.yPosition + 21, 120, 20, String.valueOf(motionZ), "Motion Z");
         mzField.setPrefaceText("Motion Z: ");
         mzField.setOnValueChanged(() ->{
             try {
                 motionZ = Double.parseDouble(mzField.getText());
             } catch (Exception ignored){}
         });
-        GuiListenerTextField dataField = new GuiListenerTextField(parentScreen, mc.fontRenderer, -120, mzField.yPosition + 21, 120, 20, String.valueOf(data), "Data");
+        ListenerTextFieldElement dataField = new ListenerTextFieldElement(parentScreen, mc.font, -120, mzField.yPosition + 21, 120, 20, String.valueOf(data), "Data");
         dataField.setPrefaceText("Data: ");
         dataField.setKeyListener(key -> {
             try {
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ItemFXEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ItemFXEntry.java
index d2f3e95e3..3eccd4c66 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ItemFXEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ItemFXEntry.java
@@ -2,9 +2,9 @@ package net.minecraft.client.gui.modelviewer.categories.entries.particle;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.particle.BreakingItemParticle;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiTextCycle;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.TextCycleElement;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.item.Item;
 import net.minecraft.core.lang.I18n;
@@ -22,8 +22,8 @@ public class ItemFXEntry extends ParticleEntry{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen) {
-        GuiTextCycle<Integer> itemIdCycle = new GuiTextCycle<Integer>(parentScreen, mc.fontRenderer, - 120, 0, 120, 20, itemID) {
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen) {
+        TextCycleElement<Integer> itemIdCycle = new TextCycleElement<Integer>(parentScreen, mc.font, - 120, 0, 120, 20, itemID) {
             @Override
             public Integer cycleElement(Integer current, int offset) {
                 return cycleItemId(current, offset);
@@ -46,7 +46,7 @@ public class ItemFXEntry extends ParticleEntry{
         itemIdCycle.textField.setPrefaceText("ID: ");
         itemIdCycle.textField.setPlaceholder("Item ID");
         itemIdCycle.setOnValueChanged(() -> itemID = itemIdCycle.getCurrentElement());
-        return new ArrayList<GuiButton>(){
+        return new ArrayList<ButtonElement>(){
             {
                 add(itemIdCycle);
             }
@@ -55,7 +55,7 @@ public class ItemFXEntry extends ParticleEntry{
 
     @Override
     public void spawnParticle(Minecraft mc, World world, double x, double y, double z) {
-        mc.effectRenderer.addEffect(new BreakingItemParticle(world, x, y, z, Item.itemsList[itemID]));
+        mc.particleEngine.add(new BreakingItemParticle(world, x, y, z, Item.itemsList[itemID]));
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/LeafFXEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/LeafFXEntry.java
index 0481e5c19..294a3da4a 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/LeafFXEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/LeafFXEntry.java
@@ -10,6 +10,6 @@ public class LeafFXEntry extends GenericFXEntry{
     }
     @Override
     public void spawnParticle(Minecraft mc, World world, double x, double y, double z) {
-        mc.effectRenderer.addEffect(new LeafParticle(world, x, y, z, motionX, motionY, motionZ));
+        mc.particleEngine.add(new LeafParticle(world, x, y, z, motionX, motionY, motionZ));
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/NoteFXEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/NoteFXEntry.java
index b5eac2d72..4eddd1569 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/NoteFXEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/NoteFXEntry.java
@@ -2,9 +2,9 @@ package net.minecraft.client.gui.modelviewer.categories.entries.particle;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.particle.NoteParticle;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerSlider;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerSliderElement;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
 
@@ -20,13 +20,13 @@ public class NoteFXEntry extends ParticleEntry{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen) {
-        GuiListenerSlider noteSlider = new GuiListenerSlider(-1, -120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.particle.note.slider", getNoteString(note)), ((float)note)/maxNote);
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen) {
+        ListenerSliderElement noteSlider = new ListenerSliderElement(-1, -120, 0, 120, 20, I18n.getInstance().translateKeyAndFormat("model.category.particle.note.slider", getNoteString(note)), ((float)note)/maxNote);
         noteSlider.setOnValueChanged(() ->{
             note = (int) (noteSlider.sliderValue * maxNote);
             noteSlider.displayString = I18n.getInstance().translateKeyAndFormat("model.category.particle.note.slider", getNoteString(note));
         });
-        return new ArrayList<GuiButton>(){{add(noteSlider);}};
+        return new ArrayList<ButtonElement>(){{add(noteSlider);}};
     }
     private String getNoteString(int note){
         return (Integer.toHexString(note).length() == 1) ? "0"+Integer.toHexString(note) : Integer.toHexString(note);
@@ -34,7 +34,7 @@ public class NoteFXEntry extends ParticleEntry{
 
     @Override
     public void spawnParticle(Minecraft mc, World world, double x, double y, double z) {
-        mc.effectRenderer.addEffect(new NoteParticle(world, x, y, z, (double) note / 24D, 0.0D, 0.0D));
+        mc.particleEngine.add(new NoteParticle(world, x, y, z, (double) note / 24D, 0.0D, 0.0D));
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntry.java
index 95d6b8a76..57480939a 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/ParticleEntry.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.modelviewer.categories.entries.particle;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
 
@@ -10,7 +10,7 @@ import java.util.List;
 
 public abstract class ParticleEntry {
     public abstract String getParticleName(I18n translator);
-    public abstract List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen);
+    public abstract List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen);
     public abstract void spawnParticle(Minecraft mc, World world, double x, double y, double z);
     public abstract void onOpen();
     public abstract void onClose();
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/RedDustFXEntry.java b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/RedDustFXEntry.java
index de87b4c6d..056c5797a 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/RedDustFXEntry.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/categories/entries/particle/RedDustFXEntry.java
@@ -2,9 +2,9 @@ package net.minecraft.client.gui.modelviewer.categories.entries.particle;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.particle.RedstoneDustParticle;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.modelviewer.elements.GuiListenerTextField;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.gui.modelviewer.elements.ListenerTextFieldElement;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.world.World;
 import org.lwjgl.input.Keyboard;
@@ -22,8 +22,8 @@ public class RedDustFXEntry extends ParticleEntry{
     }
 
     @Override
-    public List<GuiButton> getEntryButtons(Minecraft mc, GuiScreen parentScreen) {
-        GuiListenerTextField rField = new GuiListenerTextField(parentScreen, mc.fontRenderer, -120, 0, 40, 20, String.valueOf(red), "Red");
+    public List<ButtonElement> getEntryButtons(Minecraft mc, Screen parentScreen) {
+        ListenerTextFieldElement rField = new ListenerTextFieldElement(parentScreen, mc.font, -120, 0, 40, 20, String.valueOf(red), "Red");
         rField.setPrefaceText("R: ");
         rField.setKeyListener(key -> {
             try {
@@ -36,7 +36,7 @@ public class RedDustFXEntry extends ParticleEntry{
                 red = 0;
             }
         });
-        GuiListenerTextField gField = new GuiListenerTextField(parentScreen, mc.fontRenderer, -80, 0, 40, 20, String.valueOf(green), "Green");
+        ListenerTextFieldElement gField = new ListenerTextFieldElement(parentScreen, mc.font, -80, 0, 40, 20, String.valueOf(green), "Green");
         gField.setPrefaceText("G: ");
         gField.setKeyListener(key -> {
             try {
@@ -49,7 +49,7 @@ public class RedDustFXEntry extends ParticleEntry{
                 green = 0;
             }
         });
-        GuiListenerTextField bField = new GuiListenerTextField(parentScreen, mc.fontRenderer, -40, 0, 40, 20, String.valueOf(blue), "Blue");
+        ListenerTextFieldElement bField = new ListenerTextFieldElement(parentScreen, mc.font, -40, 0, 40, 20, String.valueOf(blue), "Blue");
         bField.setPrefaceText("B: ");
         bField.setKeyListener(key -> {
             try {
@@ -62,7 +62,7 @@ public class RedDustFXEntry extends ParticleEntry{
                 blue = 0;
             }
         });
-        return new ArrayList<GuiButton>(){{
+        return new ArrayList<ButtonElement>(){{
             add(rField);
             add(gField);
             add(bField);
@@ -71,7 +71,7 @@ public class RedDustFXEntry extends ParticleEntry{
 
     @Override
     public void spawnParticle(Minecraft mc, World world, double x, double y, double z) {
-        mc.effectRenderer.addEffect(new RedstoneDustParticle(world, x, y, z, red/255f, green/255f, blue/255f, 15));
+        mc.particleEngine.add(new RedstoneDustParticle(world, x, y, z, red/255f, green/255f, blue/255f, 15));
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerTextureButton.java b/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerTextureButton.java
deleted file mode 100644
index 5393017fe..000000000
--- a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerTextureButton.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package net.minecraft.client.gui.modelviewer.elements;
-
-import net.minecraft.client.Minecraft;
-import org.lwjgl.opengl.GL11;
-
-public class GuiListenerTextureButton extends GuiListenerButton{
-    private String texturePath;
-    private int u;
-    private int v;
-    public GuiListenerTextureButton(int id, String texturePath, int xPosition, int yPosition, int u, int v, int width, int height) {
-        super(id, xPosition, yPosition, width, height, "");
-        this.texturePath = texturePath;
-        this.u = u;
-        this.v = v;
-    }
-    public GuiListenerTextureButton(int id, String texturePath, int xPosition, int yPosition, int u, int v, int width, int height, String s) {
-        super(id, xPosition, yPosition, width, height, s);
-        this.texturePath = texturePath;
-        this.u = u;
-        this.v = v;
-    }
-
-    @Override
-    public void drawButton(Minecraft mc, int mouseX, int mouseY) {
-        if (!visible) {
-            return;
-        }
-        mc.renderEngine.loadTexture(texturePath).bind();
-        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-        boolean isHovered = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height;
-        if (!enabled)
-        {
-            drawTexturedModalRect(xPosition, yPosition, u, v, width, height);
-        }
-        else if (!isHovered)
-        {
-            drawTexturedModalRect(xPosition, yPosition, u, v + height, width, height);
-        }
-        else
-        {
-            drawTexturedModalRect(xPosition, yPosition, u, v + height * 2, width, height);
-        }
-        mouseDragged(mc, mouseX, mouseY);
-    }
-}
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListSelectorButton.java b/src/main/java/net/minecraft/client/gui/modelviewer/elements/ListSelectorButtonElement.java
similarity index 85%
rename from src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListSelectorButton.java
rename to src/main/java/net/minecraft/client/gui/modelviewer/elements/ListSelectorButtonElement.java
index 5d7bb9166..57ac2e8e8 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListSelectorButton.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/elements/ListSelectorButtonElement.java
@@ -7,12 +7,12 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
-public abstract class GuiListSelectorButton<T> extends GuiListenerButton{
+public abstract class ListSelectorButtonElement<T> extends ListenerButtonElement {
     public final List<T> list;
     private int index;
     private final String formattedText;
     private final T defaultElement;
-    public GuiListSelectorButton(int id, int xPosition, int yPosition, int width, int height, String formattedText, Collection<T> collection, T initialElement) {
+    public ListSelectorButtonElement(int id, int xPosition, int yPosition, int width, int height, String formattedText, Collection<T> collection, T initialElement) {
         super(id, xPosition, yPosition, width, height, "");
         displayString = String.format(formattedText, getNameFromElement(initialElement));
         this.defaultElement = initialElement;
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerButton.java b/src/main/java/net/minecraft/client/gui/modelviewer/elements/ListenerButtonElement.java
similarity index 69%
rename from src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerButton.java
rename to src/main/java/net/minecraft/client/gui/modelviewer/elements/ListenerButtonElement.java
index 331e21c69..4c26e2401 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerButton.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/elements/ListenerButtonElement.java
@@ -1,17 +1,17 @@
 package net.minecraft.client.gui.modelviewer.elements;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ButtonElement;
 
-public class GuiListenerButton extends GuiButton implements IListenerElement<GuiListenerButton> {
+public class ListenerButtonElement extends ButtonElement implements IListenerElement<ListenerButtonElement> {
     protected IActionListener action;
     protected IKeyListener keyListener;
     protected Runnable onValueChanged;
-    public GuiListenerButton(int id, int xPosition, int yPosition, String text) {
+    public ListenerButtonElement(int id, int xPosition, int yPosition, String text) {
         super(id, xPosition, yPosition, text);
     }
 
-    public GuiListenerButton(int id, int xPosition, int yPosition, int width, int height, String text) {
+    public ListenerButtonElement(int id, int xPosition, int yPosition, int width, int height, String text) {
         super(id, xPosition, yPosition, width, height, text);
     }
     @Override
@@ -29,18 +29,18 @@ public class GuiListenerButton extends GuiButton implements IListenerElement<Gui
         }
     }
     @Override
-    public GuiListenerButton setActionListener(IActionListener listener) {
+    public ListenerButtonElement setActionListener(IActionListener listener) {
         action = listener;
         return this;
     }
 
     @Override
-    public GuiListenerButton setKeyListener(IKeyListener listener) {
+    public ListenerButtonElement setKeyListener(IKeyListener listener) {
         keyListener = listener;
         return this;
     }
     @Override
-    public GuiListenerButton setOnValueChanged(Runnable runnable){
+    public ListenerButtonElement setOnValueChanged(Runnable runnable){
         onValueChanged = runnable;
         return this;
     }
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerSlider.java b/src/main/java/net/minecraft/client/gui/modelviewer/elements/ListenerSliderElement.java
similarity index 68%
rename from src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerSlider.java
rename to src/main/java/net/minecraft/client/gui/modelviewer/elements/ListenerSliderElement.java
index 1b54b47cf..2b88be8b7 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerSlider.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/elements/ListenerSliderElement.java
@@ -1,22 +1,22 @@
 package net.minecraft.client.gui.modelviewer.elements;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiSlider;
+import net.minecraft.client.gui.SliderElement;
 import net.minecraft.client.option.FloatOption;
 
-public class GuiListenerSlider extends GuiSlider implements IListenerElement<GuiListenerSlider> {
+public class ListenerSliderElement extends SliderElement implements IListenerElement<ListenerSliderElement> {
     private IActionListener action;
     private IKeyListener keyListener;
     private Runnable onValueChanged;
-    public GuiListenerSlider(int id, int xPosition, int yPosition, FloatOption floatOption) {
+    public ListenerSliderElement(int id, int xPosition, int yPosition, FloatOption floatOption) {
         super(id, xPosition, yPosition, floatOption);
     }
 
-    public GuiListenerSlider(int id, int xPosition, int yPosition, int width, int height, FloatOption floatOption) {
+    public ListenerSliderElement(int id, int xPosition, int yPosition, int width, int height, FloatOption floatOption) {
         super(id, xPosition, yPosition, width, height, floatOption);
     }
 
-    public GuiListenerSlider(int id, int xPosition, int yPosition, int width, int height, String text, float defaultValue) {
+    public ListenerSliderElement(int id, int xPosition, int yPosition, int width, int height, String text, float defaultValue) {
         super(id, xPosition, yPosition, width, height, text, defaultValue);
     }
     @Override
@@ -41,18 +41,18 @@ public class GuiListenerSlider extends GuiSlider implements IListenerElement<Gui
     }
 
     @Override
-    public GuiListenerSlider setActionListener(IActionListener listener) {
+    public ListenerSliderElement setActionListener(IActionListener listener) {
         action = listener;
         return this;
     }
 
     @Override
-    public GuiListenerSlider setKeyListener(IKeyListener listener) {
+    public ListenerSliderElement setKeyListener(IKeyListener listener) {
         keyListener = listener;
         return this;
     }
     @Override
-    public GuiListenerSlider setOnValueChanged(Runnable runnable){
+    public ListenerSliderElement setOnValueChanged(Runnable runnable){
         onValueChanged = runnable;
         return this;
     }
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerTextField.java b/src/main/java/net/minecraft/client/gui/modelviewer/elements/ListenerTextFieldElement.java
similarity index 74%
rename from src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerTextField.java
rename to src/main/java/net/minecraft/client/gui/modelviewer/elements/ListenerTextFieldElement.java
index b4765594a..59b149d99 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiListenerTextField.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/elements/ListenerTextFieldElement.java
@@ -1,14 +1,14 @@
 package net.minecraft.client.gui.modelviewer.elements;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.text.ITextField;
 import net.minecraft.client.gui.text.TextFieldEditor;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import org.lwjgl.input.Keyboard;
 
-public class GuiListenerTextField extends GuiListenerButton implements ITextField {
-    private final FontRenderer fontRenderer;
+public class ListenerTextFieldElement extends ListenerButtonElement implements ITextField {
+    private final Font font;
     private String text = "";
     private String prefaceText = "";
     private int maxStringLength;
@@ -16,26 +16,26 @@ public class GuiListenerTextField extends GuiListenerButton implements ITextFiel
     public boolean isFocused;
     public boolean isEnabled;
     public boolean removeTextOnClick = false;
-    public GuiScreen parent;
+    public Screen parent;
     private ITextChangeListener textChangeListener;
     private String placeholder;
     public boolean drawBackground = true;
     public final TextFieldEditor editor;
 
-    public GuiListenerTextField(GuiScreen parent, FontRenderer fontrenderer, int xPosition, int yPosition, int width, int height, String defaultText, String placeholder)
+    public ListenerTextFieldElement(Screen parent, Font font, int xPosition, int yPosition, int width, int height, String defaultText, String placeholder)
     {
         super(-1, xPosition, yPosition, width, height, "");
         playSound = false;
         isFocused = false;
         isEnabled = true;
         this.parent = parent;
-        fontRenderer = fontrenderer;
+        this.font = font;
         this.editor = new TextFieldEditor(this);
         this.placeholder = placeholder;
         setText(defaultText);
         editor.setCursor(10000);
     }
-    public GuiListenerTextField setPrefaceText(String prefaceText){
+    public ListenerTextFieldElement setPrefaceText(String prefaceText){
         this.prefaceText = prefaceText;
         return this;
     }
@@ -118,24 +118,24 @@ public class GuiListenerTextField extends GuiListenerButton implements ITextFiel
         }
         if (text.isEmpty() && !isFocused)
         {
-            drawString(fontRenderer, placeholder, xPosition + 4, yPosition + (height - 8) / 2, 0x5f5f5f);
+            drawString(font, placeholder, xPosition + 4, yPosition + (height - 8) / 2, 0x5f5f5f);
         }
 
         if(isEnabled)
         {
             boolean drawCursor = isFocused && (cursorCounter / 6) % 2 == 0;
             int cursor = editor.getCursor();
-            int maxDisplayableChars = this.width / fontRenderer.getCharWidth('_');
+            int maxDisplayableChars = this.width / font.getCharWidth('_');
 
             if (!text.isEmpty() || isFocused){
                 if(prefaceText.length() + text.length() <= maxDisplayableChars-1){
-                    drawString(fontRenderer, prefaceText + text, xPosition + 4, yPosition + (height - 8) / 2, 0xE0E0E0);
+                    drawString(font, prefaceText + text, xPosition + 4, yPosition + (height - 8) / 2, 0xE0E0E0);
                 } else {
                     //only draw the part of the string that's maxDisplayableChars chars around the cursor
                     String newString = prefaceText + text;
                     int begin = Math.max(0,cursor - maxDisplayableChars);
                     int end = Math.max(maxDisplayableChars,Math.min(newString.length(),cursor));
-                    drawString(fontRenderer, newString.substring(begin, end), xPosition + 4, yPosition + (height - 8) / 2, 0xE0E0E0);
+                    drawString(font, newString.substring(begin, end), xPosition + 4, yPosition + (height - 8) / 2, 0xE0E0E0);
                 }
             }
             if (drawCursor)
@@ -144,21 +144,21 @@ public class GuiListenerTextField extends GuiListenerButton implements ITextFiel
                 if (!text.isEmpty() || isFocused){
                     currentText = prefaceText + text;
                 }
-                int width = fontRenderer.getStringWidth(currentText);
+                int width = font.getStringWidth(currentText);
                 if (cursor < text.length())
                 {
-                    width = fontRenderer.getStringWidth(text.substring(0, cursor)) + fontRenderer.getStringWidth(prefaceText);
+                    width = font.getStringWidth(text.substring(0, cursor)) + font.getStringWidth(prefaceText);
                 }
                 if(width >= this.width-4){
                     // width of the text box - the width of the last character
-                    width = (this.width-4) - fontRenderer.getStringWidth(currentText.substring(currentText.length()-2,currentText.length()-1));
+                    width = (this.width-4) - font.getStringWidth(currentText.substring(currentText.length()-2,currentText.length()-1));
                 }
-                drawString(fontRenderer, "_", xPosition + 4 + width, yPosition + (height - 8) / 2, 0xE0E0E0);
+                drawString(font, "_", xPosition + 4 + width, yPosition + (height - 8) / 2, 0xE0E0E0);
             }
         }
         else
         {
-            drawString(fontRenderer, text, xPosition + 4, yPosition + (height - 8) / 2, 0x707070);
+            drawString(font, text, xPosition + 4, yPosition + (height - 8) / 2, 0x707070);
         }
     }
 
@@ -177,13 +177,13 @@ public class GuiListenerTextField extends GuiListenerButton implements ITextFiel
         return isFocused || super.isHovered(mouseX, mouseY);
     }
 
-    public GuiListenerTextField setTextChangeListener(ITextChangeListener textChangeListener) {
+    public ListenerTextFieldElement setTextChangeListener(ITextChangeListener textChangeListener) {
         this.textChangeListener = textChangeListener;
         return this;
     }
 
     public interface ITextChangeListener
     {
-        void textChanged(GuiListenerTextField textField);
+        void textChanged(ListenerTextFieldElement textField);
     }
 }
diff --git a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiTextCycle.java b/src/main/java/net/minecraft/client/gui/modelviewer/elements/TextCycleElement.java
similarity index 80%
rename from src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiTextCycle.java
rename to src/main/java/net/minecraft/client/gui/modelviewer/elements/TextCycleElement.java
index e1bafcda2..7eff42c73 100644
--- a/src/main/java/net/minecraft/client/gui/modelviewer/elements/GuiTextCycle.java
+++ b/src/main/java/net/minecraft/client/gui/modelviewer/elements/TextCycleElement.java
@@ -1,19 +1,19 @@
 package net.minecraft.client.gui.modelviewer.elements;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.render.Font;
 
-public abstract class GuiTextCycle<T> extends GuiListenerButton{
+public abstract class TextCycleElement<T> extends ListenerButtonElement {
     private T currentElement;
     private final T defaultElement;
-    public final GuiListenerButton prevButton;
-    public final GuiListenerButton nextButton;
-    public final GuiListenerTextField textField;
-    public GuiTextCycle(GuiScreen parent, FontRenderer fontRenderer, int xPosition, int yPosition, int width, int height, T initialElement) {
+    public final ListenerButtonElement prevButton;
+    public final ListenerButtonElement nextButton;
+    public final ListenerTextFieldElement textField;
+    public TextCycleElement(Screen parent, Font font, int xPosition, int yPosition, int width, int height, T initialElement) {
         super(-1, xPosition, yPosition, width, height, "");
 
-        textField = new GuiListenerTextField(parent, fontRenderer, 0, yPosition, width - height * 2 - 2, height, getNameFromElement(initialElement), "");
+        textField = new ListenerTextFieldElement(parent, font, 0, yPosition, width - height * 2 - 2, height, getNameFromElement(initialElement), "");
         textField.setKeyListener(key -> {
             String text = textField.getText();
             setCurrentElement(getElementFromString(text));
@@ -24,14 +24,14 @@ public abstract class GuiTextCycle<T> extends GuiListenerButton{
             textField.setText(text);
         });
 
-        prevButton = new GuiListenerButton(-1, xPosition, yPosition, height, height, "<");
+        prevButton = new ListenerButtonElement(-1, xPosition, yPosition, height, height, "<");
         prevButton.setActionListener(() -> {
             setCurrentElement(cycleElement(getCurrentElement(), -1));
         });
 
         textField.xPosition = prevButton.xPosition + prevButton.width + 1;
 
-        nextButton = new GuiListenerButton(-1, textField.xPosition + textField.width + 1, yPosition, height, height, ">");
+        nextButton = new ListenerButtonElement(-1, textField.xPosition + textField.width + 1, yPosition, height, height, ">");
         nextButton.setActionListener(() -> {
             setCurrentElement(cycleElement(getCurrentElement(), 1));
         });
diff --git a/src/main/java/net/minecraft/client/gui/options/GuiOptionsButton.java b/src/main/java/net/minecraft/client/gui/options/OptionsButtonElement.java
similarity index 54%
rename from src/main/java/net/minecraft/client/gui/options/GuiOptionsButton.java
rename to src/main/java/net/minecraft/client/gui/options/OptionsButtonElement.java
index caad98382..84b8ad1be 100644
--- a/src/main/java/net/minecraft/client/gui/options/GuiOptionsButton.java
+++ b/src/main/java/net/minecraft/client/gui/options/OptionsButtonElement.java
@@ -1,31 +1,31 @@
 package net.minecraft.client.gui.options;
 
-import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.client.option.Option;
 
 // Referenced classes of package net.minecraft.src:
 //            GuiButton, EnumOptions
 
-public class GuiOptionsButton extends GuiButton
+public class OptionsButtonElement extends ButtonElement
 {
 
-    public GuiOptionsButton(int id, int xPosition, int yPosition, String text)
+    public OptionsButtonElement(int id, int xPosition, int yPosition, String text)
     {
         this(id, xPosition, yPosition, null, text);
     }
 
-    public GuiOptionsButton(int id, int xPosition, int yPosition, int width, int height, String text)
+    public OptionsButtonElement(int id, int xPosition, int yPosition, int width, int height, String text)
     {
         super(id, xPosition, yPosition, width, height, text);
         option = null;
     }
 
-    public GuiOptionsButton(int id, int xPosition, int yPosition, Option<?> option, String text)
+    public OptionsButtonElement(int id, int xPosition, int yPosition, Option<?> option, String text)
     {
         this(id, xPosition, yPosition, 150, 20, option, text);
     }
 
-    public GuiOptionsButton(int id, int xPosition, int yPosition, int width, int height, Option<?> option, String text)
+    public OptionsButtonElement(int id, int xPosition, int yPosition, int width, int height, Option<?> option, String text)
     {
         super(id, xPosition, yPosition, width, height, text);
         this.option = option;
diff --git a/src/main/java/net/minecraft/client/gui/options/GuiOptions.java b/src/main/java/net/minecraft/client/gui/options/OptionsScreen.java
similarity index 82%
rename from src/main/java/net/minecraft/client/gui/options/GuiOptions.java
rename to src/main/java/net/minecraft/client/gui/options/OptionsScreen.java
index edb1b6dc2..8df1f345e 100644
--- a/src/main/java/net/minecraft/client/gui/options/GuiOptions.java
+++ b/src/main/java/net/minecraft/client/gui/options/OptionsScreen.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.options;
 
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiRenderItem;
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.ItemElement;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.client.gui.options.components.KeyBindingComponent;
 import net.minecraft.client.gui.options.components.OptionsComponent;
 import net.minecraft.client.gui.options.data.OptionsPage;
@@ -21,8 +21,8 @@ import org.lwjgl.opengl.GL11;
 import static org.lwjgl.opengl.GL11.*;
 import static org.lwjgl.opengl.GL11.glEnable;
 
-public class GuiOptions
-    extends GuiScreen
+public class OptionsScreen
+    extends Screen
 {
     private static final int TOP_SPACING = 24;
     private static final int BUTTON_SPACING = 4;
@@ -43,17 +43,17 @@ public class GuiOptions
     private OptionsPage selectedPage;
     private OptionsComponent clickedComponent;
     private int clickedComponentY;
-    private GuiRenderItem renderItem = null;
+    private ItemElement renderItem = null;
 
     private boolean doOptionsScroll = true;
     private boolean doPagesListScroll = true;
 
-    public GuiOptions(GuiScreen parent)
+    public OptionsScreen(Screen parent)
     {
         this(parent, OptionsPages.GENERAL);
     }
 
-    public GuiOptions(GuiScreen parent, OptionsPage selectedPage)
+    public OptionsScreen(Screen parent, OptionsPage selectedPage)
     {
         super(parent);
         this.selectedPage = selectedPage;
@@ -64,7 +64,7 @@ public class GuiOptions
     {
         super.init();
 
-        controlList.add(new GuiButton(0, width / 2 - 100, height - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.options.button.done")));
+        buttons.add(new ButtonElement(0, width / 2 - 100, height - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.options.button.done")));
 
         top = TOP_SPACING;
         bottom = height - (BUTTON_SPACING + 20 + BUTTON_SPACING);
@@ -72,35 +72,35 @@ public class GuiOptions
         optionsScrollRegionHeight = bottom - top;
         pagesListScrollRegionHeight = bottom - top;
 
-        this.renderItem = new GuiRenderItem(mc);
+        this.renderItem = new ItemElement(mc);
 
         this.selectedPage.initComponents(mc);
     }
 
     @Override
-    public void keyTyped(char c, int key, int mouseX, int mouseY) {
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
         if (pickingKeyBinding != null && pickingKeyBindingComponent != null) {
-            if (key == Keyboard.KEY_ESCAPE) {
+            if (eventKey == Keyboard.KEY_ESCAPE) {
                 pickingKeyBinding = null;
                 pickingKeyBindingComponent = null;
                 return;
             }
-            pickingKeyBinding.bind(InputDevice.keyboard, key);
+            pickingKeyBinding.bind(InputDevice.keyboard, eventKey);
             pickingKeyBindingComponent.update();
             pickingKeyBinding = null;
             pickingKeyBindingComponent = null;
             return;
         }
 
-        if (key == Keyboard.KEY_ESCAPE)
+        if (eventKey == Keyboard.KEY_ESCAPE)
         {
-            mc.displayGuiScreen(getParentScreen());
+            mc.displayScreen(getParentScreen());
         }
         else
         {
             for (OptionsComponent component : selectedPage.getComponents())
             {
-                component.onKeyPress(key, c);
+                component.onKeyPress(eventKey, eventCharacter);
             }
         }
     }
@@ -127,7 +127,7 @@ public class GuiOptions
                 textColor = 0xFFFFFFA0;
             }
             renderItem.render(page.getIcon(), x, y2 + (PAGE_BUTTON_HEIGHT / 2) - 9);
-            mc.fontRenderer.drawStringWithShadow(translated, x + 19, y2 + (PAGE_BUTTON_HEIGHT / 2) - 4, textColor);
+            mc.font.drawStringWithShadow(translated, x + 19, y2 + (PAGE_BUTTON_HEIGHT / 2) - 4, textColor);
             y2 += PAGE_BUTTON_HEIGHT;
         }
     }
@@ -141,19 +141,19 @@ public class GuiOptions
     }
 
     @Override
-    protected void buttonPressed(GuiButton guibutton) {
-        super.buttonPressed(guibutton);
+    protected void buttonClicked(ButtonElement button) {
+        super.buttonClicked(button);
 
-        if (guibutton.id == 0)
+        if (button.id == 0)
         {
-            mc.displayGuiScreen(getParentScreen());
+            mc.displayScreen(getParentScreen());
             mc.texturePackList.refreshIfReady(); // Sets the texturepacks on menu close
         }
     }
 
     @Override
-    public void onClosed() {
-        super.onClosed();
+    public void removed() {
+        super.removed();
         mc.gameSettings.saveOptions();
     }
 
@@ -198,19 +198,19 @@ public class GuiOptions
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float renderPartialTicks)
+    public void render(int xm, int ym, float renderPartialTicks)
     {
         if (pickingKeyBinding != null && pickingKeyBindingComponent != null) {
-            mouseX = -1;
-            mouseY = -1;
-        } else if (doOptionsScroll && mouseX > pagesListWidth + SEPARATOR_WIDTH + PADDING && mouseX < width) {
+            xm = -1;
+            ym = -1;
+        } else if (doOptionsScroll && xm > pagesListWidth + SEPARATOR_WIDTH + PADDING && xm < width) {
             if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) {
                 scrollOptions(Mouse.getDWheel() / -0.01f);
             } else {
                 scrollOptions(Mouse.getDWheel() / -0.05f);
             }
             onScrollOptions();
-        } else if (doPagesListScroll && mouseX >= 0 && mouseX <= pagesListWidth) {
+        } else if (doPagesListScroll && xm >= 0 && xm <= pagesListWidth) {
             if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) {
                 scrollPagesList(Mouse.getDWheel() / -0.01f);
             } else {
@@ -223,13 +223,13 @@ public class GuiOptions
         pageWidth = width - (pagesListWidth + SEPARATOR_WIDTH + (PADDING * 2));
         I18n i18n = I18n.getInstance();
 
-        drawDefaultBackground();
+        renderBackground();
         overlayBackground(0, width, 0, top);
         overlayBackground(0, width, bottom, height);
 
         Scissor.enable(0, top, width, bottom - top);
-        if (mouseY >= top && mouseY <= bottom) {
-            drawPageItems(pagesListWidth + SEPARATOR_WIDTH + PADDING, top - (int) optionsScrollAmount, pageWidth - 8, mouseX, mouseY);
+        if (ym >= top && ym <= bottom) {
+            drawPageItems(pagesListWidth + SEPARATOR_WIDTH + PADDING, top - (int) optionsScrollAmount, pageWidth - 8, xm, ym);
         } else {
             drawPageItems(pagesListWidth + SEPARATOR_WIDTH + PADDING, top - (int) optionsScrollAmount, pageWidth - 8, -1, -1);
         }
@@ -241,8 +241,8 @@ public class GuiOptions
         if (pagesListHeight < bottom - top) {
             pagesListY = top + (bottom - top - pagesListHeight) / 2;
         }
-        if (mouseY >= top && mouseY <= bottom) {
-            drawPagesListItems(PADDING - 4, pagesListY, pagesListWidth - PADDING, mouseX, mouseY);
+        if (ym >= top && ym <= bottom) {
+            drawPagesListItems(PADDING - 4, pagesListY, pagesListWidth - PADDING, xm, ym);
         } else {
             drawPagesListItems(PADDING - 4, pagesListY, pagesListWidth - PADDING, -1, -1);
         }
@@ -287,16 +287,16 @@ public class GuiOptions
         overlayBackground(pagesListWidth, pagesListWidth + SEPARATOR_WIDTH, top, bottom);
 
         String titleLanguageKey = "gui.options.title";
-        drawStringCentered(fontRenderer, i18n.translateKey(titleLanguageKey), width / 2, 5, 0xffffff);
+        drawStringCentered(font, i18n.translateKey(titleLanguageKey), width / 2, 5, 0xffffff);
 
-        drawOptionsScrollBar(mouseX, mouseY);
-        drawPagesListScrollBar(mouseX, mouseY);
+        drawOptionsScrollBar(xm, ym);
+        drawPagesListScrollBar(xm, ym);
 
-        super.drawScreen(mouseX, mouseY, renderPartialTicks);
+        super.render(xm, ym, renderPartialTicks);
 
         if (pickingKeyBinding != null && pickingKeyBindingComponent != null) {
             drawRect(0, 0, width, height, 0xA0000000);
-            drawStringCenteredNoShadow(fontRenderer, i18n.translateKeyAndFormat("gui.options.label.picking_keybinding", i18n.translateKey(pickingKeyBinding.getId())), width / 2, height / 2 - 4, 0xffffff);
+            drawStringCenteredNoShadow(font, i18n.translateKeyAndFormat("gui.options.label.picking_keybinding", i18n.translateKey(pickingKeyBinding.getId())), width / 2, height / 2 - 4, 0xffffff);
         }
     }
 
@@ -391,40 +391,40 @@ public class GuiOptions
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton)
+    public void mouseClicked(int mx, int my, int buttonNum)
     {
         if (pickingKeyBinding != null && pickingKeyBindingComponent != null) {
-            pickingKeyBinding.bind(InputDevice.mouse, mouseButton);
+            pickingKeyBinding.bind(InputDevice.mouse, buttonNum);
             pickingKeyBindingComponent.update();
             pickingKeyBinding = null;
             pickingKeyBindingComponent = null;
             return;
         }
 
-        super.mouseClicked(mouseX, mouseY, mouseButton);
+        super.mouseClicked(mx, my, buttonNum);
 
         int left = pagesListWidth + SEPARATOR_WIDTH + PADDING;
 
-        if (mouseX >= pagesListWidth + SEPARATOR_WIDTH && mouseY >= top && mouseY <= bottom) {
+        if (mx >= pagesListWidth + SEPARATOR_WIDTH && my >= top && my <= bottom) {
             int componentY = top - (int) optionsScrollAmount;
             for (OptionsComponent component : selectedPage.getComponents())
             {
-                if (mouseX >= left && mouseX <= left + pageWidth - PADDING && mouseY >= componentY && mouseY <= componentY + component.getHeight()) {
-                    component.onMouseClick(mouseButton, left, componentY, pageWidth - PADDING, mouseX - left, mouseY - componentY);
+                if (mx >= left && mx <= left + pageWidth - PADDING && my >= componentY && my <= componentY + component.getHeight()) {
+                    component.onMouseClick(buttonNum, left, componentY, pageWidth - PADDING, mx - left, my - componentY);
                     clickedComponent = component;
                     clickedComponentY = componentY;
                     break;
                 }
                 componentY += component.getHeight();
             }
-        } else if (mouseX >= 0 && mouseX <= pagesListWidth && mouseY >= top && mouseY <= bottom) {
+        } else if (mx >= 0 && mx <= pagesListWidth && my >= top && my <= bottom) {
             int pagesListHeight = getTotalPagesListHeight();
             int pagesListY = top - (int) pagesListScrollAmount;
             if (pagesListHeight < bottom - top) {
                 pagesListY = top + (bottom - top - pagesListHeight) / 2;
             }
             for(OptionsPage page : OptionsPageRegistry.getInstance().getPages()) {
-                if (mouseX >= 0 && mouseX <= pagesListWidth && mouseY >= pagesListY && mouseY <= pagesListY + PAGE_BUTTON_HEIGHT) {
+                if (mx >= 0 && mx <= pagesListWidth && my >= pagesListY && my <= pagesListY + PAGE_BUTTON_HEIGHT) {
                     optionsScrollAmount = 0;
                     selectedPage = page;
                     this.selectedPage.initComponents(mc);
@@ -436,42 +436,42 @@ public class GuiOptions
             }
         }
 
-        clickX = mouseX;
-        clickY = mouseY;
+        clickX = mx;
+        clickY = my;
     }
 
     @Override
-    public void mouseMovedOrButtonReleased(int mouseX, int mouseY, int mouseButton) {
+    public void mouseReleased(int mx, int my, int buttonNum) {
         if (pickingKeyBinding != null && pickingKeyBindingComponent != null) return;
 
-        super.mouseMovedOrButtonReleased(mouseX, mouseY, mouseButton);
+        super.mouseReleased(mx, my, buttonNum);
 
         int left = pagesListWidth + SEPARATOR_WIDTH + PADDING;
-        if (mouseY >= top && mouseY <= bottom) {
+        if (my >= top && my <= bottom) {
             if (clickedComponent != null) {
-                if (mouseButton >= 0) {
-                    clickedComponent.onMouseRelease(mouseButton, left, clickedComponentY, pageWidth, mouseX - left, mouseY - clickedComponentY);
+                if (buttonNum >= 0) {
+                    clickedComponent.onMouseRelease(buttonNum, left, clickedComponentY, pageWidth, mx - left, my - clickedComponentY);
                     clickedComponent = null;
                 } else {
-                    clickedComponent.onMouseMove(left, clickedComponentY, pageWidth, mouseX - left, mouseY - clickedComponentY);
+                    clickedComponent.onMouseMove(left, clickedComponentY, pageWidth, mx - left, my - clickedComponentY);
                 }
             }
         }
 
-        if(mouseButton >= 0) {
+        if(buttonNum >= 0) {
             clickX = null;
             clickY = null;
         }
     }
 
     @Override
-    public void drawDefaultBackground() {
-        super.drawDefaultBackground();
+    public void renderBackground() {
+        super.renderBackground();
 
         if (mc.theWorld == null)
         {
             Tessellator tessellator = Tessellator.instance;
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
             float scale = 32F;
             tessellator.startDrawingQuads();
@@ -502,7 +502,7 @@ public class GuiOptions
         if (mc.theWorld == null)
         {
             Tessellator tessellator = Tessellator.instance;
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
             float scale = 32F;
             tessellator.startDrawingQuads();
diff --git a/src/main/java/net/minecraft/client/gui/options/GuiOptionButton.java b/src/main/java/net/minecraft/client/gui/options/OverlayButtonElement.java
similarity index 67%
rename from src/main/java/net/minecraft/client/gui/options/GuiOptionButton.java
rename to src/main/java/net/minecraft/client/gui/options/OverlayButtonElement.java
index a5f60d32d..adcbe7cd4 100644
--- a/src/main/java/net/minecraft/client/gui/options/GuiOptionButton.java
+++ b/src/main/java/net/minecraft/client/gui/options/OverlayButtonElement.java
@@ -1,17 +1,17 @@
 package net.minecraft.client.gui.options;
 
-import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.client.option.GameSettings;
 import net.minecraft.core.util.helper.Listener;
 import net.minecraft.core.util.helper.Toggleable;
 import net.minecraft.client.option.Option;
 
-public class GuiOptionButton<E extends Option<?> & Toggleable> extends GuiButton implements Listener<GuiButton>{
+public class OverlayButtonElement<E extends Option<?> & Toggleable> extends ButtonElement implements Listener<ButtonElement>{
 
 	public final GameSettings settings;
 	public final E option;
 	
-	public GuiOptionButton(GameSettings settings, E option) {
+	public OverlayButtonElement(GameSettings settings, E option) {
 		super(0, 0, 0, 0, 0, null);
 		
 		this.settings = settings;
@@ -23,7 +23,7 @@ public class GuiOptionButton<E extends Option<?> & Toggleable> extends GuiButton
 	}
 
 	@Override
-	public void listen(GuiButton e) {
+	public void listen(ButtonElement e) {
 		option.toggle();
 		
 		updateString();
diff --git a/src/main/java/net/minecraft/client/gui/options/components/AvailableTexturePackListComponent.java b/src/main/java/net/minecraft/client/gui/options/components/AvailableTexturePackListComponent.java
index 86a3cc0b2..0634b81e7 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/AvailableTexturePackListComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/AvailableTexturePackListComponent.java
@@ -5,12 +5,12 @@ import static net.minecraft.client.gui.options.components.ButtonComponent.*;
 import java.util.ArrayList;
 import java.util.List;
 
-import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.core.sound.SoundCategory;
 import org.lwjgl.opengl.GL11;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texturepack.TexturePack;
 import net.minecraft.client.util.helper.Colors;
@@ -73,7 +73,7 @@ public class AvailableTexturePackListComponent
     @Override
     public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) {
         if (availablePacks.isEmpty()) {
-            mc.fontRenderer.drawCenteredString(I18n.getInstance().translateKey("gui.options.page.texture_packs.label.no_packs"), x + width / 2, y + 4, 0x5F7F7F7F);
+            mc.font.drawCenteredString(I18n.getInstance().translateKey("gui.options.page.texture_packs.label.no_packs"), x + width / 2, y + 4, 0x5F7F7F7F);
         }
         for (int i = 0; i < availablePacks.size(); i++) {
             TexturePackButton button = availablePacks.get(i);
@@ -110,7 +110,7 @@ public class AvailableTexturePackListComponent
     }
 
     private static class TexturePackButton {
-        private GuiButton button;
+        private ButtonElement button;
         public final int index;
         public final TexturePack texturePack;
         public final int height = BUTTON_HEIGHT;
@@ -118,7 +118,7 @@ public class AvailableTexturePackListComponent
         public TexturePackButton(int index, TexturePack texturePack) {
             this.index = index;
             this.texturePack = texturePack;
-            button = new GuiButton(0, 0, 0, 20, 20, "+");
+            button = new ButtonElement(0, 0, 0, 20, 20, "+");
         }
 
         public boolean isClickable() {
@@ -127,7 +127,7 @@ public class AvailableTexturePackListComponent
 
         public void render(int x, int y, int width, int mouseX, int mouseY, int index, boolean hovered) {
             Tessellator tessellator = Tessellator.instance;
-            FontRenderer fontRenderer = mc.fontRenderer;
+            Font font = mc.font;
 
             setupButton(x, y, width, mouseX, mouseY);
 
@@ -170,21 +170,21 @@ public class AvailableTexturePackListComponent
 
 			if(format == Global.TEXTURE_PACK_FORMAT) {
 				// Correct version
-				fontRenderer.drawString(texturePack.manifest.getName(), x + height + 2, y + 1, 0xFFFFFF);
-				fontRenderer.drawString(texturePack.manifest.getDescriptionLine1(), x + height + 2, y + 12, 0x808080);
-				fontRenderer.drawString(texturePack.manifest.getDescriptionLine2(), x + height + 2, y + 22, 0x808080);
+				font.drawString(texturePack.manifest.getName(), x + height + 2, y + 1, 0xFFFFFF);
+				font.drawString(texturePack.manifest.getDescriptionLine1(), x + height + 2, y + 12, 0x808080);
+				font.drawString(texturePack.manifest.getDescriptionLine2(), x + height + 2, y + 22, 0x808080);
 			}else if(format == -1) {
 				// Manifest error
-				fontRenderer.drawString(TextFormatting.RED + texturePack.manifest.getName(), x + height + 2, y + 1, 0xFFFFFF);
-				fontRenderer.drawString(texturePack.manifest.getDescriptionLine1(), x + height + 2, y + 12, 0x808080);
-				fontRenderer.drawString(texturePack.manifest.getDescriptionLine2(), x + height + 2, y + 22, 0x808080);
+				font.drawString(TextFormatting.RED + texturePack.manifest.getName(), x + height + 2, y + 1, 0xFFFFFF);
+				font.drawString(texturePack.manifest.getDescriptionLine1(), x + height + 2, y + 12, 0x808080);
+				font.drawString(texturePack.manifest.getDescriptionLine2(), x + height + 2, y + 22, 0x808080);
 				rgbVersion = Colors.allChatColors[TextFormatting.RED.id].getARGB();
 			}else {
 				// Wrong texture pack version
 				I18n i18n = I18n.getInstance();
-				fontRenderer.drawString(TextFormatting.RED + texturePack.manifest.getName(), x + height + 2, y + 1, 0xFFFFFF);
-				fontRenderer.drawString(i18n.translateKey("gui.options.page.texture_packs.label.outdated_pack.1"), x + height + 2, y + 12, 0x808080);
-				fontRenderer.drawString(i18n.translateKey("gui.options.page.texture_packs.label.outdated_pack.2"), x + height + 2, y + 22, 0x808080);
+				font.drawString(TextFormatting.RED + texturePack.manifest.getName(), x + height + 2, y + 1, 0xFFFFFF);
+				font.drawString(i18n.translateKey("gui.options.page.texture_packs.label.outdated_pack.1"), x + height + 2, y + 12, 0x808080);
+				font.drawString(i18n.translateKey("gui.options.page.texture_packs.label.outdated_pack.2"), x + height + 2, y + 22, 0x808080);
 				rgbVersion = Colors.allChatColors[TextFormatting.RED.id].getARGB();
 			}
 
@@ -194,8 +194,8 @@ public class AvailableTexturePackListComponent
             }
 
             String version = texturePack.manifest.getPackVersion();
-            int versionWidth = fontRenderer.getStringWidth(version);
-            fontRenderer.drawString(texturePack.manifest.getPackVersion(), x + width - versionWidth - 2, y + 1, rgbVersion);
+            int versionWidth = font.getStringWidth(version);
+            font.drawString(texturePack.manifest.getPackVersion(), x + width - versionWidth - 2, y + 1, rgbVersion);
         }
         public void setupButton(int x, int y, int width, int mouseX, int mouseY){
             button.setX(x + width - button.width - 1);
diff --git a/src/main/java/net/minecraft/client/gui/options/components/BooleanOptionComponent.java b/src/main/java/net/minecraft/client/gui/options/components/BooleanOptionComponent.java
index 360ff2052..c4264b813 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/BooleanOptionComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/BooleanOptionComponent.java
@@ -1,21 +1,21 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiSwitchButton;
+import net.minecraft.client.gui.SwitchElement;
 import net.minecraft.client.option.BooleanOption;
 
 public class BooleanOptionComponent
     extends ButtonComponent
 {
     private final BooleanOption option;
-    private final GuiSwitchButton button;
+    private final SwitchElement button;
 
     public BooleanOptionComponent(BooleanOption option)
     {
         super("options." + option.name);
 
         this.option = option;
-        this.button = new GuiSwitchButton(0, 0, 0, 150, 20, this.option.value, "", "");
+        this.button = new SwitchElement(0, 0, 0, 150, 20, this.option.value, "", "");
         this.button.setOn(this.option.value);
         this.button.displayString = this.option.getDisplayStringValue();
     }
diff --git a/src/main/java/net/minecraft/client/gui/options/components/ButtonComponent.java b/src/main/java/net/minecraft/client/gui/options/components/ButtonComponent.java
index fb765e2bf..f6ef7624a 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/ButtonComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/ButtonComponent.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.sound.SoundCategory;
@@ -20,12 +20,12 @@ public abstract class ButtonComponent
 
     private final String translationKey;
 
-    protected final GuiButton resetButton;
+    protected final ButtonElement resetButton;
 
     public ButtonComponent(String translationKey)
     {
         this.translationKey = translationKey;
-        this.resetButton = new GuiButton(0, 0, 0, 20, 20, "")
+        this.resetButton = new ButtonElement(0, 0, 0, 20, 20, "")
             .setTextures("minecraft:gui/misc/icon_reset", "minecraft:gui/misc/icon_reset_highlighted", "minecraft:gui/misc/icon_reset");
     }
 
@@ -42,7 +42,7 @@ public abstract class ButtonComponent
     @Override
     public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY)
     {
-        FontRenderer fr = mc.fontRenderer;
+        Font fr = mc.font;
         String translated = I18n.getInstance().translateKey(translationKey);
         int textColor = 0xFFFFFFFF;
         if (relativeMouseX >= 0 && relativeMouseX <= width && relativeMouseY >= COMPONENT_SPACING && relativeMouseY <= getHeight() - COMPONENT_SPACING) {
diff --git a/src/main/java/net/minecraft/client/gui/options/components/DifficultyOptionComponent.java b/src/main/java/net/minecraft/client/gui/options/components/DifficultyOptionComponent.java
index b592a19c0..0fd3d1677 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/DifficultyOptionComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/DifficultyOptionComponent.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiSliderInteger;
+import net.minecraft.client.gui.IntegerSliderElement;
 import net.minecraft.client.option.EnumOption;
 import net.minecraft.client.option.enums.Difficulty;
 import net.minecraft.core.lang.I18n;
@@ -9,12 +9,12 @@ import net.minecraft.core.lang.I18n;
 public class DifficultyOptionComponent extends ButtonComponent {
 
     protected final EnumOption<Difficulty> option;
-    protected final GuiSliderInteger slider;
+    protected final IntegerSliderElement slider;
 
     public DifficultyOptionComponent(EnumOption<Difficulty> difficultyOption) {
         super("options." + difficultyOption.name);
         option = difficultyOption;
-        this.slider = new GuiSliderInteger(0, 0, 0, 150, 20, option);
+        this.slider = new IntegerSliderElement(0, 0, 0, 150, 20, option);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/options/components/FloatOptionComponent.java b/src/main/java/net/minecraft/client/gui/options/components/FloatOptionComponent.java
index 0f1f0e802..92b07cd86 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/FloatOptionComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/FloatOptionComponent.java
@@ -1,21 +1,21 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiSlider;
+import net.minecraft.client.gui.SliderElement;
 import net.minecraft.client.option.FloatOption;
 
 public class FloatOptionComponent
         extends ButtonComponent
 {
     private final FloatOption option;
-    private final GuiSlider slider;
+    private final SliderElement slider;
 
     public FloatOptionComponent(FloatOption option)
     {
         super("options." + option.name);
 
         this.option = option;
-        this.slider = new GuiSlider(0, 0, 0, 150, 20, this.option.getDisplayStringValue(), this.option.value);
+        this.slider = new SliderElement(0, 0, 0, 150, 20, this.option.getDisplayStringValue(), this.option.value);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/options/components/IntegerOptionComponent.java b/src/main/java/net/minecraft/client/gui/options/components/IntegerOptionComponent.java
index 725ec1966..e6e32b63f 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/IntegerOptionComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/IntegerOptionComponent.java
@@ -1,21 +1,21 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.client.option.IntegerOption;
 
 public class IntegerOptionComponent
     extends ButtonComponent
 {
     private final IntegerOption option;
-    private final GuiButton button;
+    private final ButtonElement button;
 
     public IntegerOptionComponent(IntegerOption option)
     {
         super("options." + option.name);
 
         this.option = option;
-        this.button = new GuiButton(0, 0, 0, 150, 20, this.option.getDisplayString());
+        this.button = new ButtonElement(0, 0, 0, 150, 20, this.option.getDisplayString());
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/options/components/KeyBindingComponent.java b/src/main/java/net/minecraft/client/gui/options/components/KeyBindingComponent.java
index 6a7e0db91..defa9a0ff 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/KeyBindingComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/KeyBindingComponent.java
@@ -1,33 +1,33 @@
 package net.minecraft.client.gui.options.components;
 
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.options.GuiOptions;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.options.OptionsScreen;
 import net.minecraft.client.option.KeyBinding;
 
 public class KeyBindingComponent
         extends ButtonComponent
 {
     private final KeyBinding keyBinding;
-    private final GuiButton guiButton;
-    private final GuiButton clearButton;
+    private final ButtonElement keyButton;
+    private final ButtonElement clearButton;
 
     public KeyBindingComponent(KeyBinding keyBinding)
     {
         super(keyBinding.getId());
 
         this.keyBinding = keyBinding;
-        this.guiButton = new GuiButton(0, 0, 0, 150, 20, keyBinding.getKeyName());
-        this.clearButton = new GuiButton(0, 0, 0, 12, 20, "X");
+        this.keyButton = new ButtonElement(0, 0, 0, 150, 20, keyBinding.getKeyName());
+        this.clearButton = new ButtonElement(0, 0, 0, 12, 20, "X");
     }
 
     @Override
     protected void buttonClicked(int mouseButton, int x, int y, int width, int height, int relativeMouseX, int relativeMouseY) {
-        if (this.clearButton.mouseClicked(mc, this.clearButton.xPosition + (relativeMouseX - this.guiButton.width), this.clearButton.yPosition + relativeMouseY)) {
+        if (this.clearButton.mouseClicked(mc, this.clearButton.xPosition + (relativeMouseX - this.keyButton.width), this.clearButton.yPosition + relativeMouseY)) {
             this.keyBinding.unbind();
-            this.guiButton.displayString = this.keyBinding.getKeyName();
+            this.keyButton.displayString = this.keyBinding.getKeyName();
         } else {
-            GuiOptions.pickingKeyBinding = keyBinding;
-            GuiOptions.pickingKeyBindingComponent = this;
+            OptionsScreen.pickingKeyBinding = keyBinding;
+            OptionsScreen.pickingKeyBindingComponent = this;
         }
     }
 
@@ -36,14 +36,14 @@ public class KeyBindingComponent
     {
         super.renderButton(x, y, relativeButtonX, relativeButtonY, buttonWidth, buttonHeight, relativeMouseX, relativeMouseY);
 
-        this.guiButton.xPosition = x + relativeButtonX;
-        this.guiButton.yPosition = y + relativeButtonY;
-        this.guiButton.width = buttonWidth - this.clearButton.width;
-        this.guiButton.height = buttonHeight;
+        this.keyButton.xPosition = x + relativeButtonX;
+        this.keyButton.yPosition = y + relativeButtonY;
+        this.keyButton.width = buttonWidth - this.clearButton.width;
+        this.keyButton.height = buttonHeight;
 
-        this.guiButton.drawButton(mc, x + relativeMouseX, y + relativeMouseY);
+        this.keyButton.drawButton(mc, x + relativeMouseX, y + relativeMouseY);
 
-        this.clearButton.xPosition = x + relativeButtonX + this.guiButton.width;
+        this.clearButton.xPosition = x + relativeButtonX + this.keyButton.width;
         this.clearButton.yPosition = y + relativeButtonY;
         this.clearButton.enabled = this.keyBinding.isBound();
 
@@ -51,13 +51,13 @@ public class KeyBindingComponent
     }
 
     public void update() {
-        this.guiButton.displayString = this.keyBinding.getKeyName();
+        this.keyButton.displayString = this.keyBinding.getKeyName();
     }
 
     @Override
     public void resetValue() {
         keyBinding.resetToDefault();
-        guiButton.displayString = keyBinding.getKeyName();
+        keyButton.displayString = keyBinding.getKeyName();
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/options/components/LanguagePackListComponent.java b/src/main/java/net/minecraft/client/gui/options/components/LanguagePackListComponent.java
index 25f24d7a3..f5ab95fb5 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/LanguagePackListComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/LanguagePackListComponent.java
@@ -1,12 +1,14 @@
 package net.minecraft.client.gui.options.components;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.lang.Language;
 import net.minecraft.core.lang.LanguageSeeker;
 import org.lwjgl.opengl.GL11;
+import org.slf4j.Logger;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -17,6 +19,7 @@ import static net.minecraft.client.gui.options.components.ButtonComponent.mc;
 
 public class LanguagePackListComponent
     implements OptionsComponent {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private static final int BUTTON_HEIGHT = 32;
 
     private List<Language> languages = null;
@@ -38,7 +41,7 @@ public class LanguagePackListComponent
                 buttons.add(new LanguagePackComponent(i, language));
             }
         } catch (IOException e) {
-            e.printStackTrace();
+            LOGGER.error("Exception while getting available languages!", e);
         }
     }
 
@@ -83,7 +86,7 @@ public class LanguagePackListComponent
     }
 
     private static class LanguagePackComponent {
-    	private Minecraft mc = Minecraft.getMinecraft(this);
+    	private final Minecraft mc = Minecraft.getMinecraft(this);
         public final int index;
         public final Language languagePack;
         public final int height = BUTTON_HEIGHT;
@@ -94,7 +97,7 @@ public class LanguagePackListComponent
         }
 
         public void render(int x, int y, int width, int mouseX, int mouseY) {
-            FontRenderer textRenderer = mc.fontRenderer;
+            Font textRenderer = mc.font;
             Tessellator tessellator = Tessellator.instance;
 
             if (mc.gameSettings.language.value.equals(languagePack.getId())) {
diff --git a/src/main/java/net/minecraft/client/gui/options/components/OptionsCategory.java b/src/main/java/net/minecraft/client/gui/options/components/OptionsCategory.java
index 25d4b78ac..6cc34375a 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/OptionsCategory.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/OptionsCategory.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiRenderItem;
+import net.minecraft.client.gui.ItemElement;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.sound.SoundCategory;
@@ -13,7 +13,7 @@ public class OptionsCategory
     implements OptionsComponent
 {
     private static final Minecraft mc = Minecraft.getMinecraft(OptionsCategory.class);
-    private static final GuiRenderItem renderItem = new GuiRenderItem(mc);
+    private static final ItemElement renderItem = new ItemElement(mc);
     private static final int PADDING = 2;
     private static final int TOP_SPACING = PADDING + 10 + 10 + PADDING;
     private static final int COMPONENT_LEFT_MARGIN = 16;
@@ -81,7 +81,7 @@ public class OptionsCategory
         {
             textColor = 0xFFFFA0;
         }
-        mc.fontRenderer.drawStringWithShadow((collapsed ? "▷" : "▽"), x, y + PADDING + 10, textColor);
+        mc.font.drawStringWithShadow((collapsed ? "▷" : "▽"), x, y + PADDING + 10, textColor);
 
         int xOffset = 10;
         if (icon != null)
@@ -89,7 +89,7 @@ public class OptionsCategory
             renderItem.render(icon, x + 11, y + PADDING + 5);
             xOffset += 20;
         }
-        mc.fontRenderer.drawStringWithShadow(i18n.translateKey(translationKey), x + xOffset, y + PADDING + 10, textColor);
+        mc.font.drawStringWithShadow(i18n.translateKey(translationKey), x + xOffset, y + PADDING + 10, textColor);
         if (!collapsed) {
             int componentY = TOP_SPACING;
             for (OptionsComponent component : components)
diff --git a/src/main/java/net/minecraft/client/gui/options/components/SearchFieldComponent.java b/src/main/java/net/minecraft/client/gui/options/components/SearchFieldComponent.java
index 8949dec66..081d24638 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/SearchFieldComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/SearchFieldComponent.java
@@ -1,9 +1,8 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiRenderItem;
-import net.minecraft.client.gui.GuiTextField;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.TextFieldElement;
 import net.minecraft.client.gui.options.data.OptionsPage;
 import net.minecraft.client.gui.options.data.OptionsPageRegistry;
 import net.minecraft.client.gui.text.TextFieldEditor;
@@ -14,12 +13,12 @@ import java.util.ArrayList;
 import java.util.List;
 
 public class SearchFieldComponent
-    implements OptionsComponent, GuiTextField.ITextChangeListener {
+    implements OptionsComponent, TextFieldElement.ITextChangeListener {
     private static final Minecraft mc = Minecraft.getMinecraft(SearchFieldComponent.class);
 
     private static final int PADDING = 4;
 
-    private final GuiTextField textField;
+    private final TextFieldElement textField;
     private final TextFieldEditor editor;
 
     private final List<OptionsComponent> components = new ArrayList<>();
@@ -27,14 +26,14 @@ public class SearchFieldComponent
     private OptionsComponent clickedComponent = null;
     private int clickedComponentY = 0;
 
-    private GuiButton clearButton;
+    private ButtonElement clearButton;
 
     public SearchFieldComponent() {
-        textField = new GuiTextField(null, mc.fontRenderer, 0, 0, 150, 18, "", "Search...");
+        textField = new TextFieldElement(null, mc.font, 0, 0, 150, 18, "", "Search...");
         textField.setMaxStringLength(20);
         textField.setTextChangeListener(this);
         editor = new TextFieldEditor(textField);
-        clearButton = new GuiButton(0, 0, 0, 12, 20, "X");
+        clearButton = new ButtonElement(0, 0, 0, 12, 20, "X");
     }
 
     @Override
@@ -129,7 +128,7 @@ public class SearchFieldComponent
     }
 
     @Override
-    public void textChanged(GuiTextField textField) {
+    public void textChanged(TextFieldElement textField) {
         updateSearchResults(textField.getText());
     }
 
diff --git a/src/main/java/net/minecraft/client/gui/options/components/SelectedTexturePackListComponent.java b/src/main/java/net/minecraft/client/gui/options/components/SelectedTexturePackListComponent.java
index 1a3fa786a..9dc0737ca 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/SelectedTexturePackListComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/SelectedTexturePackListComponent.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.render.texturepack.TexturePack;
 import net.minecraft.client.util.helper.Colors;
@@ -64,7 +64,7 @@ public class SelectedTexturePackListComponent implements OptionsComponent {
     @Override
     public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) {
         if (selectedPacks.isEmpty()) {
-            mc.fontRenderer.drawCenteredString(I18n.getInstance().translateKey("gui.options.page.texture_packs.label.no_packs"), x + width / 2, y + 4, 0x5F7F7F7F);
+            mc.font.drawCenteredString(I18n.getInstance().translateKey("gui.options.page.texture_packs.label.no_packs"), x + width / 2, y + 4, 0x5F7F7F7F);
         }
         for (TexturePackButton button : selectedPacks) {
             if (button == draggedButton) continue;
@@ -121,7 +121,7 @@ public class SelectedTexturePackListComponent implements OptionsComponent {
     }
 
     private static class TexturePackButton {
-        private GuiButton button;
+        private ButtonElement button;
         public boolean draggable;
         public final TexturePack texturePack;
         public final int height = BUTTON_HEIGHT;
@@ -134,7 +134,7 @@ public class SelectedTexturePackListComponent implements OptionsComponent {
             this.texturePack = texturePack;
             this.xPos = xPos;
             this.yPos = yPos;
-            button = new GuiButton(0, 0, 0, 20, 20, "-");
+            button = new ButtonElement(0, 0, 0, 20, 20, "-");
         }
 
         public boolean isClickable() {
@@ -207,7 +207,7 @@ public class SelectedTexturePackListComponent implements OptionsComponent {
 
         public void render(SelectedTexturePackListComponent component, int x, int y, int width, int mouseX, int mouseY) {
             Tessellator tessellator = Tessellator.instance;
-            FontRenderer fontRenderer = mc.fontRenderer;
+            Font font = mc.font;
 
             setupButton(x, y, width, mouseX, mouseY);
 
@@ -257,21 +257,21 @@ public class SelectedTexturePackListComponent implements OptionsComponent {
 
             if(format == Global.TEXTURE_PACK_FORMAT) {
                 // Correct version
-                fontRenderer.drawString(texturePack.manifest.getName(),             x + xPos + height + 2, y + yPos + 1, 0xFFFFFF);
-                fontRenderer.drawString(texturePack.manifest.getDescriptionLine1(), x + xPos + height + 2, y + yPos + 12, 0x808080);
-                fontRenderer.drawString(texturePack.manifest.getDescriptionLine2(), x + xPos + height + 2, y + yPos + 22, 0x808080);
+                font.drawString(texturePack.manifest.getName(),             x + xPos + height + 2, y + yPos + 1, 0xFFFFFF);
+                font.drawString(texturePack.manifest.getDescriptionLine1(), x + xPos + height + 2, y + yPos + 12, 0x808080);
+                font.drawString(texturePack.manifest.getDescriptionLine2(), x + xPos + height + 2, y + yPos + 22, 0x808080);
             }else if(format == -1) {
                 // Manifest error
-                fontRenderer.drawString(TextFormatting.RED + texturePack.manifest.getName(), x + xPos + height + 2, y + yPos + 1, 0xFFFFFF);
-                fontRenderer.drawString(texturePack.manifest.getDescriptionLine1(),          x + xPos + height + 2, y + yPos + 12, 0x808080);
-                fontRenderer.drawString(texturePack.manifest.getDescriptionLine2(),          x + xPos + height + 2, y + yPos + 22, 0x808080);
+                font.drawString(TextFormatting.RED + texturePack.manifest.getName(), x + xPos + height + 2, y + yPos + 1, 0xFFFFFF);
+                font.drawString(texturePack.manifest.getDescriptionLine1(),          x + xPos + height + 2, y + yPos + 12, 0x808080);
+                font.drawString(texturePack.manifest.getDescriptionLine2(),          x + xPos + height + 2, y + yPos + 22, 0x808080);
                 rgbVersion = Colors.allChatColors[TextFormatting.RED.id].getARGB();
             }else {
                 // Wrong texture pack version
                 I18n i18n = I18n.getInstance();
-                fontRenderer.drawString(TextFormatting.RED + texturePack.manifest.getName(),                            x + xPos + height + 2, y + yPos + 1, 0xFFFFFF);
-                fontRenderer.drawString(i18n.translateKey("gui.options.page.texture_packs.label.outdated_pack.1"),  x + xPos + height + 2, y + yPos + 12, 0x808080);
-                fontRenderer.drawString(i18n.translateKey("gui.options.page.texture_packs.label.outdated_pack.2"),  x + xPos + height + 2, y + yPos + 22, 0x808080);
+                font.drawString(TextFormatting.RED + texturePack.manifest.getName(),                            x + xPos + height + 2, y + yPos + 1, 0xFFFFFF);
+                font.drawString(i18n.translateKey("gui.options.page.texture_packs.label.outdated_pack.1"),  x + xPos + height + 2, y + yPos + 12, 0x808080);
+                font.drawString(i18n.translateKey("gui.options.page.texture_packs.label.outdated_pack.2"),  x + xPos + height + 2, y + yPos + 22, 0x808080);
                 rgbVersion = Colors.allChatColors[TextFormatting.RED.id].getARGB();
             }
 
@@ -281,8 +281,8 @@ public class SelectedTexturePackListComponent implements OptionsComponent {
             }
 
             String version = texturePack.manifest.getPackVersion();
-            int versionWidth = fontRenderer.getStringWidth(version);
-            fontRenderer.drawString(texturePack.manifest.getPackVersion(), x + xPos + width - versionWidth - 2, y + yPos + 1, rgbVersion);
+            int versionWidth = font.getStringWidth(version);
+            font.drawString(texturePack.manifest.getPackVersion(), x + xPos + width - versionWidth - 2, y + yPos + 1, rgbVersion);
         }
         public void setupButton(int x, int y, int width, int mouseX, int mouseY){
             button.setX(x + xPos + width - button.width - 1);
diff --git a/src/main/java/net/minecraft/client/gui/options/components/ShortcutComponent.java b/src/main/java/net/minecraft/client/gui/options/components/ShortcutComponent.java
index aa26d6764..b77b61c1a 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/ShortcutComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/ShortcutComponent.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.sound.SoundCategory;
 
@@ -12,13 +12,13 @@ public class ShortcutComponent
     private static final int BUTTON_WIDTH = 200;
 
     protected final String translationKey;
-    protected final GuiButton button;
+    protected final ButtonElement button;
     protected final Runnable action;
 
     public ShortcutComponent(String translationKey, Runnable action) {
         this.translationKey = translationKey;
         this.action = action;
-        this.button = new GuiButton(0, 0, 0, BUTTON_WIDTH, 20, "");
+        this.button = new ButtonElement(0, 0, 0, BUTTON_WIDTH, 20, "");
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/options/components/ToggleableOptionComponent.java b/src/main/java/net/minecraft/client/gui/options/components/ToggleableOptionComponent.java
index 3e5b789a0..24fe3c894 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/ToggleableOptionComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/ToggleableOptionComponent.java
@@ -1,21 +1,21 @@
 package net.minecraft.client.gui.options.components;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiSliderInteger;
+import net.minecraft.client.gui.IntegerSliderElement;
 import net.minecraft.client.option.ToggleableOption;
 
 public class ToggleableOptionComponent<E>
         extends ButtonComponent
 {
     protected final ToggleableOption<E> option;
-    protected final GuiSliderInteger slider;
+    protected final IntegerSliderElement slider;
 
     public ToggleableOptionComponent(ToggleableOption<E> option)
     {
         super("options." + option.name);
 
         this.option = option;
-        this.slider = new GuiSliderInteger(0, 0, 0, 150, 20, option);
+        this.slider = new IntegerSliderElement(0, 0, 0, 150, 20, option);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/options/components/TooltipPickerComponent.java b/src/main/java/net/minecraft/client/gui/options/components/TooltipPickerComponent.java
index e09644359..da66be480 100644
--- a/src/main/java/net/minecraft/client/gui/options/components/TooltipPickerComponent.java
+++ b/src/main/java/net/minecraft/client/gui/options/components/TooltipPickerComponent.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.gui.options.components;
 
-import net.minecraft.client.gui.GuiTooltip;
+import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.client.option.ToggleableOption;
 import net.minecraft.client.option.enums.TooltipStyle;
 import org.lwjgl.opengl.GL11;
@@ -8,19 +8,19 @@ import org.lwjgl.opengl.GL11;
 public class TooltipPickerComponent<E>
     extends ToggleableOptionComponent<E> {
 
-    private final GuiTooltip tooltip;
+    private final TooltipElement tooltip;
 
     public TooltipPickerComponent(ToggleableOption<E> option) {
         super(option);
 
-        this.tooltip = new GuiTooltip(mc);
+        this.tooltip = new TooltipElement(mc);
     }
 
     @Override
     protected void renderButton(int x, int y, int relativeButtonX, int relativeButtonY, int buttonWidth, int buttonHeight, int relativeMouseX, int relativeMouseY) {
         super.renderButton(x, y, relativeButtonX, relativeButtonY, buttonWidth, buttonHeight, relativeMouseX, relativeMouseY);
 
-        int stringWidth = mc.fontRenderer.getStringWidth(this.option.getDisplayStringValue());
+        int stringWidth = mc.font.getStringWidth(this.option.getDisplayStringValue());
         int padding = 3;
         int yOffset = 0;
         if (this.option.value != TooltipStyle.DEFAULT) {
diff --git a/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java b/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
index efa2030db..bdd4fed5d 100644
--- a/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
+++ b/src/main/java/net/minecraft/client/gui/options/data/OptionsPages.java
@@ -1,14 +1,13 @@
 package net.minecraft.client.gui.options.data;
 
-import net.betterthanadventure.utils.BiomeFinder;
 import net.betterthanadventure.utils.DataDumper;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiControllerSetup;
-import net.minecraft.client.gui.GuiHudDesigner;
-import net.minecraft.client.gui.GuiSoundTest;
-import net.minecraft.client.gui.GuiTextureViewer;
-import net.minecraft.client.gui.achievements.GuiAchievements;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
+import net.minecraft.client.gui.ControllerSetupScreen;
+import net.minecraft.client.gui.HudDesignerScreen;
+import net.minecraft.client.gui.SoundTestScreen;
+import net.minecraft.client.gui.TextureViewerScreen;
+import net.minecraft.client.gui.achievements.AchievementsScreen;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
 import net.minecraft.client.gui.options.components.AvailableTexturePackListComponent;
 import net.minecraft.client.gui.options.components.BooleanOptionComponent;
 import net.minecraft.client.gui.options.components.DifficultyOptionComponent;
@@ -33,6 +32,7 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.util.helper.Utils;
 import net.minecraft.core.world.World;
+import org.useless.seedviewer.SeedViewerMain;
 
 import javax.management.RuntimeErrorException;
 import java.io.File;
@@ -51,7 +51,7 @@ public abstract class OptionsPages
             .withComponent(new BooleanOptionComponent(mc.gameSettings.viewBobbing))
         )
         .withComponent(new OptionsCategory("gui.options.page.general.category.user_interface")
-            .withComponent(new ShortcutComponent("gui.options.page.general.button.edit_hud", () -> mc.displayGuiScreen(new GuiHudDesigner(mc.currentScreen))))
+            .withComponent(new ShortcutComponent("gui.options.page.general.button.edit_hud", () -> mc.displayScreen(new HudDesignerScreen(mc.currentScreen))))
             .withComponent(new IntegerOptionComponent(mc.gameSettings.guiScale))
             .withComponent(new FloatOptionComponent(mc.gameSettings.screenPadding))
             .withComponent(new TooltipPickerComponent<>(mc.gameSettings.tooltipStyle))
@@ -80,6 +80,7 @@ public abstract class OptionsPages
 
     public static final OptionsPage AUDIO = register(new OptionsPage("gui.options.page.audio.title", new ItemStack(Items.RECORD_CAT))
         .withComponent(new OptionsCategory("gui.options.page.audio.category.audio")
+            .withComponent(new BooleanOptionComponent(mc.gameSettings.subtitles))
             .withComponent(new BooleanOptionComponent(mc.gameSettings.muteOnLostFocus))
             .withComponent(new FloatOptionComponent(mc.gameSettings.masterVolume))
             .withComponent(new FloatOptionComponent(mc.gameSettings.musicVolume))
@@ -144,7 +145,7 @@ public abstract class OptionsPages
             .withComponent(new BooleanOptionComponent(mc.gameSettings.swapCraftingButtons))
         )
         .withComponent(new OptionsCategory("gui.options.page.controls.category.controller")
-            .withComponent(new ShortcutComponent("gui.options.page.controls.button.controller_setup", () -> mc.displayGuiScreen(new GuiControllerSetup(mc.currentScreen))))
+            .withComponent(new ShortcutComponent("gui.options.page.controls.button.controller_setup", () -> mc.displayScreen(new ControllerSetupScreen(mc.currentScreen))))
             .withComponent(new FloatOptionComponent(mc.gameSettings.controllerSensitivity))
             .withComponent(new FloatOptionComponent(mc.gameSettings.controllerMenuSensitivity))
             .withComponent(new FloatOptionComponent(mc.gameSettings.controllerDeadzoneLeft))
@@ -281,7 +282,7 @@ public abstract class OptionsPages
             .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.model_viewer", () -> {
                                mc.playerController = new PlayerControllerSP(mc);
                                mc.changeWorld(new World(), "Loading Model Viewer");
-                               mc.displayGuiScreen(new GuiModelViewer());}) {
+                               mc.displayScreen(new ModelViewerScreen());}) {
                                @Override
                                public void render(int x, int y, int width, int relativeMouseX, int relativeMouseY) {
                                    button.enabled = mc.theWorld == null;
@@ -289,10 +290,10 @@ public abstract class OptionsPages
                                }
                            }
             )
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.sound_test", () -> mc.displayGuiScreen(new GuiSoundTest(mc.currentScreen))))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.texture_viewer", () -> mc.displayGuiScreen(new GuiTextureViewer(mc.currentScreen))))
+            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.sound_test", () -> mc.displayScreen(new SoundTestScreen(mc.currentScreen))))
+            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.texture_viewer", () -> mc.displayScreen(new TextureViewerScreen(mc.currentScreen))))
             .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.biome_finder", () -> {
-                new Thread(() -> BiomeFinder.main(new String[0])).start();
+                new Thread(() -> SeedViewerMain.main(new String[0])).start();
                 Global.accessor = mc;
             }))
             .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.datadumper", () ->{
@@ -300,7 +301,7 @@ public abstract class OptionsPages
                 Utils.openDirectory(new File(mc.getMinecraftDir(), "infodump"));
                 Global.accessor = mc;
             }))
-            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.achievements", () -> mc.displayGuiScreen(new GuiAchievements(mc.currentScreen, mc.statsCounter))))
+            .withComponent(new ShortcutComponent("gui.options.page.debug.button.open.achievements", () -> mc.displayScreen(new AchievementsScreen(mc.currentScreen, mc.statsCounter))))
         )
         .withComponent(new OptionsCategory("gui.options.page.debug.category.test")
             .withComponent(new ShortcutComponent("gui.options.page.debug.button.music.skip", () -> {
diff --git a/src/main/java/net/minecraft/client/gui/paged/GuiPaged.java b/src/main/java/net/minecraft/client/gui/paged/PagedScreen.java
similarity index 83%
rename from src/main/java/net/minecraft/client/gui/paged/GuiPaged.java
rename to src/main/java/net/minecraft/client/gui/paged/PagedScreen.java
index 8439fdd2f..53e7b8ea5 100644
--- a/src/main/java/net/minecraft/client/gui/paged/GuiPaged.java
+++ b/src/main/java/net/minecraft/client/gui/paged/PagedScreen.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.gui.paged;
 
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiRenderItem;
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.ItemElement;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.client.render.Scissor;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.lang.I18n;
@@ -14,8 +14,8 @@ import org.lwjgl.opengl.GL11;
 import static org.lwjgl.opengl.GL11.*;
 import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
 
-public class GuiPaged
-    extends GuiScreen {
+public class PagedScreen
+    extends Screen {
     private static final int TOP_SPACING = 24;
     private static final int BUTTON_SPACING = 4;
     private static final int SEPARATOR_WIDTH = 8;
@@ -35,11 +35,11 @@ public class GuiPaged
     private Page selectedPage;
     private PageComponent clickedComponent;
     private int clickedComponentY;
-    private GuiRenderItem renderItem = null;
+    private ItemElement renderItem = null;
 
     private final PageRegistry pageRegistry;
 
-    public GuiPaged(GuiScreen parent, PageRegistry pageRegistry, Page selectedPage, String titleTranslationKey, String[] buttonTranslationKeys)
+    public PagedScreen(Screen parent, PageRegistry pageRegistry, Page selectedPage, String titleTranslationKey, String[] buttonTranslationKeys)
     {
         super(parent);
         this.pageRegistry = pageRegistry;
@@ -57,7 +57,7 @@ public class GuiPaged
         int totalButtonsWidth = buttonTranslationKeys.length * (buttonWidth + 4) - 4;
         for (int i = 0; i < buttonTranslationKeys.length; i++) {
             String buttonTranslationKey = buttonTranslationKeys[i];
-            controlList.add(new GuiButton(i, width / 2 - totalButtonsWidth / 2 + ((buttonWidth + 4) * i), height - (BUTTON_SPACING + 20), buttonWidth, 20, I18n.getInstance().translateKey(buttonTranslationKey)));
+            buttons.add(new ButtonElement(i, width / 2 - totalButtonsWidth / 2 + ((buttonWidth + 4) * i), height - (BUTTON_SPACING + 20), buttonWidth, 20, I18n.getInstance().translateKey(buttonTranslationKey)));
         }
 
         top = TOP_SPACING;
@@ -66,22 +66,22 @@ public class GuiPaged
         rightScrollRegionHeight = bottom - top;
         leftScrollRegionHeight = bottom - top;
 
-        this.renderItem = new GuiRenderItem(mc);
+        this.renderItem = new ItemElement(mc);
 
         this.selectedPage.initComponents(mc);
     }
 
     @Override
-    public void keyTyped(char c, int key, int mouseX, int mouseY) {
-        if (key == Keyboard.KEY_ESCAPE)
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my) {
+        if (eventKey == Keyboard.KEY_ESCAPE)
         {
-            mc.displayGuiScreen(getParentScreen());
+            mc.displayScreen(getParentScreen());
         }
         else
         {
             for (PageComponent component : selectedPage.getComponents())
             {
-                component.onKeyPress(key, c);
+                component.onKeyPress(eventKey, eventCharacter);
             }
         }
     }
@@ -108,7 +108,7 @@ public class GuiPaged
                 textColor = 0xFFFFFFA0;
             }
             renderItem.render(page.getIcon(), x, y2 + (PAGE_BUTTON_HEIGHT / 2) - 9);
-            mc.fontRenderer.drawStringWithShadow(translated, x + 19, y2 + (PAGE_BUTTON_HEIGHT / 2) - 4, textColor);
+            mc.font.drawStringWithShadow(translated, x + 19, y2 + (PAGE_BUTTON_HEIGHT / 2) - 4, textColor);
             y2 += PAGE_BUTTON_HEIGHT;
         }
     }
@@ -122,12 +122,12 @@ public class GuiPaged
     }
 
     @Override
-    protected void buttonPressed(GuiButton guibutton) {
-        super.buttonPressed(guibutton);
+    protected void buttonClicked(ButtonElement button) {
+        super.buttonClicked(button);
 
-        if (guibutton.id == 0)
+        if (button.id == 0)
         {
-            mc.displayGuiScreen(getParentScreen());
+            mc.displayScreen(getParentScreen());
             mc.texturePackList.refreshIfReady(); // Sets the texturepacks on menu close
         }
     }
@@ -173,16 +173,16 @@ public class GuiPaged
     }
 
     @Override
-    public void drawScreen(int mouseX, int mouseY, float renderPartialTicks)
+    public void render(int xm, int ym, float renderPartialTicks)
     {
-        if (mouseX > leftWidth + SEPARATOR_WIDTH + PADDING && mouseX < width) {
+        if (xm > leftWidth + SEPARATOR_WIDTH + PADDING && xm < width) {
             if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) {
                 scrollRightPanel(Mouse.getDWheel() / -0.01f);
             } else {
                 scrollRightPanel(Mouse.getDWheel() / -0.05f);
             }
             onScrollRightPanel();
-        } else if (mouseX >= 0 && mouseX <= leftWidth) {
+        } else if (xm >= 0 && xm <= leftWidth) {
             if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) {
                 scrollLeftPanel(Mouse.getDWheel() / -0.01f);
             } else {
@@ -195,13 +195,13 @@ public class GuiPaged
         pageWidth = width - (leftWidth + SEPARATOR_WIDTH + (PADDING * 2));
         I18n i18n = I18n.getInstance();
 
-        drawDefaultBackground();
+        renderBackground();
         overlayBackground(0, width, 0, top);
         overlayBackground(0, width, bottom, height);
 
         Scissor.enable(0, top, width, bottom - top);
-        if (mouseY >= top && mouseY <= bottom) {
-            drawPageItems(leftWidth + SEPARATOR_WIDTH + PADDING, top - (int) rightScrollAmount, pageWidth - 8, mouseX, mouseY);
+        if (ym >= top && ym <= bottom) {
+            drawPageItems(leftWidth + SEPARATOR_WIDTH + PADDING, top - (int) rightScrollAmount, pageWidth - 8, xm, ym);
         } else {
             drawPageItems(leftWidth + SEPARATOR_WIDTH + PADDING, top - (int) rightScrollAmount, pageWidth - 8, -1, -1);
         }
@@ -213,8 +213,8 @@ public class GuiPaged
         if (pagesListHeight < bottom - top) {
             pagesListY = top + (bottom - top - pagesListHeight) / 2;
         }
-        if (mouseY >= top && mouseY <= bottom) {
-            drawPagesListItems(PADDING - 4, pagesListY, leftWidth - PADDING, mouseX, mouseY);
+        if (ym >= top && ym <= bottom) {
+            drawPagesListItems(PADDING - 4, pagesListY, leftWidth - PADDING, xm, ym);
         } else {
             drawPagesListItems(PADDING - 4, pagesListY, leftWidth - PADDING, -1, -1);
         }
@@ -258,12 +258,12 @@ public class GuiPaged
 
         overlayBackground(leftWidth, leftWidth + SEPARATOR_WIDTH, top, bottom);
 
-        drawStringCentered(fontRenderer, i18n.translateKey(titleTranslationKey), width / 2, 5, 0xffffff);
+        drawStringCentered(font, i18n.translateKey(titleTranslationKey), width / 2, 5, 0xffffff);
 
-        drawRightPanelScrollBar(mouseX, mouseY);
-        drawLeftPanelScrollBar(mouseX, mouseY);
+        drawRightPanelScrollBar(xm, ym);
+        drawLeftPanelScrollBar(xm, ym);
 
-        super.drawScreen(mouseX, mouseY, renderPartialTicks);
+        super.render(xm, ym, renderPartialTicks);
     }
 
     protected void drawRightPanelScrollBar(int mouseX, int mouseY) {
@@ -357,32 +357,32 @@ public class GuiPaged
     }
 
     @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton)
+    public void mouseClicked(int mx, int my, int buttonNum)
     {
-        super.mouseClicked(mouseX, mouseY, mouseButton);
+        super.mouseClicked(mx, my, buttonNum);
 
         int left = leftWidth + SEPARATOR_WIDTH + PADDING;
 
-        if (mouseX >= leftWidth + SEPARATOR_WIDTH && mouseY >= top && mouseY <= bottom) {
+        if (mx >= leftWidth + SEPARATOR_WIDTH && my >= top && my <= bottom) {
             int componentY = top - (int) rightScrollAmount;
             for (PageComponent component : selectedPage.getComponents())
             {
-                if (mouseX >= left && mouseX <= left + pageWidth - PADDING && mouseY >= componentY && mouseY <= componentY + component.getHeight()) {
-                    component.onMouseClick(mouseButton, left, componentY, pageWidth - PADDING, mouseX - left, mouseY - componentY);
+                if (mx >= left && mx <= left + pageWidth - PADDING && my >= componentY && my <= componentY + component.getHeight()) {
+                    component.onMouseClick(buttonNum, left, componentY, pageWidth - PADDING, mx - left, my - componentY);
                     clickedComponent = component;
                     clickedComponentY = componentY;
                     break;
                 }
                 componentY += component.getHeight();
             }
-        } else if (mouseX >= 0 && mouseX <= leftWidth && mouseY >= top && mouseY <= bottom) {
+        } else if (mx >= 0 && mx <= leftWidth && my >= top && my <= bottom) {
             int pagesListHeight = getTotalLeftPanelHeight();
             int pagesListY = top - (int) leftScrollAmount;
             if (pagesListHeight < bottom - top) {
                 pagesListY = top + (bottom - top - pagesListHeight) / 2;
             }
             for(Page page : pageRegistry.getPages()) {
-                if (mouseX >= 0 && mouseX <= leftWidth && mouseY >= pagesListY && mouseY <= pagesListY + PAGE_BUTTON_HEIGHT) {
+                if (mx >= 0 && mx <= leftWidth && my >= pagesListY && my <= pagesListY + PAGE_BUTTON_HEIGHT) {
                     rightScrollAmount = 0;
                     selectedPage = page;
                     this.selectedPage.initComponents(mc);
@@ -394,40 +394,40 @@ public class GuiPaged
             }
         }
 
-        clickX = mouseX;
-        clickY = mouseY;
+        clickX = mx;
+        clickY = my;
     }
 
     @Override
-    public void mouseMovedOrButtonReleased(int mouseX, int mouseY, int mouseButton) {
-        super.mouseMovedOrButtonReleased(mouseX, mouseY, mouseButton);
+    public void mouseReleased(int mx, int my, int buttonNum) {
+        super.mouseReleased(mx, my, buttonNum);
 
         int left = leftWidth + SEPARATOR_WIDTH + PADDING;
-        if (mouseY >= top && mouseY <= bottom) {
+        if (my >= top && my <= bottom) {
             if (clickedComponent != null) {
-                if (mouseButton >= 0) {
-                    clickedComponent.onMouseRelease(mouseButton, left, clickedComponentY, pageWidth, mouseX - left, mouseY - clickedComponentY);
+                if (buttonNum >= 0) {
+                    clickedComponent.onMouseRelease(buttonNum, left, clickedComponentY, pageWidth, mx - left, my - clickedComponentY);
                     clickedComponent = null;
                 } else {
-                    clickedComponent.onMouseMove(left, clickedComponentY, pageWidth, mouseX - left, mouseY - clickedComponentY);
+                    clickedComponent.onMouseMove(left, clickedComponentY, pageWidth, mx - left, my - clickedComponentY);
                 }
             }
         }
 
-        if(mouseButton >= 0) {
+        if(buttonNum >= 0) {
             clickX = null;
             clickY = null;
         }
     }
 
     @Override
-    public void drawDefaultBackground() {
-        super.drawDefaultBackground();
+    public void renderBackground() {
+        super.renderBackground();
 
         if (mc.theWorld == null)
         {
             Tessellator tessellator = Tessellator.instance;
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
             float scale = 32F;
             tessellator.startDrawingQuads();
@@ -458,7 +458,7 @@ public class GuiPaged
         if (mc.theWorld == null)
         {
             Tessellator tessellator = Tessellator.instance;
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
             GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
             float scale = 32F;
             tessellator.startDrawingQuads();
diff --git a/src/main/java/net/minecraft/client/gui/popup/ButtonComponent.java b/src/main/java/net/minecraft/client/gui/popup/ButtonComponent.java
index 6a1a03af7..24e0c1316 100644
--- a/src/main/java/net/minecraft/client/gui/popup/ButtonComponent.java
+++ b/src/main/java/net/minecraft/client/gui/popup/ButtonComponent.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui.popup;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.core.lang.I18n;
 
 public class ButtonComponent
@@ -9,7 +9,7 @@ public class ButtonComponent
     private final Minecraft minecraft;
     private final String buttonLabel;
     private final String[] buttonValues;
-    private final GuiButton button;
+    private final ButtonElement button;
     private int value;
 
     public ButtonComponent(int width, String buttonLabel, String[] buttonValues, int defaultValue) {
@@ -22,7 +22,7 @@ public class ButtonComponent
 
         this.value = defaultValue;
 
-        button = new GuiButton(0, 0, 0, width, getHeight(), getButtonLabel());
+        button = new ButtonElement(0, 0, 0, width, getHeight(), getButtonLabel());
     }
 
     private String getButtonLabel() {
diff --git a/src/main/java/net/minecraft/client/gui/popup/ButtonGroupComponent.java b/src/main/java/net/minecraft/client/gui/popup/ButtonGroupComponent.java
index 523845b61..c79783c86 100644
--- a/src/main/java/net/minecraft/client/gui/popup/ButtonGroupComponent.java
+++ b/src/main/java/net/minecraft/client/gui/popup/ButtonGroupComponent.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.gui.popup;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ButtonElement;
 import net.minecraft.core.sound.SoundCategory;
 
 public class ButtonGroupComponent
@@ -9,7 +9,7 @@ public class ButtonGroupComponent
 {
     private static final int BUTTON_GAP = 2;
     private final Minecraft minecraft;
-    private final GuiButton[] buttons;
+    private final ButtonElement[] buttons;
 
     public ButtonGroupComponent(int width, String[] buttonLabels, int[] buttonStatusCodes, boolean[] enabled)
     {
@@ -17,7 +17,7 @@ public class ButtonGroupComponent
 
         this.minecraft = Minecraft.getMinecraft(this);
 
-        this.buttons = new GuiButton[buttonLabels.length];
+        this.buttons = new ButtonElement[buttonLabels.length];
 
         int numButtons = this.buttons.length;
         int buttonWidth = (width - (BUTTON_GAP * (numButtons - 1))) / numButtons;
@@ -25,7 +25,7 @@ public class ButtonGroupComponent
         buttonWidth = Math.min(buttonWidth,256);
         for (int i = 0; i < numButtons; i++)
         {
-            buttons[i] = new GuiButton(buttonStatusCodes[i], 0, 0, buttonWidth, getHeight(), buttonLabels[i]);
+            buttons[i] = new ButtonElement(buttonStatusCodes[i], 0, 0, buttonWidth, getHeight(), buttonLabels[i]);
             buttons[i].enabled = enabled[i];
         }
     }
@@ -41,7 +41,7 @@ public class ButtonGroupComponent
     {
         for (int i = 0; i < buttons.length; i++)
         {
-            GuiButton button = buttons[i];
+            ButtonElement button = buttons[i];
 
             button.xPosition = x + (button.width + BUTTON_GAP) * i;
             button.yPosition = y;
@@ -52,7 +52,7 @@ public class ButtonGroupComponent
     @Override
     public void onClick(int x, int y, int button)
     {
-        for (GuiButton b : buttons)
+        for (ButtonElement b : buttons)
         {
             if (b.mouseClicked(minecraft, x, y))
             {
diff --git a/src/main/java/net/minecraft/client/gui/popup/LabelComponent.java b/src/main/java/net/minecraft/client/gui/popup/LabelComponent.java
index b78f9a121..31d7c5ea8 100644
--- a/src/main/java/net/minecraft/client/gui/popup/LabelComponent.java
+++ b/src/main/java/net/minecraft/client/gui/popup/LabelComponent.java
@@ -1,19 +1,19 @@
 package net.minecraft.client.gui.popup;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 
 public class LabelComponent
     extends PopupComponent
 {
-    private final FontRenderer fr;
+    private final Font fr;
     private final String text;
     private final int color;
 
     public LabelComponent(int width, String text, int color)
     {
         super(width);
-        this.fr = Minecraft.getMinecraft(this).fontRenderer;
+        this.fr = Minecraft.getMinecraft(this).font;
         this.text = text;
         this.color = color;
     }
@@ -27,7 +27,7 @@ public class LabelComponent
     @Override
     public void render(int x, int y, int mouseX, int mouseY)
     {
-        int middle = (x - GuiPopup.HORIZONTAL_MARGIN) + getWidth() / 2;
+        int middle = (x - PopupScreen.HORIZONTAL_MARGIN) + getWidth() / 2;
 
         fr.drawCenteredString(text, middle, y, color);
     }
diff --git a/src/main/java/net/minecraft/client/gui/popup/ListComponent.java b/src/main/java/net/minecraft/client/gui/popup/ListComponent.java
index 4979e5fb8..c48a547f8 100644
--- a/src/main/java/net/minecraft/client/gui/popup/ListComponent.java
+++ b/src/main/java/net/minecraft/client/gui/popup/ListComponent.java
@@ -7,8 +7,8 @@ import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.GL11;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiButton;
-import net.minecraft.client.gui.GuiTooltip;
+import net.minecraft.client.gui.ButtonElement;
+import net.minecraft.client.gui.TooltipElement;
 import net.minecraft.core.util.helper.MathHelper;
 
 public class ListComponent
@@ -17,12 +17,12 @@ public class ListComponent
     private final Minecraft minecraft;
     private int selectedItem = 0;
     private float scrollAmount = 0;
-    private final GuiButton[] buttons;
+    private final ButtonElement[] buttons;
     private final int height;
     private int lastX = 0;
     private int lastY = 0;
     private final boolean closeOnItemSelected;
-    private final GuiTooltip tooltip;
+    private final TooltipElement tooltip;
     private final String[] buttonTooltips;
     
     private int scrollbarX;
@@ -40,15 +40,15 @@ public class ListComponent
         this.minecraft = Minecraft.getMinecraft(this);
         this.height = height;
         this.closeOnItemSelected = closeOnItemSelected;
-        this.tooltip = new GuiTooltip(minecraft);
+        this.tooltip = new TooltipElement(minecraft);
 
         this.selectedItem = selectedItem;
         this.buttonTooltips = buttonTooltips;
 
-        this.buttons = new GuiButton[buttonLabels.length];
+        this.buttons = new ButtonElement[buttonLabels.length];
         for (int i = 0; i < this.buttons.length; i++)
         {
-            this.buttons[i] = new GuiButton(i, 0, 0, width - 2 - 6, 20, buttonLabels[i]);
+            this.buttons[i] = new ButtonElement(i, 0, 0, width - 2 - 6, 20, buttonLabels[i]);
             if (i == selectedItem)
             {
                 this.buttons[i].enabled = false;
@@ -118,7 +118,7 @@ public class ListComponent
                 buttons[i].width = getWidth() - 2;
             }
 
-            GuiButton button = buttons[i];
+            ButtonElement button = buttons[i];
             button.xPosition = x + 1;
             button.yPosition = (y + 1) + (i * 20) - getScrollPixels();
             if (mouseInRegion(x, y, mouseX, mouseY))
@@ -137,7 +137,7 @@ public class ListComponent
         {
             for (int i = 0; i < buttons.length; i++)
             {
-                GuiButton button = buttons[i];
+                ButtonElement button = buttons[i];
                 if (button.isHovered(mouseX, mouseY))
                 {
                     tooltip.render(buttonTooltips[i], mouseX, mouseY, 0, 0);
@@ -180,11 +180,11 @@ public class ListComponent
         
         if (mouseInRegion(lastX, lastY, x, y))
         {
-            for (GuiButton b : this.buttons)
+            for (ButtonElement b : this.buttons)
             {
                 if (b.mouseClicked(minecraft, x, y))
                 {
-                    for (GuiButton b2 : this.buttons)
+                    for (ButtonElement b2 : this.buttons)
                     {
                         b2.enabled = true;
                     }
diff --git a/src/main/java/net/minecraft/client/gui/popup/MessageBoxComponent.java b/src/main/java/net/minecraft/client/gui/popup/MessageBoxComponent.java
index 51ca70739..c586e7889 100644
--- a/src/main/java/net/minecraft/client/gui/popup/MessageBoxComponent.java
+++ b/src/main/java/net/minecraft/client/gui/popup/MessageBoxComponent.java
@@ -3,14 +3,12 @@ package net.minecraft.client.gui.popup;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.Scissor;
 import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.net.command.TextFormatting;
 import net.minecraft.core.util.helper.MathHelper;
 import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.GL11;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 
 public class MessageBoxComponent
@@ -126,7 +124,7 @@ public class MessageBoxComponent
         // Draw lines
         for (int i = 0; i < lines.size(); i++)
         {
-            minecraft.fontRenderer.drawStringWithShadow(lines.get(i),x + 4,(y + 4) + (i * 12) - getScrollPixels(),0xFFFFFFFF);
+            minecraft.font.drawStringWithShadow(lines.get(i),x + 4,(y + 4) + (i * 12) - getScrollPixels(),0xFFFFFFFF);
         }
 
         Scissor.disable();
diff --git a/src/main/java/net/minecraft/client/gui/popup/PopupBuilder.java b/src/main/java/net/minecraft/client/gui/popup/PopupBuilder.java
index c6772d60c..5dc36b76d 100644
--- a/src/main/java/net/minecraft/client/gui/popup/PopupBuilder.java
+++ b/src/main/java/net/minecraft/client/gui/popup/PopupBuilder.java
@@ -1,18 +1,18 @@
 package net.minecraft.client.gui.popup;
 
-import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.Screen;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.collection.Pair;
 
 import java.util.*;
 
-import static net.minecraft.client.gui.popup.GuiPopup.VERTICAL_MARGIN;
-import static net.minecraft.client.gui.popup.GuiPopup.HORIZONTAL_MARGIN;
-import static net.minecraft.client.gui.popup.GuiPopup.COMPONENT_GAP;
+import static net.minecraft.client.gui.popup.PopupScreen.VERTICAL_MARGIN;
+import static net.minecraft.client.gui.popup.PopupScreen.HORIZONTAL_MARGIN;
+import static net.minecraft.client.gui.popup.PopupScreen.COMPONENT_GAP;
 
 public class PopupBuilder
 {
-    private final GuiScreen parent;
+    private final Screen parent;
     private final int width;
     private Integer statusCodeOnEsc = null;
     private Integer statusCodeOnEnter = null;
@@ -22,15 +22,15 @@ public class PopupBuilder
     private final List<PopupCloseListener> onCloseListeners = new ArrayList<>();
     private Pair<Integer,Integer> backgroundColor = null;
 
-    public PopupBuilder(GuiScreen parent, int width)
+    public PopupBuilder(Screen parent, int width)
     {
         this.parent = parent;
         this.width = width;
     }
 
-    public GuiPopup build()
+    public PopupScreen build()
     {
-        GuiPopup popup = new GuiPopup(
+        PopupScreen popup = new PopupScreen(
                 parent,
                 width,
                 getHeight(),
diff --git a/src/main/java/net/minecraft/client/gui/popup/PopupComponent.java b/src/main/java/net/minecraft/client/gui/popup/PopupComponent.java
index 82d54047c..01cf5ccc7 100644
--- a/src/main/java/net/minecraft/client/gui/popup/PopupComponent.java
+++ b/src/main/java/net/minecraft/client/gui/popup/PopupComponent.java
@@ -2,7 +2,7 @@ package net.minecraft.client.gui.popup;
 
 public abstract class PopupComponent
 {
-    private GuiPopup parent = null;
+    private PopupScreen parent = null;
     private final int width;
 
     public PopupComponent(int width)
@@ -10,12 +10,12 @@ public abstract class PopupComponent
         this.width = width;
     }
 
-    public void setParent(GuiPopup parent)
+    public void setParent(PopupScreen parent)
     {
         this.parent = parent;
     }
 
-    public GuiPopup getParent()
+    public PopupScreen getParent()
     {
         return parent;
     }
diff --git a/src/main/java/net/minecraft/client/gui/popup/GuiPopup.java b/src/main/java/net/minecraft/client/gui/popup/PopupScreen.java
similarity index 76%
rename from src/main/java/net/minecraft/client/gui/popup/GuiPopup.java
rename to src/main/java/net/minecraft/client/gui/popup/PopupScreen.java
index 8aa438cd8..f569d36b0 100644
--- a/src/main/java/net/minecraft/client/gui/popup/GuiPopup.java
+++ b/src/main/java/net/minecraft/client/gui/popup/PopupScreen.java
@@ -1,213 +1,213 @@
-package net.minecraft.client.gui.popup;
-
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.util.collection.Pair;
-import org.lwjgl.input.Keyboard;
-import org.lwjgl.opengl.GL11;
-
-import java.util.*;
-
-public final class GuiPopup
-    extends GuiScreen
-{
-    static final int HORIZONTAL_MARGIN = 8;
-    static final int VERTICAL_MARGIN = 8;
-    static final int COMPONENT_GAP = 4;
-
-
-    private final GuiScreen parent;
-    private final int popupWidth;
-    private final int popupHeight;
-
-    private final Integer statusCodeOnEsc;
-    private final Integer statusCodeOnEnter;
-    private final Integer statusCodeOnClickOut;
-    private final List<PopupComponent> components;
-    private final Map<PopupComponent, String> componentKeyMap;
-    private final List<PopupCloseListener> onCloseListeners;
-
-    private final Pair<Integer,Integer> backgroundColor;
-
-    private int statusCode = -1;
-
-    GuiPopup(
-            GuiScreen parent,
-            int width,
-            int height,
-            Integer statusCodeOnEsc,
-            Integer statusCodeOnEnter,
-            Integer statusCodeOnClickOut,
-            List<PopupComponent> components,
-            Map<PopupComponent, String> componentKeyMap,
-            List<PopupCloseListener> onCloseListeners,
-            Pair<Integer,Integer> backgroundColor
-    )
-    {
-        this.parent = parent;
-        this.popupWidth = width;
-        this.popupHeight = height;
-        this.statusCodeOnEsc = statusCodeOnEsc;
-        this.statusCodeOnEnter = statusCodeOnEnter;
-        this.statusCodeOnClickOut = statusCodeOnClickOut;
-        this.components = components;
-        this.componentKeyMap = componentKeyMap;
-        this.onCloseListeners = onCloseListeners;
-        this.backgroundColor = backgroundColor;
-    }
-
-    void close(int statusCode)
-    {
-        this.statusCode = statusCode;
-        this.onClosed();
-        mc.currentScreen = parent;
-    }
-
-    @Override
-    public void tick()
-    {
-        super.tick();
-
-        for (PopupComponent component : components)
-        {
-            component.tick();
-        }
-    }
-
-    @Override
-    public void onClosed()
-    {
-        super.onClosed();
-
-        Map<String, Object> results = new HashMap<>();
-        for (Map.Entry<PopupComponent, String> entry : componentKeyMap.entrySet())
-        {
-            if (entry.getKey() instanceof InteractivePopupComponent<?>)
-            {
-                Object value = ((InteractivePopupComponent<?>) entry.getKey()).getOutput();
-                results.put(entry.getValue(), value);
-            }
-        }
-
-        for (PopupCloseListener listener : onCloseListeners)
-        {
-            listener.onClosed(statusCode, results);
-        }
-    }
-
-    @Override
-    public void init()
-    {
-        if (parent.width != width || parent.height != height)
-        {
-            parent.width = width;
-            parent.height = height;
-            parent.controlList.clear();
-            parent.init();
-        }
-
-        super.init();
-    }
-
-    @Override
-    public void keyTyped(char c, int key, int mouseX, int mouseY)
-    {
-        if (key == Keyboard.KEY_ESCAPE && statusCodeOnEsc != null)
-        {
-            close(statusCodeOnEsc);
-        }
-        if (key == Keyboard.KEY_RETURN && statusCodeOnEnter != null)
-        {
-            close(statusCodeOnEnter);
-        }
-        for (PopupComponent component : components)
-        {
-            component.onKeyDown(key, c);
-        }
-    }
-
-    @Override
-    public void mouseClicked(int mouseX, int mouseY, int mouseButton)
-    {
-        if (statusCodeOnClickOut != null)
-        {
-            int popupX = width / 2 - popupWidth / 2;
-            int popupY = height / 2 - popupHeight / 2;
-
-            if (mouseX < popupX || mouseX > popupX + popupWidth || mouseY < popupY || mouseY > popupY + popupHeight)
-            {
-                close(statusCodeOnClickOut);
-            }
-        }
-
-        super.mouseClicked(mouseX, mouseY, mouseButton);
-
-        for (PopupComponent component : components)
-        {
-            component.onClick(mouseX, mouseY, mouseButton);
-        }
-    }
-    
-    @Override
-    public void mouseMovedOrButtonReleased(int mouseX, int mouseY, int mouseButton)
-    {
-    	super.mouseMovedOrButtonReleased(mouseX, mouseY, mouseButton);
-    	
-    	for(PopupComponent component : components) {
-    		component.mouseMovedOrUp(mouseX, mouseY, mouseButton);
-    	}
-    }
-
-    @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTick)
-    {
-        int popupX = width / 2 - popupWidth / 2;
-        int popupY = height / 2 - popupHeight / 2;
-
-        parent.drawScreen(-1, -1, partialTick);
-
-        drawPopupBackground();
-
-        int accY = popupY + VERTICAL_MARGIN;
-
-        for (PopupComponent component : components)
-        {
-            component.render(popupX + HORIZONTAL_MARGIN, accY, mouseX, mouseY);
-            accY += component.getHeight() + COMPONENT_GAP;
-        }
-
-        super.drawScreen(mouseX, mouseY, partialTick);
-    }
-
-    private void drawPopupBackground()
-    {
-        int popupX = width / 2 - popupWidth / 2;
-        int popupY = height / 2 - popupHeight / 2;
-
-        GL11.glDisable(GL11.GL_LIGHTING);
-        GL11.glDisable(GL11.GL_FOG);
-        Tessellator tessellator = Tessellator.instance;
-        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
-
-        if(backgroundColor == null){
-            int color = mc.gameSettings.guiBackgroundColor.value.getARGB();
-            drawGradientRect(0, 0, width, height, color, color);
-        } else {
-            drawGradientRect(0, 0, width, height, backgroundColor.getLeft(), backgroundColor.getRight());
-        }
-
-
-        drawRectWidthHeight(popupX - 1, popupY - 1, popupWidth + 2, popupHeight + 2, 0xFFA0A0A0);
-
-        GL11.glEnable(GL11.GL_TEXTURE_2D);
-        float f = 32F;
-        tessellator.startDrawingQuads();
-        mc.renderEngine.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
-        tessellator.setColorOpaque_I(0x404040);
-        tessellator.addVertexWithUV(popupX, popupY + popupHeight, 0.0D, 0.0D, (float)popupHeight / f);
-        tessellator.addVertexWithUV(popupX + popupWidth, popupY + popupHeight, 0.0D, (float)popupWidth / f, (float)popupHeight / f);
-        tessellator.addVertexWithUV(popupX + popupWidth, popupY, 0.0D, (float)popupWidth / f, 0);
-        tessellator.addVertexWithUV(popupX, popupY, 0.0D, 0.0D, 0);
-        tessellator.draw();
-    }
-}
+package net.minecraft.client.gui.popup;
+
+import net.minecraft.client.gui.Screen;
+import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.core.util.collection.Pair;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+
+import java.util.*;
+
+public final class PopupScreen
+    extends Screen
+{
+    static final int HORIZONTAL_MARGIN = 8;
+    static final int VERTICAL_MARGIN = 8;
+    static final int COMPONENT_GAP = 4;
+
+
+    private final Screen parent;
+    private final int popupWidth;
+    private final int popupHeight;
+
+    private final Integer statusCodeOnEsc;
+    private final Integer statusCodeOnEnter;
+    private final Integer statusCodeOnClickOut;
+    private final List<PopupComponent> components;
+    private final Map<PopupComponent, String> componentKeyMap;
+    private final List<PopupCloseListener> onCloseListeners;
+
+    private final Pair<Integer,Integer> backgroundColor;
+
+    private int statusCode = -1;
+
+    PopupScreen(
+            Screen parent,
+            int width,
+            int height,
+            Integer statusCodeOnEsc,
+            Integer statusCodeOnEnter,
+            Integer statusCodeOnClickOut,
+            List<PopupComponent> components,
+            Map<PopupComponent, String> componentKeyMap,
+            List<PopupCloseListener> onCloseListeners,
+            Pair<Integer,Integer> backgroundColor
+    )
+    {
+        this.parent = parent;
+        this.popupWidth = width;
+        this.popupHeight = height;
+        this.statusCodeOnEsc = statusCodeOnEsc;
+        this.statusCodeOnEnter = statusCodeOnEnter;
+        this.statusCodeOnClickOut = statusCodeOnClickOut;
+        this.components = components;
+        this.componentKeyMap = componentKeyMap;
+        this.onCloseListeners = onCloseListeners;
+        this.backgroundColor = backgroundColor;
+    }
+
+    void close(int statusCode)
+    {
+        this.statusCode = statusCode;
+        this.removed();
+        mc.currentScreen = parent;
+    }
+
+    @Override
+    public void tick()
+    {
+        super.tick();
+
+        for (PopupComponent component : components)
+        {
+            component.tick();
+        }
+    }
+
+    @Override
+    public void removed()
+    {
+        super.removed();
+
+        Map<String, Object> results = new HashMap<>();
+        for (Map.Entry<PopupComponent, String> entry : componentKeyMap.entrySet())
+        {
+            if (entry.getKey() instanceof InteractivePopupComponent<?>)
+            {
+                Object value = ((InteractivePopupComponent<?>) entry.getKey()).getOutput();
+                results.put(entry.getValue(), value);
+            }
+        }
+
+        for (PopupCloseListener listener : onCloseListeners)
+        {
+            listener.onClosed(statusCode, results);
+        }
+    }
+
+    @Override
+    public void init()
+    {
+        if (parent.width != width || parent.height != height)
+        {
+            parent.width = width;
+            parent.height = height;
+            parent.buttons.clear();
+            parent.init();
+        }
+
+        super.init();
+    }
+
+    @Override
+    public void keyPressed(char eventCharacter, int eventKey, int mx, int my)
+    {
+        if (eventKey == Keyboard.KEY_ESCAPE && statusCodeOnEsc != null)
+        {
+            close(statusCodeOnEsc);
+        }
+        if (eventKey == Keyboard.KEY_RETURN && statusCodeOnEnter != null)
+        {
+            close(statusCodeOnEnter);
+        }
+        for (PopupComponent component : components)
+        {
+            component.onKeyDown(eventKey, eventCharacter);
+        }
+    }
+
+    @Override
+    public void mouseClicked(int mx, int my, int buttonNum)
+    {
+        if (statusCodeOnClickOut != null)
+        {
+            int popupX = width / 2 - popupWidth / 2;
+            int popupY = height / 2 - popupHeight / 2;
+
+            if (mx < popupX || mx > popupX + popupWidth || my < popupY || my > popupY + popupHeight)
+            {
+                close(statusCodeOnClickOut);
+            }
+        }
+
+        super.mouseClicked(mx, my, buttonNum);
+
+        for (PopupComponent component : components)
+        {
+            component.onClick(mx, my, buttonNum);
+        }
+    }
+    
+    @Override
+    public void mouseReleased(int mx, int my, int buttonNum)
+    {
+    	super.mouseReleased(mx, my, buttonNum);
+    	
+    	for(PopupComponent component : components) {
+    		component.mouseMovedOrUp(mx, my, buttonNum);
+    	}
+    }
+
+    @Override
+    public void render(int xm, int ym, float partialTick)
+    {
+        int popupX = width / 2 - popupWidth / 2;
+        int popupY = height / 2 - popupHeight / 2;
+
+        parent.render(-1, -1, partialTick);
+
+        drawPopupBackground();
+
+        int accY = popupY + VERTICAL_MARGIN;
+
+        for (PopupComponent component : components)
+        {
+            component.render(popupX + HORIZONTAL_MARGIN, accY, xm, ym);
+            accY += component.getHeight() + COMPONENT_GAP;
+        }
+
+        super.render(xm, ym, partialTick);
+    }
+
+    private void drawPopupBackground()
+    {
+        int popupX = width / 2 - popupWidth / 2;
+        int popupY = height / 2 - popupHeight / 2;
+
+        GL11.glDisable(GL11.GL_LIGHTING);
+        GL11.glDisable(GL11.GL_FOG);
+        Tessellator tessellator = Tessellator.instance;
+        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+
+        if(backgroundColor == null){
+            int color = mc.gameSettings.guiBackgroundColor.value.getARGB();
+            drawGradientRect(0, 0, width, height, color, color);
+        } else {
+            drawGradientRect(0, 0, width, height, backgroundColor.getLeft(), backgroundColor.getRight());
+        }
+
+
+        drawRectWidthHeight(popupX - 1, popupY - 1, popupWidth + 2, popupHeight + 2, 0xFFA0A0A0);
+
+        GL11.glEnable(GL11.GL_TEXTURE_2D);
+        float f = 32F;
+        tessellator.startDrawingQuads();
+        mc.textureManager.loadTexture("/assets/minecraft/textures/gui/background.png").bind();
+        tessellator.setColorOpaque_I(0x404040);
+        tessellator.addVertexWithUV(popupX, popupY + popupHeight, 0.0D, 0.0D, (float)popupHeight / f);
+        tessellator.addVertexWithUV(popupX + popupWidth, popupY + popupHeight, 0.0D, (float)popupWidth / f, (float)popupHeight / f);
+        tessellator.addVertexWithUV(popupX + popupWidth, popupY, 0.0D, (float)popupWidth / f, 0);
+        tessellator.addVertexWithUV(popupX, popupY, 0.0D, 0.0D, 0);
+        tessellator.draw();
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/popup/TextInputComponent.java b/src/main/java/net/minecraft/client/gui/popup/TextInputComponent.java
index ddf2423bc..389e75fd4 100644
--- a/src/main/java/net/minecraft/client/gui/popup/TextInputComponent.java
+++ b/src/main/java/net/minecraft/client/gui/popup/TextInputComponent.java
@@ -1,21 +1,21 @@
 package net.minecraft.client.gui.popup;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiTextField;
+import net.minecraft.client.gui.TextFieldElement;
 
 public class TextInputComponent
     extends InteractivePopupComponent<String>
 {
-    private final GuiTextField textField;
+    private final TextFieldElement textField;
 
     public TextInputComponent(int width, String defaultText, String placeholder)
     {
         super(width);
-        this.textField = new GuiTextField(null, Minecraft.getMinecraft(this).fontRenderer, 0, 0, width, getHeight(), defaultText, placeholder);
+        this.textField = new TextFieldElement(null, Minecraft.getMinecraft(this).font, 0, 0, width, getHeight(), defaultText, placeholder);
     }
 
     @Override
-    public void setParent(GuiPopup parent)
+    public void setParent(PopupScreen parent)
     {
         super.setParent(parent);
         this.textField.parent = parent;
diff --git a/src/main/java/net/minecraft/client/gui/subtitles/SubtitleTracker.java b/src/main/java/net/minecraft/client/gui/subtitles/SubtitleTracker.java
new file mode 100644
index 000000000..0d7a8e120
--- /dev/null
+++ b/src/main/java/net/minecraft/client/gui/subtitles/SubtitleTracker.java
@@ -0,0 +1,68 @@
+package net.minecraft.client.gui.subtitles;
+
+import net.minecraft.client.sound.SoundEvent;
+import net.minecraft.core.entity.Entity;
+import net.minecraft.core.util.helper.MathHelper;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class SubtitleTracker {
+    public static final int SUBTITLE_LIFETIME_MS = 5000;
+    public final Map<SoundEvent, SubtitleEntry> entryMap = new LinkedHashMap<>();
+
+    public void heardSound(SoundEvent event, double x, double y, double z) {
+        if (entryMap.containsKey(event)) {
+            entryMap.get(event).wasHeard(event, x, y, z);
+        } else {
+            entryMap.put(event, new SubtitleEntry(event, x, y, z));
+        }
+    }
+
+    private static final List<SoundEvent> removalQueue = new ArrayList<>();
+    public void tick() {
+        long currentTime = System.currentTimeMillis();
+        for (SubtitleEntry e : entryMap.values()) {
+            if (currentTime - e.lastHeardTime > SUBTITLE_LIFETIME_MS) {
+                removalQueue.add(e.soundEvent);
+            }
+        }
+        removalQueue.forEach(entryMap::remove);
+        removalQueue.clear();
+    }
+
+    public void clear() {
+        entryMap.clear();
+    }
+
+    public static class SubtitleEntry {
+        public double sourceX;
+        public double sourceY;
+        public double sourceZ;
+        public SoundEvent soundEvent;
+        public long lastHeardTime;
+        public SubtitleEntry(SoundEvent event, double x, double y, double z) {
+            wasHeard(event, x, y, z);
+        }
+
+        public void wasHeard(SoundEvent event, double x, double y, double z) {
+            this.sourceX = x;
+            this.sourceY = y;
+            this.sourceZ = z;
+            this.soundEvent = event;
+            this.lastHeardTime = System.currentTimeMillis();
+        }
+
+        public float getFadeout() {
+            return  ((float) (System.currentTimeMillis() - lastHeardTime) / SUBTITLE_LIFETIME_MS);
+        }
+
+        public double getRelativeAngle(Entity listener) {
+            if (listener == null) return Float.NaN;
+            double angle = Math.atan2(sourceZ - listener.z, sourceX - listener.x);
+            return angle - Math.toRadians(listener.yRot);
+        }
+    }
+}
diff --git a/src/main/java/net/minecraft/client/gui/text/TextFieldEditor.java b/src/main/java/net/minecraft/client/gui/text/TextFieldEditor.java
index fe10f3c52..67ebfd662 100644
--- a/src/main/java/net/minecraft/client/gui/text/TextFieldEditor.java
+++ b/src/main/java/net/minecraft/client/gui/text/TextFieldEditor.java
@@ -1,8 +1,10 @@
 package net.minecraft.client.gui.text;
 
+import com.mojang.logging.LogUtils;
 import org.lwjgl.input.Keyboard;
 
 import net.minecraft.core.util.helper.MathHelper;
+import org.slf4j.Logger;
 
 import java.awt.*;
 import java.awt.datatransfer.Clipboard;
@@ -12,6 +14,7 @@ import java.awt.datatransfer.Transferable;
 
 public class TextFieldEditor
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static String substring(String s, int start, int end)
     {
         if (start < 0) start = 0;
@@ -178,7 +181,7 @@ public class TextFieldEditor
         if (cursor > currentText.length()) setCursor(currentText.length());
         if (cursor < 0) setCursor(0);
 
-        if (currentText.length() == 0)
+        if (currentText.isEmpty())
         {
             setText(String.valueOf(c));
         }
@@ -261,7 +264,7 @@ public class TextFieldEditor
         }
         catch (Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Exception while trying to copy text field to clipboard!", e);
         }
     }
 
@@ -277,7 +280,7 @@ public class TextFieldEditor
         }
         catch (Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Exception while trying to read clipboard!", e);
         }
         return null;
     }
diff --git a/src/main/java/net/minecraft/client/gui/toasts/GuiHudToasts.java b/src/main/java/net/minecraft/client/gui/toasts/HudToastsElement.java
similarity index 89%
rename from src/main/java/net/minecraft/client/gui/toasts/GuiHudToasts.java
rename to src/main/java/net/minecraft/client/gui/toasts/HudToastsElement.java
index 497e3c57f..4109c35e2 100644
--- a/src/main/java/net/minecraft/client/gui/toasts/GuiHudToasts.java
+++ b/src/main/java/net/minecraft/client/gui/toasts/HudToastsElement.java
@@ -17,7 +17,7 @@ import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
 
-public class GuiHudToasts extends Gui {
+public class HudToastsElement extends Gui {
     private static final int TOAST_WIDTH = 160;
     private static final int TOAST_HEIGHT = 32;
     private static final int MAX_SHOWN_ENTRIES = 5;
@@ -27,7 +27,7 @@ public class GuiHudToasts extends Gui {
 
     private final Minecraft mc;
 
-    public GuiHudToasts(Minecraft minecraft) {
+    public HudToastsElement(Minecraft minecraft) {
         mc = minecraft;
     }
 
@@ -90,9 +90,9 @@ public class GuiHudToasts extends Gui {
             String s = I18n.getInstance().translateKeyAndFormat("gui.achievement.label.unlicensed.1", Global.VERSION);
             String s1 = I18n.getInstance().translateKey("gui.achievement.label.unlicensed.2");
             String s2 = I18n.getInstance().translateKey("gui.achievement.label.unlicensed.3");
-            mc.fontRenderer.drawStringWithShadow(s, 2, 2, 0xffffff);
-            mc.fontRenderer.drawStringWithShadow(s1, 2, 11, 0xffffff);
-            mc.fontRenderer.drawStringWithShadow(s2, 2, 20, 0xffffff);
+            mc.font.drawStringWithShadow(s, 2, 2, 0xffffff);
+            mc.font.drawStringWithShadow(s1, 2, 11, 0xffffff);
+            mc.font.drawStringWithShadow(s2, 2, 20, 0xffffff);
             GL11.glDepthMask(true);
             GL11.glEnable(GL11.GL_DEPTH_TEST);
         }
@@ -166,10 +166,10 @@ public class GuiHudToasts extends Gui {
 
         drawGuiIcon(x, y, TOAST_WIDTH, TOAST_HEIGHT, TextureRegistry.getTexture(toast.getTexture(duration)));
         if(toast.messageOnly(duration)) {
-            mc.fontRenderer.drawStringIntoConstrainedBlock(toast.getMessage(duration), x + 30, y + 7, 120, toast.descriptionColor(duration));
+            mc.font.drawStringIntoConstrainedBlock(toast.getMessage(duration), x + 30, y + 7, 120, toast.descriptionColor(duration));
         } else {
-            mc.fontRenderer.drawString(toast.getTitle(duration), x + 30, y + 7, toast.nameColor(duration));
-            mc.fontRenderer.drawString(toast.getMessage(duration), x + 30, y + 18, toast.descriptionColor(duration));
+            mc.font.drawString(toast.getTitle(duration), x + 30, y + 7, toast.nameColor(duration));
+            mc.font.drawString(toast.getMessage(duration), x + 30, y + 18, toast.descriptionColor(duration));
         }
 
         GL11.glDepthMask(true);
@@ -179,7 +179,7 @@ public class GuiHudToasts extends Gui {
 
         GL11.glEnable(GL11.GL_DEPTH_TEST);
         ItemStack icon = toast.getIcon(duration);
-        ItemModelDispatcher.getInstance().getDispatch(icon).renderItemIntoGui(Tessellator.instance, mc.fontRenderer, mc.renderEngine, icon, x + 8, y + 8, 1.0f);
+        ItemModelDispatcher.getInstance().getDispatch(icon).renderItemIntoGui(Tessellator.instance, mc.font, mc.textureManager, icon, x + 8, y + 8, 1.0f);
         GL11.glDisable(GL11.GL_DEPTH_TEST);
     }
 
diff --git a/src/main/java/net/minecraft/client/input/InputHandler.java b/src/main/java/net/minecraft/client/input/InputHandler.java
index b8f1c3ad2..4dca2a85a 100644
--- a/src/main/java/net/minecraft/client/input/InputHandler.java
+++ b/src/main/java/net/minecraft/client/input/InputHandler.java
@@ -1,14 +1,16 @@
 package net.minecraft.client.input;
 
-import net.minecraft.client.input.glfw.FakeGamepad;
+import com.mojang.logging.LogUtils;
+import net.minecraft.client.input.glfw.GlfwGamepad;
+import net.minecraft.client.input.glfw.GlfwJoystick;
 import org.lwjgl.glfw.GLFW;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.input.controller.ControllerInput;
-import net.minecraft.client.input.glfw.GlfwGamepad;
-import net.minecraft.client.input.glfw.GlfwJoystick;
+import org.slf4j.Logger;
 
 public abstract class InputHandler {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static Minecraft minecraft;
 	public static ControllerInput[] controllers = new ControllerInput[GLFW.GLFW_JOYSTICK_LAST + 1];
 	
@@ -18,7 +20,7 @@ public abstract class InputHandler {
 		try {
 			initLWJGL3(minecraft);
 		} catch (Throwable e) {
-			System.err.println("Could not initialize LWJGL3.");
+			LOGGER.error("Could not initialize LWJGL3.");
 			e.printStackTrace();
 		}
 	}
@@ -46,12 +48,12 @@ public abstract class InputHandler {
 	}
 
 	private static void connected(ControllerInput controller) {
-		System.out.println("Controller connected: " + controller.getGUID());
+        LOGGER.info("Controller connected: {}", controller.getGUID());
 		minecraft.controllerInput = getController(controller.getGUID());
 	}
 
 	private static void disconnected(ControllerInput controller) {
-		System.out.println("Controller disconnected: " + controller.getGUID());
+        LOGGER.info("Controller disconnected: {}", controller.getGUID());
 		if(minecraft.controllerInput == controller) {
 			minecraft.setInputType(InputType.KEYBOARD);
 			minecraft.controllerInput = null;
@@ -76,9 +78,9 @@ public abstract class InputHandler {
 //		for (int i = 0; i < vids.length; i++) {
 //			controllers[GLFW.GLFW_JOYSTICK_1 + i] = new ControllerInput(minecraft, new FakeGamepad(GLFW.GLFW_JOYSTICK_1 + i, names[i], vids[i], pids[i]));
 //		}
-		System.out.println(found + " controllers found!");
+    LOGGER.info("{} controllers found!", found);
 	}
-	
+
 	public static ControllerInput getController(String guid) {
 		try {
 			for(ControllerInput controllerInput : controllers) {
@@ -86,8 +88,7 @@ public abstract class InputHandler {
 					return controllerInput;
 				}
 			}
-		}catch (Exception e) {}
+		}catch (Exception ignored) {}
 		return null;
 	}
-
 }
diff --git a/src/main/java/net/minecraft/client/input/controller/ControllerInput.java b/src/main/java/net/minecraft/client/input/controller/ControllerInput.java
index 77ed4c282..080dfd0d2 100644
--- a/src/main/java/net/minecraft/client/input/controller/ControllerInput.java
+++ b/src/main/java/net/minecraft/client/input/controller/ControllerInput.java
@@ -2,7 +2,7 @@ package net.minecraft.client.input.controller;
 
 import com.b100.utils.ReflectUtils;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiContainer;
+import net.minecraft.client.gui.container.AbstractContainerScreen;
 import net.minecraft.client.input.glfw.GlfwGamepad;
 import net.minecraft.core.player.inventory.slot.Slot;
 import net.minecraft.core.util.helper.Time;
@@ -41,7 +41,7 @@ public class ControllerInput {
 
     private final ControllerType type;
 
-    public final ControllerInventoryHandler craftingGuiHandler = new ControllerInventoryHandler(this);
+    public final ControllerInventoryHandler inventoryHandler = new ControllerInventoryHandler(this);
 
     private boolean disconnected = false;
 
@@ -145,17 +145,17 @@ public class ControllerInput {
         digitalPad.update();
     }
 
-    public Slot getSlotAtCursor(GuiContainer guiContainer) {
-        return getSlotAt((int) cursorX, (int) cursorY, guiContainer);
+    public Slot getSlotAtCursor(AbstractContainerScreen screen) {
+        return getSlotAt((int) cursorX, (int) cursorY, screen);
     }
 
-    public Slot getSlotAt(int x, int y, GuiContainer guiContainer) {
-        for (Slot slot : guiContainer.inventorySlots.slots) {
+    public Slot getSlotAt(int x, int y, AbstractContainerScreen screen) {
+        for (Slot slot : screen.inventorySlots.slots) {
             int mx = (int) cursorX;
             int my = (int) cursorY;
 
-            int slotX = (slot.x + (minecraft.resolution.scaledWidth - guiContainer.xSize) / 2) - 2;
-            int slotY = (slot.y + (minecraft.resolution.scaledHeight - guiContainer.ySize) / 2) - 2;
+            int slotX = (slot.x + (minecraft.resolution.scaledWidth - screen.xSize) / 2) - 2;
+            int slotY = (slot.y + (minecraft.resolution.scaledHeight - screen.ySize) / 2) - 2;
 
             if (mx > slotX && my > slotY && mx < slotX + 20 && my < slotY + 20) {
                 return slot;
@@ -164,15 +164,15 @@ public class ControllerInput {
         return null;
     }
 
-    public void snapToSlot(GuiContainer guiContainer, int id) {
-        snapToSlot(guiContainer, guiContainer.inventorySlots.getSlot(id));
+    public void snapToSlot(AbstractContainerScreen screen, int id) {
+        snapToSlot(screen, screen.inventorySlots.getSlot(id));
     }
 
-    public void snapToSlot(GuiContainer guiContainer, Slot slot) {
+    public void snapToSlot(AbstractContainerScreen screen, Slot slot) {
         if (slot == null) return;
 
-        int slotX = (slot.x + (minecraft.resolution.scaledWidth - guiContainer.xSize) / 2) - 1;
-        int slotY = (slot.y + (minecraft.resolution.scaledHeight - guiContainer.ySize) / 2) - 1;
+        int slotX = (slot.x + (minecraft.resolution.scaledWidth - screen.xSize) / 2) - 1;
+        int slotY = (slot.y + (minecraft.resolution.scaledHeight - screen.ySize) / 2) - 1;
 
         //Snap to Slot
         cursorX = slotX + 8;
diff --git a/src/main/java/net/minecraft/client/input/controller/ControllerInventoryHandler.java b/src/main/java/net/minecraft/client/input/controller/ControllerInventoryHandler.java
index 01ae1f0a8..fdda3ca7e 100644
--- a/src/main/java/net/minecraft/client/input/controller/ControllerInventoryHandler.java
+++ b/src/main/java/net/minecraft/client/input/controller/ControllerInventoryHandler.java
@@ -1,14 +1,16 @@
 package net.minecraft.client.input.controller;
 
 import com.b100.utils.interfaces.Condition;
-import net.minecraft.client.gui.GuiContainer;
-import net.minecraft.client.gui.GuiCrafting;
-import net.minecraft.client.gui.GuiFurnace;
-import net.minecraft.client.gui.GuiInventory;
+import com.mojang.logging.LogUtils;
+import net.minecraft.client.gui.container.AbstractContainerScreen;
+import net.minecraft.client.gui.container.CraftingScreen;
+import net.minecraft.client.gui.container.FurnaceScreen;
+import net.minecraft.client.gui.container.InventoryScreen;
 import net.minecraft.core.player.inventory.slot.Slot;
+import org.slf4j.Logger;
 
 public class ControllerInventoryHandler {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public final ControllerInput controllerInput;
 	
 	private Slot lastSlot;
@@ -17,12 +19,12 @@ public class ControllerInventoryHandler {
 		this.controllerInput = controllerInput;
 	}
 	
-	public void handleAbstractCrafting(GuiContainer container, Condition<Slot> isInventorySlot, Condition<Slot> isCraftingSlot, Condition<Slot> isResultSlot, int craftingSlot, int resultSlot, int invSlot) {
+	public void handleAbstractCrafting(AbstractContainerScreen container, Condition<Slot> isInventorySlot, Condition<Slot> isCraftingSlot, Condition<Slot> isResultSlot, int craftingSlot, int resultSlot, int invSlot) {
 		Slot slot = controllerInput.getSlotAtCursor(container);
 		
 		if(controllerInput.buttonA.pressedThisFrame()) {
 			for(Slot slot2 : container.inventorySlots.slots) {
-				System.out.println(slot2.index +": "+slot2.getItem());
+                LOGGER.debug("{}: {}", slot2.index, slot2.getItem());
 			}
 		}
 		
@@ -42,7 +44,7 @@ public class ControllerInventoryHandler {
 						controllerInput.snapToSlot(container, invSlot); //Inventory Center
 					}
 				}else {
-					if(slot != null && slot.index > 9) lastSlot = slot;
+					if(slot.index > 9) lastSlot = slot;
 					controllerInput.snapToSlot(container, craftingSlot); //Crafting Grid Center
 				}
 			}else {
@@ -67,20 +69,20 @@ public class ControllerInventoryHandler {
 		}
 	}
 	
-	public void handleCrafting(GuiCrafting crafting) {
+	public void handleCrafting(CraftingScreen crafting) {
 		handleAbstractCrafting(crafting, (e) -> e.index > 9, (e) -> e.index > 0 && e.index < 10, (e) -> e.index == 0, 5, 0, 24);
 	}
 	
-	public void handleInventory(GuiInventory inventory) {
+	public void handleInventory(InventoryScreen inventory) {
 		handleAbstractCrafting(inventory, (e) -> e.index >= 9 && e.index <= 44, (e) -> e.index >= 1 && e.index <= 4, (e) -> e.index == 0, 1, 0, 22);
 	}
 	
-	public void handleFurnace(GuiFurnace furnace) {
+	public void handleFurnace(FurnaceScreen furnace) {
 		handleAbstractCrafting(furnace, (e) -> e.index >= 3 && e.index <= 38, (e) -> e.index >= 0 && e.index <= 1, (e) -> e.index == 2, 0, 2, 16);
 	}
 	
-	public void click(GuiContainer guiCrafting, int button) {
-		guiCrafting.mouseClicked((int)controllerInput.cursorX, (int)controllerInput.cursorY, button);
+	public void click(AbstractContainerScreen screen, int button) {
+		screen.mouseClicked((int)controllerInput.cursorX, (int)controllerInput.cursorY, button);
 	}
 	
 }
diff --git a/src/main/java/net/minecraft/client/lang/text/Text.java b/src/main/java/net/minecraft/client/lang/text/Text.java
index 2ac6d34f8..4d1f98374 100644
--- a/src/main/java/net/minecraft/client/lang/text/Text.java
+++ b/src/main/java/net/minecraft/client/lang/text/Text.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.lang.text;
 
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.core.net.command.TextFormatting;
 
 public abstract class Text {
@@ -17,8 +17,8 @@ public abstract class Text {
 
     abstract void toString(StringBuilder sb);
 
-    public int width(FontRenderer fontRenderer) {
-        return fontRenderer.getStringWidth(this.toString());
+    public int width(Font font) {
+        return font.getStringWidth(this.toString());
     }
 
     public Text trans(String languageKey) {
diff --git a/src/main/java/net/minecraft/client/net/handler/ClientPacketHandler.java b/src/main/java/net/minecraft/client/net/handler/ClientPacketHandler.java
index b3b04d307..92d104a91 100644
--- a/src/main/java/net/minecraft/client/net/handler/ClientPacketHandler.java
+++ b/src/main/java/net/minecraft/client/net/handler/ClientPacketHandler.java
@@ -1,14 +1,15 @@
 package net.minecraft.client.net.handler;
 
 import com.b100.utils.StringUtils;
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.particle.TakeAnimationParticle;
 import net.minecraft.client.entity.player.LocalPlayer;
 import net.minecraft.client.entity.player.RemotePlayer;
-import net.minecraft.client.gui.GuiConnectFailed;
-import net.minecraft.client.gui.GuiDownloadTerrain;
-import net.minecraft.client.gui.GuiIngameMenu;
-import net.minecraft.client.gui.guidebook.GuiGuidebook;
+import net.minecraft.client.gui.ConnectFailedScreen;
+import net.minecraft.client.gui.DownloadTerrainScreen;
+import net.minecraft.client.gui.PauseScreen;
+import net.minecraft.client.gui.guidebook.GuidebookScreen;
 import net.minecraft.client.gui.guidebook.PageManager;
 import net.minecraft.client.gui.guidebook.search.SearchPage;
 import net.minecraft.client.player.controller.PlayerControllerMP;
@@ -114,10 +115,12 @@ import net.minecraft.core.world.Explosion;
 import net.minecraft.core.world.ExplosionCannonball;
 import net.minecraft.core.world.IVehicle;
 import net.minecraft.core.world.chunk.ChunkCoordinates;
+import net.minecraft.core.world.data.SynchedEntityData;
 import net.minecraft.core.world.save.LevelData;
 import net.minecraft.core.world.saveddata.SavedDataStorage;
 import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.weather.Weathers;
+import org.slf4j.Logger;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -133,6 +136,7 @@ import java.util.Random;
 
 public class ClientPacketHandler extends PacketHandler
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private boolean disconnected;
     private final NetworkManager netManager;
     public String message; // Name from b1.2 leak
@@ -211,26 +215,26 @@ public class ClientPacketHandler extends PacketHandler
         worldClient.isClientSide = true;
         mc.changeWorld(worldClient);
         mc.thePlayer.dimension = loginPacket.dimensionId;
-        mc.displayGuiScreen(new GuiDownloadTerrain(this));
+        mc.displayScreen(new DownloadTerrainScreen(this));
         mc.thePlayer.id = loginPacket.playerEntityIdAndProtocolVersion;
         NetworkManager.PACKET_DELAY = loginPacket.packetDelay;
         Registries.RECIPES = new RecipeRegistry();
     }
 
     @Override
-    public void handlePickupSpawn(AddItemEntityPacket addItemEntityPacket21Pickupspawn)
+    public void handlePickupSpawn(AddItemEntityPacket itemEntityPacket)
     {
-        double x = addItemEntityPacket21Pickupspawn.xPosition / 32D;
-        double y = addItemEntityPacket21Pickupspawn.yPosition / 32D;
-        double z = addItemEntityPacket21Pickupspawn.zPosition / 32D;
-        ItemEntity entityitem = new ItemEntity(worldClient, x, y, z, new ItemStack(addItemEntityPacket21Pickupspawn.itemID, addItemEntityPacket21Pickupspawn.count, addItemEntityPacket21Pickupspawn.itemDamage, addItemEntityPacket21Pickupspawn.tag));
-        entityitem.xd = (double) addItemEntityPacket21Pickupspawn.xd / 128D;
-        entityitem.yd = (double) addItemEntityPacket21Pickupspawn.yd / 128D;
-        entityitem.zd = (double) addItemEntityPacket21Pickupspawn.zd / 128D;
-        entityitem.serverPosX = addItemEntityPacket21Pickupspawn.xPosition;
-        entityitem.serverPosY = addItemEntityPacket21Pickupspawn.yPosition;
-        entityitem.serverPosZ = addItemEntityPacket21Pickupspawn.zPosition;
-        worldClient.addEntityToWorld(addItemEntityPacket21Pickupspawn.entityId, entityitem);
+        double x = itemEntityPacket.xPosition / 32D;
+        double y = itemEntityPacket.yPosition / 32D;
+        double z = itemEntityPacket.zPosition / 32D;
+        ItemEntity itemEntity = new ItemEntity(worldClient, x, y, z, new ItemStack(itemEntityPacket.itemID, itemEntityPacket.count, itemEntityPacket.itemDamage, itemEntityPacket.tag));
+        itemEntity.xd = (double) itemEntityPacket.xd / 128D;
+        itemEntity.yd = (double) itemEntityPacket.yd / 128D;
+        itemEntity.zd = (double) itemEntityPacket.zd / 128D;
+        itemEntity.serverPosX = itemEntityPacket.xPosition;
+        itemEntity.serverPosY = itemEntityPacket.yPosition;
+        itemEntity.serverPosZ = itemEntityPacket.zPosition;
+        worldClient.addEntityToWorld(itemEntityPacket.entityId, itemEntity);
     }
 
 
@@ -337,40 +341,40 @@ public class ClientPacketHandler extends PacketHandler
     }
 
     @Override
-    public void handleEntityMetadata(SetEntityDataPacket entitymetadata)
+    public void handleEntityMetadata(SetEntityDataPacket entityDataPacket)
     {
-        Entity entity = getEntityByID(entitymetadata.entityId);
-        if (entity != null && entitymetadata.getUnpackedData() != null)
+        Entity entity = getEntityByID(entityDataPacket.entityId);
+        if (entity != null && entityDataPacket.getUnpackedData() != null)
         {
-            entity.getEntityData().assignValues(entitymetadata.getUnpackedData());
+            entity.getEntityData().assignValues(entityDataPacket.getUnpackedData());
         }
     }
 
     @Override
-    public void handleNamedEntitySpawn(AddPlayerPacket addPlayerPacket20Namedentityspawn)
-    {
-        double d = (double) addPlayerPacket20Namedentityspawn.xPosition / 32D;
-        double d1 = (double) addPlayerPacket20Namedentityspawn.yPosition / 32D;
-        double d2 = (double) addPlayerPacket20Namedentityspawn.zPosition / 32D;
-        float f = (float) (addPlayerPacket20Namedentityspawn.rotation * 360) / 256F;
-        float f1 = (float) (addPlayerPacket20Namedentityspawn.pitch * 360) / 256F;
-        RemotePlayer entityotherplayermp = new RemotePlayer(mc.theWorld, addPlayerPacket20Namedentityspawn.name);
-        entityotherplayermp.xo = entityotherplayermp.serverPosX = addPlayerPacket20Namedentityspawn.xPosition;
-        entityotherplayermp.yo = entityotherplayermp.serverPosY = addPlayerPacket20Namedentityspawn.yPosition;
-        entityotherplayermp.zo = entityotherplayermp.serverPosZ = addPlayerPacket20Namedentityspawn.zPosition;
-        int i = addPlayerPacket20Namedentityspawn.currentItem;
+    public void handleNamedEntitySpawn(AddPlayerPacket playerPacket)
+    {
+        double d = (double) playerPacket.xPosition / 32D;
+        double d1 = (double) playerPacket.yPosition / 32D;
+        double d2 = (double) playerPacket.zPosition / 32D;
+        float f = (float) (playerPacket.rotation * 360) / 256F;
+        float f1 = (float) (playerPacket.pitch * 360) / 256F;
+        RemotePlayer remotePlayer = new RemotePlayer(mc.theWorld, playerPacket.name, playerPacket.uuid);
+        remotePlayer.xo = remotePlayer.serverPosX = playerPacket.xPosition;
+        remotePlayer.yo = remotePlayer.serverPosY = playerPacket.yPosition;
+        remotePlayer.zo = remotePlayer.serverPosZ = playerPacket.zPosition;
+        int i = playerPacket.currentItem;
         if (i == 0)
         {
-            entityotherplayermp.inventory.mainInventory[entityotherplayermp.inventory.currentItem] = null;
+            remotePlayer.inventory.mainInventory[remotePlayer.inventory.currentItem] = null;
         }
         else
         {
-            entityotherplayermp.inventory.mainInventory[entityotherplayermp.inventory.currentItem] = new ItemStack(i, 1, 0);
+            remotePlayer.inventory.mainInventory[remotePlayer.inventory.currentItem] = new ItemStack(i, 1, 0);
         }
-        entityotherplayermp.absMoveTo(d, d1, d2, f, f1);
-        worldClient.addEntityToWorld(addPlayerPacket20Namedentityspawn.entityId, entityotherplayermp);
-        entityotherplayermp.nickname = StringUtils.substring(addPlayerPacket20Namedentityspawn.nickname, 0, 32);
-        entityotherplayermp.chatColor = addPlayerPacket20Namedentityspawn.chatColor;
+        remotePlayer.absMoveTo(d, d1, d2, f, f1);
+        worldClient.addEntityToWorld(playerPacket.entityId, remotePlayer);
+        remotePlayer.nickname = StringUtils.substring(playerPacket.nickname, 0, 32);
+        remotePlayer.chatColor = playerPacket.chatColor;
     }
 
     @Override
@@ -483,7 +487,7 @@ public class ClientPacketHandler extends PacketHandler
             mc.thePlayer.yo = mc.thePlayer.y;
             mc.thePlayer.zo = mc.thePlayer.z;
             started = true;
-            mc.displayGuiScreen(null);
+            mc.displayScreen(null);
         }
     }
 
@@ -532,7 +536,7 @@ public class ClientPacketHandler extends PacketHandler
         netManager.networkShutdown("disconnect.kicked", new Object[0]);
         disconnected = true;
         mc.changeWorld(null);
-        mc.displayGuiScreen(new GuiConnectFailed("disconnect.disconnected", "disconnect.genericReason", new Object[]{
+        mc.displayScreen(new ConnectFailedScreen("disconnect.disconnected", "disconnect.genericReason", new Object[]{
             packet255KickdisconnectPacket.reason
         }));
     }
@@ -545,29 +549,23 @@ public class ClientPacketHandler extends PacketHandler
             try {
                 mc.changeWorld(null); // Leave current world
             } catch (Exception e) {
-                e.printStackTrace();
+                LOGGER.error("Exception when leaving world!", e);
             }
             try {
-                mc.displayGuiScreen(null); // Exit out of current GUI
+                mc.displayScreen(null); // Exit out of current GUI
             } catch (Exception e) {
-                e.printStackTrace();
+                LOGGER.error("Exception when leaving GUI!", e);
             }
 
-            mc.displayGuiScreen(new GuiConnectFailed("disconnect.lost", s, errorLines)); // Open error message gui
+            mc.displayScreen(new ConnectFailedScreen("disconnect.lost", s, errorLines)); // Open error message gui
         }
     }
 
     public void func_28117_a(Packet packet)
     {
-        if (disconnected)
-        {
-            return;
-        }
-        else
-        {
+        if (!disconnected) {
             netManager.addToSendQueue(packet);
             netManager.serverShutdown();
-            return;
         }
     }
 
@@ -581,18 +579,18 @@ public class ClientPacketHandler extends PacketHandler
     @Override
     public void handleCollect(TakeItemEntityPacket takeItemEntityPacket)
     {
-        Entity entity = getEntityByID(takeItemEntityPacket.collectedEntityId);
-        Object obj = (Mob) getEntityByID(takeItemEntityPacket.collectorEntityId);
-        if (obj == null)
+        Entity item = getEntityByID(takeItemEntityPacket.collectedEntityId);
+        Entity collector = getEntityByID(takeItemEntityPacket.collectorEntityId);
+        if (collector == null)
         {
-            obj = mc.thePlayer;
+            collector = mc.thePlayer;
         }
-        if (entity != null)
+        if (item != null)
         {
             // this class does not seem to handle pick up from server dropped items. find where it is.
             // something about that isn't working on servers if the player changed their gamemode.
-            worldClient.playSoundAtEntity(null, entity, "random.pop", 0.2F, ((rand.nextFloat() - rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
-            mc.effectRenderer.addEffect(new TakeAnimationParticle(mc.theWorld, entity, ((Entity) (obj)), -0.5F));
+            worldClient.playSoundAtEntity(null, item, "random.pop", 0.2F, ((rand.nextFloat() - rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
+            mc.particleEngine.add(new TakeAnimationParticle(mc.theWorld, item, collector, -0.5F));
             worldClient.removeEntityFromWorld(takeItemEntityPacket.collectedEntityId);
         }
     }
@@ -612,20 +610,20 @@ public class ClientPacketHandler extends PacketHandler
 		
 		int type = packet.type;
 		if(type == 1) {
-			mc.ingameGUI.guiHeldItemTooltip.setString(message);
+			mc.ingameHud.heldItemTooltipElement.setString(message);
 		}else {
-			mc.ingameGUI.addChatMessage(message);
+			mc.ingameHud.addChatMessage(message);
 		}
 	}
 
     public void handlePlayerJoin(ChatPacket chatPacket)
     {
-        mc.ingameGUI.addChatMessage(chatPacket.message);
+        mc.ingameHud.addChatMessage(chatPacket.message);
     }
 
     public void handlePlayerLeave(ChatPacket chatPacket)
     {
-        mc.ingameGUI.addChatMessage(chatPacket.message);
+        mc.ingameHud.addChatMessage(chatPacket.message);
     }
 
     @Override
@@ -647,13 +645,13 @@ public class ClientPacketHandler extends PacketHandler
         }
         else if (animatePacket.animate == 3)
         {
-            Player entityplayer1 = (Player) entity;
-            entityplayer1.wakeUpPlayer(false, false);
+            Player player = (Player) entity;
+            player.wakeUpPlayer(false, false);
         }
         else if (animatePacket.animate == 4)
         {
-            Player entityplayer2 = (Player) entity;
-            entityplayer2.func_6420_o();
+            Player player = (Player) entity;
+            player.animate4();
         }
     }
 
@@ -680,7 +678,7 @@ public class ClientPacketHandler extends PacketHandler
             try
             {
                 RSA.RSAKeyChain = RSA.generateKeyPair();
-                addToSendQueue(new LoginPacket(mc.session.username, Global.MP_PROTOCOL_VERSION, RSA.getPublicKey(RSA.RSAKeyChain.getPublic())));
+                addToSendQueue(new LoginPacket(mc.session.username, mc.session.uuid, Global.MP_PROTOCOL_VERSION, RSA.getPublicKey(RSA.RSAKeyChain.getPublic())));
             }
             catch (Exception e)
             {
@@ -700,11 +698,11 @@ public class ClientPacketHandler extends PacketHandler
                     try
                     {
                         RSA.RSAKeyChain = RSA.generateKeyPair();
-                        addToSendQueue(new LoginPacket(mc.session.username, Global.MP_PROTOCOL_VERSION, RSA.getPublicKey(RSA.RSAKeyChain.getPublic())));
+                        addToSendQueue(new LoginPacket(mc.session.username, mc.session.uuid, Global.MP_PROTOCOL_VERSION, RSA.getPublicKey(RSA.RSAKeyChain.getPublic())));
                     }
                     catch (Exception e)
                     {
-                        throw new RuntimeException(e);
+                        throw new RuntimeException("Exception while creating LoginPacket!", e);
                     }
                 }
                 else
@@ -716,9 +714,9 @@ public class ClientPacketHandler extends PacketHandler
             }
             catch (Exception exception)
             {
-                exception.printStackTrace();
+                LOGGER.error("Login Exception!", exception);
                 netManager.networkShutdown("disconnect.genericReason", new Object[]{
-                        "Internal client error: " + exception.toString()
+                        "Internal client error: " + exception
                 });
             }
         }
@@ -733,7 +731,7 @@ public class ClientPacketHandler extends PacketHandler
         }
         catch (Exception e)
         {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Failed to get AES key!", e);
         }
     }
 
@@ -764,27 +762,27 @@ public class ClientPacketHandler extends PacketHandler
         double d2 = (double) addMobspawn.z / 32D;
         float f = (float) (addMobspawn.yaw * 360) / 256F;
         float f1 = (float) (addMobspawn.pitch * 360) / 256F;
-        Mob entityliving = (Mob) EntityDispatcher.createEntity(addMobspawn.type, mc.theWorld);
-        entityliving.serverPosX = addMobspawn.x;
-        entityliving.serverPosY = addMobspawn.y;
-        entityliving.serverPosZ = addMobspawn.z;
-        entityliving.id = addMobspawn.id;
-        entityliving.absMoveTo(d, d1, d2, f, f1);
-        entityliving.isMultiplayerEntity = true;
-        worldClient.addEntityToWorld(addMobspawn.id, entityliving);
-        java.util.List list = addMobspawn.getUnpackedData();
+        Mob mob = (Mob) EntityDispatcher.createEntity(addMobspawn.type, mc.theWorld);
+        mob.serverPosX = addMobspawn.x;
+        mob.serverPosY = addMobspawn.y;
+        mob.serverPosZ = addMobspawn.z;
+        mob.id = addMobspawn.id;
+        mob.absMoveTo(d, d1, d2, f, f1);
+        mob.isMultiplayerEntity = true;
+        worldClient.addEntityToWorld(addMobspawn.id, mob);
+        List<SynchedEntityData.DataItem<?>> list = addMobspawn.getUnpackedData();
         if (list != null)
         {
-            entityliving.getEntityData().assignValues(list);
+            mob.getEntityData().assignValues(list);
         }
-        entityliving.nickname = StringUtils.substring(addMobspawn.nickname, 0, 32);
-        entityliving.chatColor = addMobspawn.chatColor;
+        mob.nickname = StringUtils.substring(addMobspawn.nickname, 0, 32);
+        mob.chatColor = addMobspawn.chatColor;
     }
 
     @Override
-    public void handleUpdateTime(SetTimePacket packet4UpdatetimePacket)
+    public void handleUpdateTime(SetTimePacket timePacket)
     {
-        mc.theWorld.setWorldTime(packet4UpdatetimePacket.time);
+        mc.theWorld.setWorldTime(timePacket.time);
     }
 
     @Override
@@ -836,23 +834,23 @@ public class ClientPacketHandler extends PacketHandler
     }
 
     @Override
-    public void handleUpdateHealth(SetHealthPacket packet8UpdatehealthPacket)
+    public void handleUpdateHealth(SetHealthPacket healthPacket)
     {
-        mc.thePlayer.setHealth(packet8UpdatehealthPacket.healthMP);
+        mc.thePlayer.setHealth(healthPacket.healthMP);
     }
 
     @Override
-    public void handleUpdatePlayerProfile(UpdatePlayerProfilePacket packet72playerprofile)
+    public void handleUpdatePlayerProfile(UpdatePlayerProfilePacket profilePacket)
     {
-        PlayerProfile playerProfile = new PlayerProfile(packet72playerprofile.username, packet72playerprofile.nickname, packet72playerprofile.score, packet72playerprofile.chatColor, packet72playerprofile.isOperator);
-        if (playerProfile.playerName.equals(mc.thePlayer.username))
+        PlayerProfile playerProfile = new PlayerProfile(profilePacket.username, profilePacket.nickname, profilePacket.uuid, profilePacket.score, profilePacket.chatColor, profilePacket.isOperator);
+        if (playerProfile.uuid.equals(mc.thePlayer.uuid))
         {
             mc.thePlayer.score = playerProfile.scoreTotal;
         }
         int index = findPlayerInList(playerProfile);
         if (index != -1)
         {
-            if (!packet72playerprofile.isOnline)
+            if (!profilePacket.isOnline)
             {
                 removePlayer(index);
             }
@@ -877,7 +875,7 @@ public class ClientPacketHandler extends PacketHandler
             worldClient.isClientSide = true;
             mc.changeWorld(worldClient);
             mc.thePlayer.dimension = respawnPacket.respawnDimensionId;
-            mc.displayGuiScreen(new GuiDownloadTerrain(this));
+            mc.displayScreen(new DownloadTerrainScreen(this));
         }
         mc.respawn(true, respawnPacket.respawnDimensionId);
     }
@@ -900,66 +898,66 @@ public class ClientPacketHandler extends PacketHandler
     }
 
     @Override
-    public void handleOpenWindow(ContainerOpenPacket containerOpenwindow)
+    public void handleOpenWindow(ContainerOpenPacket containerOpenPacket)
     {
-        if (containerOpenwindow.inventoryType == 0)
+        if (containerOpenPacket.inventoryType == 0)
         {
-            SimpleContainer inventorybasic = new SimpleContainer(containerOpenwindow.windowTitle, containerOpenwindow.slotsCount);
-            mc.thePlayer.displayGUIChest(inventorybasic);
-            mc.thePlayer.craftingInventory.containerId = containerOpenwindow.windowId;
+            SimpleContainer simpleContainer = new SimpleContainer(containerOpenPacket.windowTitle, containerOpenPacket.slotsCount);
+            mc.thePlayer.displayContainerScreen(simpleContainer);
+            mc.thePlayer.craftingInventory.containerId = containerOpenPacket.windowId;
         }
-        else if (containerOpenwindow.inventoryType == 2)
+        else if (containerOpenPacket.inventoryType == 2)
         {
-            FurnaceBlockEntity tileentityfurnace = new FurnaceBlockEntity();
-            mc.thePlayer.displayGUIFurnace(tileentityfurnace);
-            mc.thePlayer.craftingInventory.containerId = containerOpenwindow.windowId;
+            FurnaceBlockEntity furnaceBlockEntity = new FurnaceBlockEntity();
+            mc.thePlayer.displayFurnaceScreen(furnaceBlockEntity);
+            mc.thePlayer.craftingInventory.containerId = containerOpenPacket.windowId;
         }
-        else if (containerOpenwindow.inventoryType == 3)
+        else if (containerOpenPacket.inventoryType == 3)
         {
-            DispenserBlockEntity tileentitydispenser = new DispenserBlockEntity();
-            mc.thePlayer.displayGUIDispenser(tileentitydispenser);
-            mc.thePlayer.craftingInventory.containerId = containerOpenwindow.windowId;
+            DispenserBlockEntity dispenserBlockEntity = new DispenserBlockEntity();
+            mc.thePlayer.displayDispenserScreen(dispenserBlockEntity);
+            mc.thePlayer.craftingInventory.containerId = containerOpenPacket.windowId;
         }
-        else if (containerOpenwindow.inventoryType == 4)
+        else if (containerOpenPacket.inventoryType == 4)
         {
-            BlastFurnaceBlockEntity tileentityblastfurnace = new BlastFurnaceBlockEntity();
-            mc.thePlayer.displayGUIFurnace(tileentityblastfurnace);
-            mc.thePlayer.craftingInventory.containerId = containerOpenwindow.windowId;
+            BlastFurnaceBlockEntity blastFurnaceBlockEntity = new BlastFurnaceBlockEntity();
+            mc.thePlayer.displayFurnaceScreen(blastFurnaceBlockEntity);
+            mc.thePlayer.craftingInventory.containerId = containerOpenPacket.windowId;
         }
-        else if (containerOpenwindow.inventoryType == 5)
+        else if (containerOpenPacket.inventoryType == 5)
         {
-            TrommelBlockEntity tileentitytrommel = new TrommelBlockEntity();
-            mc.thePlayer.displayGUITrommel(tileentitytrommel);
-            mc.thePlayer.craftingInventory.containerId = containerOpenwindow.windowId;
+            TrommelBlockEntity trommelBlockEntity = new TrommelBlockEntity();
+            mc.thePlayer.displayTrommelScreen(trommelBlockEntity);
+            mc.thePlayer.craftingInventory.containerId = containerOpenPacket.windowId;
         }
-        else if (containerOpenwindow.inventoryType == 7)
+        else if (containerOpenPacket.inventoryType == 7)
         {
-            mc.thePlayer.displayGUIPaintingPicker();
+            mc.thePlayer.displayPaintingPickerScreen();
         }
-        else if (containerOpenwindow.inventoryType == 1)
+        else if (containerOpenPacket.inventoryType == 1)
         {
-            LocalPlayer entityplayersp = mc.thePlayer;
-            mc.thePlayer.displayGUIWorkbench(MathHelper.floor(entityplayersp.x), MathHelper.floor(entityplayersp.y), MathHelper.floor(entityplayersp.z));
-            mc.thePlayer.craftingInventory.containerId = containerOpenwindow.windowId;
+            LocalPlayer localPlayer = mc.thePlayer;
+            mc.thePlayer.displayWorkbenchScreen(MathHelper.floor(localPlayer.x), MathHelper.floor(localPlayer.y), MathHelper.floor(localPlayer.z));
+            mc.thePlayer.craftingInventory.containerId = containerOpenPacket.windowId;
         }
     }
 
     @Override
-    public void handleOpenFlagWindow(FlagOpenPacket packet)
+    public void handleOpenFlagWindow(FlagOpenPacket flagOpenPacket)
     {
-        BlockEntity blockEntity = worldClient.getBlockEntity(packet.x, packet.y, packet.z);
+        BlockEntity blockEntity = worldClient.getBlockEntity(flagOpenPacket.x, flagOpenPacket.y, flagOpenPacket.z);
         if (blockEntity instanceof FlagBlockEntity)
         {
             FlagBlockEntity tileEntityFlag = (FlagBlockEntity) blockEntity;
-            mc.thePlayer.displayGUIEditFlag(tileEntityFlag);
-            mc.thePlayer.craftingInventory.containerId = packet.windowId;
+            mc.thePlayer.displayFlagEditorScreen(tileEntityFlag);
+            mc.thePlayer.craftingInventory.containerId = flagOpenPacket.windowId;
         }
     }
 
     @Override
     public void handlePhotoMode(PhotoModePacket packet)
     {
-        GuiIngameMenu.photoModeDisabled = packet.disabled;
+        PauseScreen.photoModeDisabled = packet.disabled;
     }
 
     @Override
@@ -1011,40 +1009,40 @@ public class ClientPacketHandler extends PacketHandler
     }
 
     @Override
-    public void handleWindowItems(ContainerSetContentPacket containerSetContentPacket104Windowitems)
+    public void handleWindowItems(ContainerSetContentPacket setContentPacket)
     {
-        if (containerSetContentPacket104Windowitems.windowId == 0)
+        if (setContentPacket.windowId == 0)
         {
-            mc.thePlayer.inventorySlots.setAll(containerSetContentPacket104Windowitems.stackList);
+            mc.thePlayer.inventorySlots.setAll(setContentPacket.stackList);
         }
-        else if (containerSetContentPacket104Windowitems.windowId == mc.thePlayer.craftingInventory.containerId)
+        else if (setContentPacket.windowId == mc.thePlayer.craftingInventory.containerId)
         {
-            mc.thePlayer.craftingInventory.setAll(containerSetContentPacket104Windowitems.stackList);
+            mc.thePlayer.craftingInventory.setAll(setContentPacket.stackList);
         }
     }
 
     @Override
-    public void handleUpdateProgressbar(ContainerSetDataPacket containerSetDataPacket105Updateprogressbar)
+    public void handleUpdateProgressbar(ContainerSetDataPacket setDataPacket)
     {
-        handleInvalidPacket(containerSetDataPacket105Updateprogressbar);
-        if (mc.thePlayer.craftingInventory != null && mc.thePlayer.craftingInventory.containerId == containerSetDataPacket105Updateprogressbar.windowId)
+        handleInvalidPacket(setDataPacket);
+        if (mc.thePlayer.craftingInventory != null && mc.thePlayer.craftingInventory.containerId == setDataPacket.windowId)
         {
-            mc.thePlayer.craftingInventory.setData(containerSetDataPacket105Updateprogressbar.progressBar, containerSetDataPacket105Updateprogressbar.progressBarValue);
+            mc.thePlayer.craftingInventory.setData(setDataPacket.progressBar, setDataPacket.progressBarValue);
         }
     }
 
     @Override
-    public void handlePlayerInventory(SetEquippedItemPacket setEquippedItemPacket5Playerinventory)
+    public void handlePlayerInventory(SetEquippedItemPacket equippedItemPacket)
     {
-        Entity entity = getEntityByID(setEquippedItemPacket5Playerinventory.entityID);
+        Entity entity = getEntityByID(equippedItemPacket.entityID);
         if (entity != null)
         {
-            entity.setEquippedSlot(setEquippedItemPacket5Playerinventory.slot, setEquippedItemPacket5Playerinventory.itemID, setEquippedItemPacket5Playerinventory.itemMeta, setEquippedItemPacket5Playerinventory.itemData);
+            entity.setEquippedSlot(equippedItemPacket.slot, equippedItemPacket.itemID, equippedItemPacket.itemMeta, equippedItemPacket.itemData);
         }
     }
 
     @Override
-    public void handleCloseWindow(ContainerClosePacket containerClosewindow)
+    public void handleCloseWindow(ContainerClosePacket containerClosePacket)
     {
         mc.thePlayer.closeScreen();
     }
@@ -1055,8 +1053,6 @@ public class ClientPacketHandler extends PacketHandler
         mc.theWorld.triggerEvent(packet54PlaynoteblockEventPacket.xLocation, packet54PlaynoteblockEventPacket.yLocation, packet54PlaynoteblockEventPacket.zLocation, packet54PlaynoteblockEventPacket.instrumentType, packet54PlaynoteblockEventPacket.pitch);
     }
 
-    // TODO
-    // todo what?
     @Override
     public void handleBed(BedMessagePacket bedMessagePacket)
     {
@@ -1076,7 +1072,7 @@ public class ClientPacketHandler extends PacketHandler
         }
         else
         {
-            System.out.println((new StringBuilder()).append("Unknown itemid: ").append(mapdataPacket.meta).toString());
+            LOGGER.warn("Unexpected itemId: {}", mapdataPacket.itemId);
         }
     }
 
@@ -1157,8 +1153,8 @@ public class ClientPacketHandler extends PacketHandler
     }
     
     @Override
-    public void handleBlockItemSwitch(SetCarriedItemPacket packet16blockitemswitch) {
-        mc.thePlayer.inventory.currentItem = packet16blockitemswitch.id;
+    public void handleBlockItemSwitch(SetCarriedItemPacket setCarriedItemPacket) {
+        mc.thePlayer.inventory.currentItem = setCarriedItemPacket.id;
     }
 
     @Override
@@ -1193,18 +1189,18 @@ public class ClientPacketHandler extends PacketHandler
     @Override
     public void handleSyncedRecipe(RecipeSyncPacket recipeSyncPacket) {
         if(Registries.RECIPES.getAllSerializableRecipes().isEmpty()){
-            System.out.println("Receiving "+ recipeSyncPacket.maxRecipes+" recipes from server..");
+            LOGGER.info("Receiving {} recipes from server..", recipeSyncPacket.maxRecipes);
         }
         DataLoader.loadRecipeFromServer(recipeSyncPacket);
         if(Registries.RECIPES.getAllSerializableRecipes().size() == recipeSyncPacket.maxRecipes){
-            System.out.println("All recipes received!");
+            LOGGER.info("All recipes received!");
             Registries.RECIPES.invalidateCaches();
             SearchPage.searchField.setText("_");
             PageManager.searchQuery = SearchQuery.resolve(SearchPage.searchField.getText());
-            GuiGuidebook.getPageManager().updatePages();
+            GuidebookScreen.getPageManager().updatePages();
             SearchPage.searchField.setText("");
             PageManager.searchQuery = SearchQuery.resolve(SearchPage.searchField.getText());
-            GuiGuidebook.getPageManager().updatePages();
+            GuidebookScreen.getPageManager().updatePages();
         }
     }
     
@@ -1215,6 +1211,11 @@ public class ClientPacketHandler extends PacketHandler
     
     @Override
     public void handleCustomPayload(CustomPayloadPacket packet) {
-    	
+        if("BTA|RainbowStart".equals(packet.channel)) {
+//            System.out.printf("b0:%s b1:%s b2:%s b3:%s\n", packet.data[0], packet.data[1], packet.data[2], packet.data[3]);
+            int rainbowTicks = Byte.toUnsignedInt(packet.data[0]) << 24 | Byte.toUnsignedInt(packet.data[1]) << 16 | Byte.toUnsignedInt(packet.data[2]) << 8 | Byte.toUnsignedInt(packet.data[3]);
+//            System.out.println("Added rainbow with " + rainbowTicks + " ticks");
+            worldClient.addRainbow(rainbowTicks);
+        }
     }
 }
diff --git a/src/main/java/net/minecraft/client/net/handler/PingPacketHandler.java b/src/main/java/net/minecraft/client/net/handler/PingPacketHandler.java
index 218fccdc7..1ba52c28e 100644
--- a/src/main/java/net/minecraft/client/net/handler/PingPacketHandler.java
+++ b/src/main/java/net/minecraft/client/net/handler/PingPacketHandler.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.net.handler;
 
-import net.minecraft.client.gui.GuiSelectServer;
+import net.minecraft.client.gui.SelectServerScreen;
 import net.minecraft.core.net.NetworkManager;
 import net.minecraft.core.net.ServerAddress;
 import net.minecraft.core.net.ServerData;
@@ -16,14 +16,14 @@ public class PingPacketHandler
     extends PacketHandler
 {
     private boolean disconnected = false;
-    private final GuiSelectServer gui;
+    private final SelectServerScreen screen;
     private final NetworkManager netManager;
     private final ServerData server;
     public static long startTime = 0;
 
-    public PingPacketHandler(GuiSelectServer gui, ServerData server)
+    public PingPacketHandler(SelectServerScreen screen, ServerData server)
         throws IOException {
-        this.gui = gui;
+        this.screen = screen;
         this.server = server;
         ServerAddress address = server.getServerAddress();
         Socket socket = new Socket(InetAddress.getByName(address.getIP()), address.getPort());
@@ -64,7 +64,7 @@ public class PingPacketHandler
             server.maxPlayers = parseIntWithDefault(serverInfo[5], -1);
             server.latency = System.currentTimeMillis() - startTime;
 
-            gui.handleIncomingServerInfo(server);
+            screen.handleIncomingServerInfo(server);
 
             netManager.networkShutdown("disconnect.kicked", new Object[0]);
             disconnected = true;
diff --git a/src/main/java/net/minecraft/client/net/thread/ThreadDownloadImage.java b/src/main/java/net/minecraft/client/net/thread/ThreadDownloadImage.java
index 8a46b17cb..51546d8f0 100644
--- a/src/main/java/net/minecraft/client/net/thread/ThreadDownloadImage.java
+++ b/src/main/java/net/minecraft/client/net/thread/ThreadDownloadImage.java
@@ -1,7 +1,9 @@
 package net.minecraft.client.net.thread;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.render.texture.DownloadedTexture;
 import net.minecraft.client.render.ImageParser;
+import org.slf4j.Logger;
 
 import java.awt.image.BufferedImage;
 import java.io.InputStream;
@@ -11,7 +13,7 @@ import java.net.URL;
 import javax.imageio.ImageIO;
 
 public class ThreadDownloadImage extends Thread {
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static int counter = 0;
 	
 	public final String url;
@@ -49,7 +51,7 @@ public class ThreadDownloadImage extends Thread {
 
 			inputStream.close();
 		} catch (Exception exception) {
-			exception.printStackTrace();
+            LOGGER.error("Exception when getting image from '{}'!", url, exception);
 		} finally {
 			if(connection != null) connection.disconnect();
 		}
diff --git a/src/main/java/net/minecraft/client/net/thread/ThreadDownloadResources.java b/src/main/java/net/minecraft/client/net/thread/ThreadDownloadResources.java
index 8619de121..fd6f4601d 100644
--- a/src/main/java/net/minecraft/client/net/thread/ThreadDownloadResources.java
+++ b/src/main/java/net/minecraft/client/net/thread/ThreadDownloadResources.java
@@ -6,7 +6,6 @@ import static com.b100.utils.StreamUtils.*;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.net.URL;
 import java.nio.file.Files;
 import java.util.ArrayList;
@@ -20,10 +19,13 @@ import com.b100.xml.XmlFile;
 import com.b100.xml.XmlParser;
 import com.b100.xml.element.XmlContentTag;
 import com.b100.xml.element.XmlTag;
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
+import org.slf4j.Logger;
 
 public class ThreadDownloadResources extends Thread {
 
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static String[] extractFiles = new String[]{"ui/ui_back.ogg", "ui/ui_click.ogg", "ui/ui_focus.ogg", "ui/ui_scroll.ogg", "ui/crafting_fail.ogg", "ui/crafting_made.ogg"};
     public static String resourceDomain = "https://api.betterthanadventure.net/MinecraftResources/";
 
@@ -56,26 +58,24 @@ public class ThreadDownloadResources extends Thread {
             }
 
         } catch (Exception e) {
-            e.printStackTrace();
+            LOGGER.error("Exception when copying 'sound/ui/' files to resources!", e);
         }
 
         try {
             if (mc.gameSettings.downloadSoundfiles.value) {
-                System.out.println("Downloading sounds...");
+                LOGGER.info("Downloading sounds...");
                 try {
                     downloadResources();
                 } catch (Exception e) {
                     downloading = false;
-                    System.err.println("Error downloading sounds...");
-                    e.printStackTrace();
+                    LOGGER.error("Error downloading sounds...", e);
                 }
             }
         } catch (Exception e) {
-            e.printStackTrace();
+            LOGGER.error("Error downloading sounds", e);
         }
     }
 
-
     public void downloadResources() {
         String xmlString = StringUtils.getWebsiteContentAsString(resourceDomain);
 
@@ -148,15 +148,15 @@ public class ThreadDownloadResources extends Thread {
         String url = resourceDomain + name;
         url = url.replace(" ", "%20");
 
-        System.out.println("Downloading File: " + url);
+        LOGGER.info("Downloading File: {}", url);
 
         transferDataAndClose(new BufferedInputStream(new URL(url).openStream()), new BufferedOutputStream(Files.newOutputStream(createNewFile(file).toPath())));
     }
 
     private static class SoundEntry {
-        private File file;
-        private String name;
-        private long size;
+        private final File file;
+        private final String name;
+        private final long size;
 
         public SoundEntry(File file, String name, long size) {
             this.file = file;
diff --git a/src/main/java/net/minecraft/client/net/thread/ThreadPingServer.java b/src/main/java/net/minecraft/client/net/thread/ThreadPingServer.java
index ec1702841..7f28e0a8b 100644
--- a/src/main/java/net/minecraft/client/net/thread/ThreadPingServer.java
+++ b/src/main/java/net/minecraft/client/net/thread/ThreadPingServer.java
@@ -1,6 +1,6 @@
 package net.minecraft.client.net.thread;
 
-import net.minecraft.client.gui.GuiSelectServer;
+import net.minecraft.client.gui.SelectServerScreen;
 import net.minecraft.client.net.handler.PingPacketHandler;
 import net.minecraft.core.Global;
 import net.minecraft.core.net.ServerAddress;
@@ -11,13 +11,13 @@ import net.minecraft.core.net.packet.PingHandshakePacket;
 public class ThreadPingServer
     extends Thread {
 
-    private final GuiSelectServer gui;
+    private final SelectServerScreen screen;
     private final ServerData server;
     private boolean done = false;
     private PingPacketHandler netHandler = null;
 
-    public ThreadPingServer(GuiSelectServer gui, ServerData server) {
-        this.gui = gui;
+    public ThreadPingServer(SelectServerScreen screen, ServerData server) {
+        this.screen = screen;
         this.server = server;
         ServerAddress address = server.getServerAddress();
         this.setName("ThreadPingServer - " + address.getIP() + ":" + address.getPort());
@@ -46,7 +46,7 @@ public class ThreadPingServer
         int port = address.getPort();
 
         try {
-            netHandler = new PingPacketHandler(gui, server);
+            netHandler = new PingPacketHandler(screen, server);
             netHandler.addToSendQueue(new PingHandshakePacket(0x01, 0xFA, "BTAPingHost", Global.MP_PROTOCOL_VERSION, hostName, port));
         } catch (Exception ignored) {
         } finally {
diff --git a/src/main/java/net/minecraft/client/option/ColorOption.java b/src/main/java/net/minecraft/client/option/ColorOption.java
index dd4ea3d43..82c686dff 100644
--- a/src/main/java/net/minecraft/client/option/ColorOption.java
+++ b/src/main/java/net/minecraft/client/option/ColorOption.java
@@ -1,9 +1,11 @@
 package net.minecraft.client.option;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.util.helper.Color;
+import org.slf4j.Logger;
 
 public class ColorOption extends Option<Color>{
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public ColorOption(GameSettings gameSettings, String name, Color defaultValue) {
 		super(gameSettings, name, defaultValue);
 	}
@@ -13,7 +15,7 @@ public class ColorOption extends Option<Color>{
 		try{
 			this.value.parse(string);
 		}catch (Exception e) {
-			e.printStackTrace();
+            LOGGER.error("Failed to parse color for '{}'!", string, e);
 		}
 	}
 	
diff --git a/src/main/java/net/minecraft/client/option/GameSettings.java b/src/main/java/net/minecraft/client/option/GameSettings.java
index f1f8fafe9..8449cfe20 100644
--- a/src/main/java/net/minecraft/client/option/GameSettings.java
+++ b/src/main/java/net/minecraft/client/option/GameSettings.java
@@ -10,15 +10,16 @@ import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.mojang.logging.LogUtils;
+
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.discord.RichPresenceHandlerThread;
-import net.minecraft.client.gui.hud.HudComponents;
+import net.minecraft.client.gui.hud.component.HudComponents;
 import net.minecraft.client.input.InputDevice;
 import net.minecraft.client.option.enums.Colorblindness;
 import net.minecraft.client.option.enums.Difficulty;
 import net.minecraft.client.option.enums.LightmapStyle;
 import net.minecraft.client.option.enums.MipmapType;
-import net.minecraft.client.option.enums.RenderDistance;
 import net.minecraft.client.option.enums.RenderScale;
 import net.minecraft.client.option.enums.TooltipStyle;
 import net.minecraft.core.enums.PlacementMode;
@@ -26,13 +27,14 @@ import net.minecraft.core.lang.I18n;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.Color;
 import net.minecraft.core.util.helper.ITranslatable;
+import org.slf4j.Logger;
 
 public class GameSettings {
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static final String[] ANIMATIONS = { "options.animations.off", "options.animations.procedural", "options.animations.custom" };
 
 	public final Minecraft mc;
-	private File optionsFile;
+	private final File optionsFile;
 
 	public IntegerOption windowWidth = new IntegerOption(this, "windowWidth", 854);
 	public IntegerOption windowHeight = new IntegerOption(this, "windowHeight", 480);
@@ -163,6 +165,7 @@ public class GameSettings {
 	public BooleanOption aurora = new BooleanOption(this, "aurora", true);
 	public BooleanOption mobVariants = new BooleanOption(this, "mobVariants", true);
 	public EnumOption<Colorblindness> colorblindnessFix = new EnumOption<>(this, "colorblindnessFix", Colorblindness.class, Colorblindness.NONE);
+	public BooleanOption subtitles = new BooleanOption(this, "subtitles", false);
 
 	public KeyBinding keyAttack = new KeyBinding("key.attack").setDefault(InputDevice.mouse, 0);
 	public KeyBinding keyInteract = new KeyBinding("key.interact").setDefault(InputDevice.mouse, 1);
@@ -406,6 +409,7 @@ public class GameSettings {
 	}
 
 	public void optionChanged(Option<?> option) {
+		if (option == null) return;
 		if (option == difficulty) {
 			if (mc.theWorld != null) {
 				mc.theWorld.setDifficulty(difficulty.value, false);
@@ -417,13 +421,13 @@ public class GameSettings {
 		if(option == advancedOpenGL) mc.renderGlobal.loadRenderers();
 		if(option == biomeWater) {
 			mc.renderGlobal.loadRenderers();
-			mc.renderEngine.updateDynamicTextures(false);
+			mc.textureManager.updateDynamicTextures(false);
 		}
 		if(option == treeShadows) mc.renderGlobal.loadRenderers();
 		if(option == placementMode && mc.thePlayer != null) mc.thePlayer.syncPlacementMode();
 		if(option == animations || option == customAnimations) {
-			mc.renderEngine.refreshTexturesAndDisplayErrors();
-			mc.renderEngine.updateDynamicTextures(false);
+			mc.textureManager.refreshTexturesAndDisplayErrors();
+			mc.textureManager.updateDynamicTextures(false);
 		}
 		if(option == fullscreen) mc.gameWindow.updateWindowState();
 		if(option == borderlessFullscreen && fullscreen.value) mc.gameWindow.updateWindowState();
@@ -432,11 +436,11 @@ public class GameSettings {
 			guiScale.value = (guiScale.value + max) % max;
 			mc.resolution.update();
 			if (mc.currentScreen != null) {
-				mc.currentScreen.setWorldAndResolution(mc, mc.resolution.scaledWidth, mc.resolution.scaledHeight);
+				mc.currentScreen.init(mc, mc.resolution.scaledWidth, mc.resolution.scaledHeight);
 			}
 		}
 		if(option == mipmapType || option == mipmapLevels) {
-			mc.renderEngine.refreshTexturesAndDisplayErrors();
+			mc.textureManager.refreshTexturesAndDisplayErrors();
 		}
 		if(option == autosaveTimer) {
 			int max = 24;
@@ -452,7 +456,7 @@ public class GameSettings {
 		}
 		if(option == language) {
 			if (mc.currentScreen != null) {
-				mc.currentScreen.setWorldAndResolution(mc, mc.resolution.scaledWidth, mc.resolution.scaledHeight);
+				mc.currentScreen.init(mc, mc.resolution.scaledWidth, mc.resolution.scaledHeight);
 			}
 		}
 		if(option == lightmapStyle) {
@@ -499,14 +503,13 @@ line:		for (String line = ""; (line = br.readLine()) != null;) {
                         }
                     }
 				} catch (Exception e) {
-					System.out.println("Skipping bad option: "+line);
+                    LOGGER.warn("Skipping bad option: {}", line, e);
 				}
 			}
 
 			br.close();
 		} catch (Exception e) {
-			System.out.println("Failed to load options");
-			e.printStackTrace();
+			LOGGER.error("Failed to load options", e);
 		}
 	}
 	
@@ -529,8 +532,7 @@ line:		for (String line = ""; (line = br.readLine()) != null;) {
 
 			printwriter.close();
 		} catch (Exception exception) {
-			System.out.println("Failed to save options");
-			exception.printStackTrace();
+			LOGGER.error("Failed to save options", exception);
 		}
 	}
 
diff --git a/src/main/java/net/minecraft/client/player/controller/PlayerController.java b/src/main/java/net/minecraft/client/player/controller/PlayerController.java
index 80d9856b1..19be7b340 100644
--- a/src/main/java/net/minecraft/client/player/controller/PlayerController.java
+++ b/src/main/java/net/minecraft/client/player/controller/PlayerController.java
@@ -101,7 +101,7 @@ public abstract class PlayerController {
 					setMineBlock(x, y, z);
 				}
 				
-				mc.effectRenderer.addBlockHitEffects(x, y, z, side);
+				mc.particleEngine.crack(x, y, z, side);
 				playDigSound(mineBlock, x, y, z);
 				 
 				currentDamage += mineStrength;
@@ -200,11 +200,11 @@ public abstract class PlayerController {
 
 	public void render(float f) {
 		if (currentDamage <= 0.0F) {
-			mc.ingameGUI.damageGuiPartialTime = 0.0F;
+			mc.ingameHud.damageGuiPartialTime = 0.0F;
 			mc.renderGlobal.damagePartialTime = 0.0F;
 		} else {
 			float f1 = previousDamage + (currentDamage - previousDamage) * f;
-			mc.ingameGUI.damageGuiPartialTime = f1;
+			mc.ingameHud.damageGuiPartialTime = f1;
 			mc.renderGlobal.damagePartialTime = f1;
 		}
 	}
diff --git a/src/main/java/net/minecraft/client/render/BlockEntityRenderDispatcher.java b/src/main/java/net/minecraft/client/render/BlockEntityRenderDispatcher.java
index a9785542e..37963ef6e 100644
--- a/src/main/java/net/minecraft/client/render/BlockEntityRenderDispatcher.java
+++ b/src/main/java/net/minecraft/client/render/BlockEntityRenderDispatcher.java
@@ -60,15 +60,15 @@ public class BlockEntityRenderDispatcher
         return getRenderer(tileEntity) != null;
     }
 
-    public void cacheActiveRenderInfo(World world, RenderEngine renderEngine, FontRenderer fontRenderer, ICamera camera, float partialTick)
+    public void cacheActiveRenderInfo(World world, TextureManager textureManager, Font font, ICamera camera, float partialTick)
     {
         if(worldObj != world)
         {
             updateRendererWorldCache(world);
         }
-        this.renderEngine = renderEngine;
+        this.textureManager = textureManager;
         this.camera = camera;
-        this.fontRenderer = fontRenderer;
+        this.font = font;
         viewLerpYaw = (float) camera.getYRot(partialTick);
         viewLerpPitch = (float) camera.getXRot(partialTick);
         viewLerpPosX = (float) camera.getX(partialTick);
@@ -118,18 +118,18 @@ public class BlockEntityRenderDispatcher
         }
     }
 
-    public FontRenderer getFontRenderer()
+    public Font getFont()
     {
-        return fontRenderer;
+        return font;
     }
 
     private final Map<Class<?>, BlockEntityRenderer<?>> renderers;
     public static BlockEntityRenderDispatcher instance = new BlockEntityRenderDispatcher();
-    private FontRenderer fontRenderer;
+    private Font font;
     public static double renderPosX;
     public static double renderPosY;
     public static double renderPosZ;
-    public RenderEngine renderEngine;
+    public TextureManager textureManager;
     public World worldObj;
     public ICamera camera;
     public float viewLerpYaw;
diff --git a/src/main/java/net/minecraft/client/render/EffectRenderer.java b/src/main/java/net/minecraft/client/render/EffectRenderer.java
deleted file mode 100644
index d1b2c1e2c..000000000
--- a/src/main/java/net/minecraft/client/render/EffectRenderer.java
+++ /dev/null
@@ -1,214 +0,0 @@
-package net.minecraft.client.render;
-
-import java.util.*;
-
-import net.minecraft.client.render.camera.ICamera;
-import net.minecraft.client.entity.particle.TerrainParticle;
-import net.minecraft.client.entity.particle.Particle;
-import net.minecraft.client.render.texture.stitcher.TextureRegistry;
-import net.minecraft.client.render.tessellator.Tessellator;
-import net.minecraft.core.util.helper.MathHelper;
-import net.minecraft.core.util.helper.Side;
-import net.minecraft.core.world.World;
-import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
-import org.lwjgl.opengl.GL11;
-
-// Referenced classes of package net.minecraft.src:
-//            EntityFX, Entity, MathHelper, RenderEngine, 
-//            Tessellator, Block, EntityDiggingFX, World
-
-public class EffectRenderer
-{
-
-    public EffectRenderer(World world, RenderEngine renderengine)
-    {
-        fxLayers = new List[4];
-        rand = new Random();
-        if(world != null)
-        {
-            worldObj = world;
-        }
-        renderer = renderengine;
-        for(int i = 0; i < 4; i++)
-        {
-            fxLayers[i] = new ArrayList();
-        }
-
-    }
-
-    public void addEffect(Particle entityfx)
-    {
-        int i = entityfx.getParticleTexture();
-        if(fxLayers[i].size() >= 4000)
-        {
-            fxLayers[i].remove(0);
-        }
-        fxLayers[i].add(entityfx);
-    }
-
-    public void updateEffects()
-    {
-        for(int i = 0; i < 4; i++)
-        {
-            for(int j = 0; j < fxLayers[i].size(); j++)
-            {
-                Particle entityfx = (Particle)fxLayers[i].get(j);
-                entityfx.tick();
-                if(entityfx.removed)
-                {
-                    fxLayers[i].remove(j--);
-                }
-            }
-
-        }
-
-    }
-
-    public void renderParticles(ICamera camera, float partialTick)
-    {
-        double pitch = camera.getXRot(partialTick);
-        double yaw = camera.getYRot(partialTick);
-    	float rotationX = MathHelper.cos((float) (yaw * Math.PI) / 180F);
-        float rotationZ = MathHelper.sin((float) (yaw * Math.PI) / 180F);
-        float rotationYZ = -rotationZ * MathHelper.sin((float) ((pitch * Math.PI) / 180F));
-        float rotationXY = rotationX * MathHelper.sin((float) ((pitch * Math.PI) / 180F));
-        float rotationXZ = MathHelper.cos((float) ((pitch * Math.PI) / 180F));
-        Particle.xOff = camera.getX(partialTick);
-        Particle.yOff = camera.getY(partialTick);
-        Particle.zOff = camera.getZ(partialTick);
-
-        for(int i = 0; i < 3; i++)
-        {
-            if(fxLayers[i].size() == 0)
-            {
-                continue;
-            }
-            int texture = 0;
-            if(i == 0)
-            {
-                texture = TextureRegistry.particleAtlas.id();
-            }
-            if(i == 1)
-            {
-                texture = TextureRegistry.blockAtlas.id();
-            }
-            if(i == 2)
-            {
-                texture = TextureRegistry.itemAtlas.id();
-            }
-            GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
-            Tessellator tessellator = Tessellator.instance;
-            tessellator.startDrawingQuads();
-            for(int k = 0; k < fxLayers[i].size(); k++)
-            {
-                Particle entityfx = (Particle)fxLayers[i].get(k);
-                entityfx.render(tessellator, partialTick, rotationX, rotationXZ, rotationZ, rotationYZ, rotationXY);
-            }
-
-            tessellator.draw();
-        }
-    }
-
-    public void renderParticlesAtOrigin(float partialTick)
-    {
-        byte layerId = 3;
-        if(fxLayers[layerId].size() == 0)
-        {
-            return;
-        }
-        Tessellator tessellator = Tessellator.instance;
-        for(int i = 0; i < fxLayers[layerId].size(); i++)
-        {
-            Particle entityfx = (Particle)fxLayers[layerId].get(i);
-            entityfx.render(tessellator, partialTick, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F);
-        }
-
-    }
-
-    public void clearEffects(World world)
-    {
-        worldObj = world;
-        for(int i = 0; i < 4; i++)
-        {
-            fxLayers[i].clear();
-        }
-
-    }
-
-    public void addBlockDestroyEffects(int x, int y, int z, int blockId, int i1)
-    {
-        Block block = Block.blocksList[blockId];
-        if (block == null) return;
-        int amount = 4;
-        if(block == Blocks.FIRE)
-            return;
-        for(int _x = 0; _x < amount; _x++)
-        {
-            for(int _y = 0; _y < amount; _y++)
-            {
-                for(int _z = 0; _z < amount; _z++)
-                {
-                    double pX = (double)x + ((double)_x + 0.5D) / (double)amount;
-                    double pY = (double)y + ((double)_y + 0.5D) / (double)amount;
-                    double pZ = (double)z + ((double)_z + 0.5D) / (double)amount;
-                    int side = rand.nextInt(6);
-                    addEffect((new TerrainParticle(worldObj, pX, pY, pZ, pX - (double)x - 0.5D, pY - (double)y - 0.5D, pZ - (double)z - 0.5D, block, side, i1)).init(x, y, z));
-                }
-
-            }
-
-        }
-
-    }
-
-    public void addBlockHitEffects(int i, int j, int k, Side side)
-    {
-    	int l = side.getId();
-        int i1 = worldObj.getBlockId(i, j, k);
-        if(i1 == 0)
-        {
-            return;
-        }
-        Block block = Block.blocksList[i1];
-        float f = 0.1F;
-        double d = (double)i + rand.nextDouble() * (block.maxX - block.minX - (double)(f * 2.0F)) + (double)f + block.minX;
-        double d1 = (double)j + rand.nextDouble() * (block.maxY - block.minY - (double)(f * 2.0F)) + (double)f + block.minY;
-        double d2 = (double)k + rand.nextDouble() * (block.maxZ - block.minZ - (double)(f * 2.0F)) + (double)f + block.minZ;
-        if(l == 0)
-        {
-            d1 = ((double)j + block.minY) - (double)f;
-        }
-        if(l == 1)
-        {
-            d1 = (double)j + block.maxY + (double)f;
-        }
-        if(l == 2)
-        {
-            d2 = ((double)k + block.minZ) - (double)f;
-        }
-        if(l == 3)
-        {
-            d2 = (double)k + block.maxZ + (double)f;
-        }
-        if(l == 4)
-        {
-            d = ((double)i + block.minX) - (double)f;
-        }
-        if(l == 5)
-        {
-            d = (double)i + block.maxX + (double)f;
-        }
-        addEffect((new TerrainParticle(worldObj, d, d1, d2, 0.0D, 0.0D, 0.0D, block, l, worldObj.getBlockMetadata(i, j, k))).init(i, j, k).setPower(0.2F).setScale(0.6F));
-    }
-
-    public String getNumParticlesString()
-    {
-        return "" + (fxLayers[0].size() + fxLayers[1].size() + fxLayers[2].size());
-    }
-
-    protected World worldObj;
-    private List fxLayers[];
-    private RenderEngine renderer;
-    private Random rand;
-}
diff --git a/src/main/java/net/minecraft/client/render/EntityRenderDispatcher.java b/src/main/java/net/minecraft/client/render/EntityRenderDispatcher.java
index 5867617a9..8483bf786 100644
--- a/src/main/java/net/minecraft/client/render/EntityRenderDispatcher.java
+++ b/src/main/java/net/minecraft/client/render/EntityRenderDispatcher.java
@@ -154,12 +154,12 @@ public class EntityRenderDispatcher
         return getRenderer(entity.getClass());
     }
 
-    public void cacheActiveRenderInfo(World world, RenderEngine renderEngine, FontRenderer fontRenderer, ICamera camera, GameSettings gameSettings, float partialTick)
+    public void cacheActiveRenderInfo(World world, TextureManager textureManager, Font font, ICamera camera, GameSettings gameSettings, float partialTick)
     {
         this.world = world;
-        this.renderEngine = renderEngine;
+        this.textureManager = textureManager;
         this.gameSettings = gameSettings;
-        this.fontRenderer = fontRenderer;
+        this.font = font;
         this.camera = camera;
         viewLerpYaw = (float) camera.getYRot(partialTick);
         viewLerpPitch = (float) camera.getXRot(partialTick);
@@ -233,18 +233,18 @@ public class EntityRenderDispatcher
         return dx * dx + dy * dy + dz * dz;
     }
 
-    public FontRenderer getFontRenderer()
+    public Font getFont()
     {
-        return fontRenderer;
+        return font;
     }
 
     private final Map<Class<?>, EntityRenderer<?>> renderers;
     public static EntityRenderDispatcher instance = new EntityRenderDispatcher();
-    private FontRenderer fontRenderer;
+    private Font font;
     public static double renderPosX;
     public static double renderPosY;
     public static double renderPosZ;
-    public RenderEngine renderEngine;
+    public TextureManager textureManager;
     public ItemRenderer itemRenderer;
     public World world;
     public ICamera camera;
diff --git a/src/main/java/net/minecraft/client/render/FlagRenderer.java b/src/main/java/net/minecraft/client/render/FlagRenderer.java
index c4b09a2c3..543598f30 100644
--- a/src/main/java/net/minecraft/client/render/FlagRenderer.java
+++ b/src/main/java/net/minecraft/client/render/FlagRenderer.java
@@ -11,15 +11,15 @@ public class FlagRenderer {
     public final int CANVAS_WIDTH = 24;
     public final int CANVAS_HEIGHT = 16;
 
-    private final RenderEngine renderEngine;
+    private final TextureManager textureManager;
     
     private final int texture;
     
-    public FlagRenderer(RenderEngine renderEngine)
+    public FlagRenderer(TextureManager textureManager)
     {
-        this.renderEngine = renderEngine;
+        this.textureManager = textureManager;
         
-        texture = renderEngine.createTexture(CANVAS_WIDTH, CANVAS_HEIGHT);
+        texture = textureManager.createTexture(CANVAS_WIDTH, CANVAS_HEIGHT);
     }
 
     @Override
@@ -32,7 +32,7 @@ public class FlagRenderer {
     {
         byte[] flagColors = tileEntity.flagColors;
         int[] rgbFlagColors = flagDataToRGB(tileEntity, flagColors);
-        renderEngine.updateTextureData(rgbFlagColors, CANVAS_WIDTH, CANVAS_HEIGHT, texture);
+        textureManager.updateTextureData(rgbFlagColors, CANVAS_WIDTH, CANVAS_HEIGHT, texture);
     }
     
     public int getTexture()
diff --git a/src/main/java/net/minecraft/client/render/FogManager.java b/src/main/java/net/minecraft/client/render/FogManager.java
index 13cfe5885..bf0d56965 100644
--- a/src/main/java/net/minecraft/client/render/FogManager.java
+++ b/src/main/java/net/minecraft/client/render/FogManager.java
@@ -9,8 +9,8 @@ import org.lwjgl.opengl.NVFogDistance;
 
 import net.minecraft.client.GLAllocation;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiPhotoMode;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
+import net.minecraft.client.gui.PhotoModeScreen;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
 import net.minecraft.client.option.enums.RenderDistance;
 import net.minecraft.client.render.camera.CameraUtil;
 import net.minecraft.client.render.colorizer.Colorizers;
@@ -78,9 +78,9 @@ public class FogManager {
 
             if (fogDistance > maxFogDistance * fogModifier) fogDistance = maxFogDistance * fogModifier;
 
-            if (mc.currentScreen instanceof GuiPhotoMode)
+            if (mc.currentScreen instanceof PhotoModeScreen)
             {
-                fogDistance = farPlaneDistance * ((GuiPhotoMode)mc.currentScreen).getFog(partialTick);
+                fogDistance = farPlaneDistance * ((PhotoModeScreen)mc.currentScreen).getFog(partialTick);
             }
 
             glFogi(GL_FOG_MODE, GL_LINEAR);
@@ -170,8 +170,8 @@ public class FogManager {
         fogRed *= brightness;
         fogGreen *= brightness;
         fogBlue *= brightness;
-        if (mc.currentScreen instanceof GuiModelViewer) {
-            float[] color = ((GuiModelViewer) mc.currentScreen).getBackgroundFogColor();
+        if (mc.currentScreen instanceof ModelViewerScreen) {
+            float[] color = ((ModelViewerScreen) mc.currentScreen).getBackgroundFogColor();
             fogRed = color[0];
             fogGreen = color[1];
             fogBlue = color[2];
diff --git a/src/main/java/net/minecraft/client/render/FontRenderer.java b/src/main/java/net/minecraft/client/render/Font.java
similarity index 98%
rename from src/main/java/net/minecraft/client/render/FontRenderer.java
rename to src/main/java/net/minecraft/client/render/Font.java
index e1b89fbf9..9e8c28c82 100644
--- a/src/main/java/net/minecraft/client/render/FontRenderer.java
+++ b/src/main/java/net/minecraft/client/render/Font.java
@@ -21,7 +21,7 @@ import java.util.List;
 import java.util.Random;
 import java.util.regex.Pattern;
 
-public class FontRenderer {
+public class Font {
     private static final Pattern FORMATTING_CODE_REGEX = Pattern.compile("(?i)\\u00A7[0-9A-FK-OR]");
 
     private final GameSettings gameSettings;
@@ -35,7 +35,7 @@ public class FontRenderer {
     private final int[] glyphTextureNames;
     private final int[] colorCode;
     private int boundTextureName;
-    private final RenderEngine renderEngine;
+    private final TextureManager textureManager;
     private float posX;
     private float posY;
     private boolean bidiFlag;
@@ -50,7 +50,7 @@ public class FontRenderer {
     private boolean underlineStyle;
     private boolean strikethroughStyle;
 
-    public FontRenderer(Minecraft minecraft, GameSettings gameSettings, String fontPath, RenderEngine renderEngine) {
+    public Font(Minecraft minecraft, GameSettings gameSettings, TextureManager textureManager) {
         this.mc = minecraft;
         this.gameSettings = gameSettings;
         this.charWidth = new byte[65536];
@@ -66,7 +66,7 @@ public class FontRenderer {
         this.italicStyle = false;
         this.underlineStyle = false;
         this.strikethroughStyle = false;
-        this.renderEngine = renderEngine;
+        this.textureManager = textureManager;
 
         try (InputStream glyphStream = mc.texturePackList.getResourceAsStream("/font/glyph_sizes.bin");
              InputStream glyphStreamDefault = mc.texturePackList.getResourceAsStream("/font/glyph_sizes_default.bin")) {
@@ -120,9 +120,9 @@ public class FontRenderer {
         String fontPath = String.format("/font/font_%02X.png", id);
         String glyphPath = String.format("/font/glyph_%02X.png", id);
 
-        Texture fontTexture = this.renderEngine.loadTextureNoDefault(fontPath);
+        Texture fontTexture = this.textureManager.loadTextureNoDefault(fontPath);
         if (fontTexture == null) {
-            fontTexture = this.renderEngine.loadTextureNoDefault(glyphPath);
+            fontTexture = this.textureManager.loadTextureNoDefault(glyphPath);
         }
         if (fontTexture == null) {
             throw new RuntimeException("Failed to load texture from '" + fontPath + "' or '" + glyphPath + "'!");
@@ -187,7 +187,7 @@ public class FontRenderer {
             throw new RuntimeException(var5);
         }
 
-        this.glyphTextureNames[id] = this.renderEngine.loadBufferedTexture(glyphTexture).id();
+        this.glyphTextureNames[id] = this.textureManager.loadBufferedTexture(glyphTexture).id();
         this.boundTextureName = this.glyphTextureNames[id];
     }
 
diff --git a/src/main/java/net/minecraft/client/render/ItemRenderer.java b/src/main/java/net/minecraft/client/render/ItemRenderer.java
index 931d744ea..bd88d605e 100644
--- a/src/main/java/net/minecraft/client/render/ItemRenderer.java
+++ b/src/main/java/net/minecraft/client/render/ItemRenderer.java
@@ -101,7 +101,7 @@ public class ItemRenderer
             f18 = MathHelper.sin(MathHelper.sqrt_float(swingProgress) * MathHelper.PI);
             GL11.glRotatef(f18 * 70F, 0.0F, 1.0F, 0.0F);
             GL11.glRotatef(-f14 * 20F, 0.0F, 0.0F, 1.0F);
-            mc.renderEngine.bindDownloadableTexture(mc.thePlayer.skinURL, mc.thePlayer.getEntityTexture(), PlayerSkinParser.instance);
+            mc.textureManager.bindDownloadableTexture(mc.thePlayer.skinURL, mc.thePlayer.getEntityTexture(), PlayerSkinParser.instance);
             GL11.glTranslatef(-1F, 3.6F, 3.5F);
             GL11.glRotatef(120F, 0.0F, 0.0F, 1.0F);
             GL11.glRotatef(200F, 1.0F, 0.0F, 0.0F);
@@ -164,7 +164,7 @@ public class ItemRenderer
 
 		}
 		if(mc.thePlayer.isUnderLiquid(Material.water)) {
-            mc.renderEngine.loadTexture("/assets/minecraft/textures/misc/water.png").bind();
+            mc.textureManager.loadTexture("/assets/minecraft/textures/misc/water.png").bind();
 			renderWarpedTextureOverlay(partialTicks);
 		}
 		glEnable(GL_ALPHA_TEST);
diff --git a/src/main/java/net/minecraft/client/render/LightmapHelper.java b/src/main/java/net/minecraft/client/render/LightmapHelper.java
index 17b446b2b..55fc7dcf6 100644
--- a/src/main/java/net/minecraft/client/render/LightmapHelper.java
+++ b/src/main/java/net/minecraft/client/render/LightmapHelper.java
@@ -5,17 +5,21 @@ import static org.lwjgl.opengl.GL13.*;
 
 import java.awt.image.BufferedImage;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.GLAllocation;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiPhotoMode;
+import net.minecraft.client.gui.PhotoModeScreen;
 import net.minecraft.client.option.enums.LightmapStyle;
 import net.minecraft.client.util.helper.Textures;
 import net.minecraft.core.util.helper.Buffer;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 public class LightmapHelper {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static LightmapHelper instance = null;
 
 	public static boolean isLightmapEnabled() {
@@ -26,7 +30,7 @@ public class LightmapHelper {
 	public final WorldRenderer worldRenderer;
 
 	private int lightmapTexture = 0;
-	private int[] lightmapData = new int[256];
+	private final int[] lightmapData = new int[256];
 	public BufferedImage customLightmap;
 	
 	private float prevSkyDarken;
@@ -44,18 +48,18 @@ public class LightmapHelper {
 			int dimension = world.dimension.id;
 			
 			String path = "/assets/minecraft/textures/environment/lightmap" + dimension + ".png";
-			
-			System.out.println("Loading lightmap '" + path + "'");
-			customLightmap = mc.renderEngine.getImage(path);
+
+            LOGGER.info("Loading custom lightmap '{}'", path);
+			customLightmap = mc.textureManager.getImage(path);
 			
 			if(customLightmap == Textures.missingTexture) {
 				customLightmap = null;
 			}
 			
 			if(customLightmap != null) {
-				System.out.println("Loaded lightmap!");
+				LOGGER.info("Loaded custom lightmap!");
 			}else {
-				System.out.println("No lightmap!");
+				LOGGER.info("No custom lightmap found");
 			}
 		}else {
 			customLightmap = null;
@@ -91,9 +95,7 @@ public class LightmapHelper {
 		}
 
 		if(mc.fullbright) {
-			for(int i = 0; i < lightmapData.length; i++) {
-				lightmapData[i] = 0xFFFFFFFF;
-			}
+            Arrays.fill(lightmapData, 0xFFFFFFFF);
 		} else {
 			if(mc.gameSettings.customLightmap.value && customLightmap != null) {
 				generateCustomLightmap(world);
@@ -167,7 +169,7 @@ public class LightmapHelper {
 			
 			if(smooth) {
 				float skyDarken = prevSkyDarken + (skyDarkenSmooth - prevSkyDarken) * partialTicks;
-				if(mc.currentScreen instanceof GuiPhotoMode) {
+				if(mc.currentScreen instanceof PhotoModeScreen) {
 					skyDarken = world.skyDarken;
 				}
 				float modifiedSkylight = Math.max(0, skyLightLevel - skyDarken);
diff --git a/src/main/java/net/minecraft/client/render/LoadingScreenRenderer.java b/src/main/java/net/minecraft/client/render/LoadingScreenRenderer.java
index 879719c49..88b56cca5 100644
--- a/src/main/java/net/minecraft/client/render/LoadingScreenRenderer.java
+++ b/src/main/java/net/minecraft/client/render/LoadingScreenRenderer.java
@@ -171,7 +171,7 @@ public class LoadingScreenRenderer
         GL11.glLoadIdentity();
         GL11.glTranslatef(0.0F, 0.0F, -200F);
         Tessellator t = Tessellator.instance;
-        minecraft.renderEngine.loadTexture(backgroundPath).bind();
+        minecraft.textureManager.loadTexture(backgroundPath).bind();
         float f = 32F;
 
         // Draw background
@@ -207,11 +207,11 @@ public class LoadingScreenRenderer
         }
 
         // Draw title and stage
-        minecraft.fontRenderer.drawStringWithShadow(title, (width - minecraft.fontRenderer.getStringWidth(title)) / 2, height / 2 - 4 - 16, 0xffffff);
-        minecraft.fontRenderer.drawStringWithShadow(stage, (width - minecraft.fontRenderer.getStringWidth(stage)) / 2, (height / 2 - 4) + 8, 0xffffff);
+        minecraft.font.drawStringWithShadow(title, (width - minecraft.font.getStringWidth(title)) / 2, height / 2 - 4 - 16, 0xffffff);
+        minecraft.font.drawStringWithShadow(stage, (width - minecraft.font.getStringWidth(stage)) / 2, (height / 2 - 4) + 8, 0xffffff);
 
         // Draw tip
-        minecraft.fontRenderer.drawStringWithShadow(tip, (width - minecraft.fontRenderer.getStringWidth(tip)) / 2, (height / 2 - 4) + 32, 0xffffff);
+        minecraft.font.drawStringWithShadow(tip, (width - minecraft.font.getStringWidth(tip)) / 2, (height / 2 - 4) + 32, 0xffffff);
         
         minecraft.renderer.endRenderGame(1.0f);
         
diff --git a/src/main/java/net/minecraft/client/render/MapItemRenderer.java b/src/main/java/net/minecraft/client/render/MapItemRenderer.java
index 383e6fe05..1f14956ad 100644
--- a/src/main/java/net/minecraft/client/render/MapItemRenderer.java
+++ b/src/main/java/net/minecraft/client/render/MapItemRenderer.java
@@ -4,7 +4,6 @@ import java.awt.image.BufferedImage;
 import java.util.Iterator;
 
 import net.minecraft.client.render.texture.BufferedTexture;
-import net.minecraft.core.util.helper.MathHelper;
 
 import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.render.tessellator.Tessellator;
@@ -25,12 +24,12 @@ public class MapItemRenderer
     public static final int IMAGE_HEIGHT = 128;
     public static final int IMAGE_AREA = 128 * 128;
 
-    public MapItemRenderer(FontRenderer fontrenderer, GameSettings gamesettings, RenderEngine renderengine)
+    public MapItemRenderer(Font font, GameSettings gamesettings, TextureManager textureManager)
     {
         mapImageData = new int[IMAGE_AREA];
         gameSettings = gamesettings;
-        fontRenderer = fontrenderer;
-        mapTexture = renderengine.loadBufferedTexture(new BufferedImage(128, 128, 2));
+        this.font = font;
+        mapTexture = textureManager.loadBufferedTexture(new BufferedImage(128, 128, 2));
         for(int i = 0; i < IMAGE_AREA; i++)
         {
             mapImageData[i] = 0;
@@ -39,11 +38,11 @@ public class MapItemRenderer
     }
 
 
-    public void renderMap(RenderEngine renderengine, ItemMapSavedData mapdata, float brightness)
+    public void renderMap(TextureManager textureManager, ItemMapSavedData data, float brightness)
     {
         for(int i = 0; i < IMAGE_AREA; i++)
         {
-            int colorIndex = mapdata.colors[i];
+            int colorIndex = data.colors[i];
             //value is divided by 4 to get the map colour id
             if(colorIndex >> 2 == 0)
             {
@@ -75,7 +74,7 @@ public class MapItemRenderer
         }
 
 
-        renderengine.updateTextureData(mapImageData, 128, 128, mapTexture.id());
+        textureManager.updateTextureData(mapImageData, 128, 128, mapTexture.id());
         int j = 0;
         int k = 0;
         Tessellator tessellator = Tessellator.instance;
@@ -92,9 +91,9 @@ public class MapItemRenderer
         tessellator.draw();
         GL11.glEnable(GL11.GL_ALPHA_TEST);
         GL11.glDisable(GL11.GL_BLEND);
-        renderengine.bindTexture(renderengine.loadTexture("/assets/minecraft/textures/misc/mapicons.png"));
+        textureManager.bindTexture(textureManager.loadTexture("/assets/minecraft/textures/misc/mapicons.png"));
 
-        for(Iterator<MapWaypoint> iterator = mapdata.mapWaypoints.iterator(); iterator.hasNext(); GL11.glPopMatrix())
+        for(Iterator<MapWaypoint> iterator = data.mapWaypoints.iterator(); iterator.hasNext(); GL11.glPopMatrix())
         {
             MapWaypoint mapWaypoint = iterator.next();
             GL11.glPushMatrix();
@@ -115,8 +114,8 @@ public class MapItemRenderer
             tessellator.draw();
         }
         //renders map icons
-        renderengine.bindTexture(renderengine.loadTexture("/assets/minecraft/textures/misc/mapicons.png"));
-        for(Iterator<ItemMapSavedData.MapDecoration> iterator = mapdata.decorations.iterator(); iterator.hasNext(); GL11.glPopMatrix())
+        textureManager.bindTexture(textureManager.loadTexture("/assets/minecraft/textures/misc/mapicons.png"));
+        for(Iterator<ItemMapSavedData.MapDecoration> iterator = data.decorations.iterator(); iterator.hasNext(); GL11.glPopMatrix())
         {
             ItemMapSavedData.MapDecoration mapcoord = iterator.next();
             GL11.glPushMatrix();
@@ -142,9 +141,9 @@ public class MapItemRenderer
         }
         GL11.glPushMatrix();
 
-        renderengine.bindTexture(renderengine.loadTexture("/assets/minecraft/textures/misc/flagicon.png"));
+        textureManager.bindTexture(textureManager.loadTexture("/assets/minecraft/textures/misc/flagicon.png"));
         // begin drawing flag colors
-        for(Iterator<MapWaypoint> iterator = mapdata.mapWaypoints.iterator(); iterator.hasNext(); GL11.glPopMatrix()) {
+        for(Iterator<MapWaypoint> iterator = data.mapWaypoints.iterator(); iterator.hasNext(); GL11.glPopMatrix()) {
             MapWaypoint mapWaypoint = iterator.next();
             GL11.glPushMatrix();
             for (int y = 0; y < 3; y++) {
@@ -185,5 +184,5 @@ public class MapItemRenderer
     private final int[] mapImageData;
     private final BufferedTexture mapTexture;
     private final GameSettings gameSettings;
-    private FontRenderer fontRenderer;
+    private Font font;
 }
diff --git a/src/main/java/net/minecraft/client/render/OpenGLHelper.java b/src/main/java/net/minecraft/client/render/OpenGLHelper.java
index 6b545d69b..9450e1ac9 100644
--- a/src/main/java/net/minecraft/client/render/OpenGLHelper.java
+++ b/src/main/java/net/minecraft/client/render/OpenGLHelper.java
@@ -5,6 +5,7 @@ import static org.lwjgl.opengl.GL11.*;
 import java.util.HashSet;
 import java.util.Set;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.Global;
 import org.lwjgl.opengl.ARBFramebufferObject;
 import org.lwjgl.opengl.ContextCapabilities;
@@ -12,10 +13,11 @@ import org.lwjgl.opengl.GLContext;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.shader.Shaders;
+import org.slf4j.Logger;
 
 public class OpenGLHelper {
-	
-	private static Set<String> errors = new HashSet<>();
+	private static final Logger LOGGER = LogUtils.getLogger();
+	private static final Set<String> errors = new HashSet<>();
 	
 	public static boolean enableOcclusionCheck = false;
 	public static boolean enableSphericalFog = false;
@@ -23,15 +25,15 @@ public class OpenGLHelper {
 	public static boolean gl31 = false;
 	
     public static void testCapabilities(Minecraft minecraft) {
-        System.out.println(glGetString(GL_VERSION));
-        System.out.println(glGetString(GL_VENDOR));
-        System.out.println(glGetString(GL_RENDERER));
+        LOGGER.info(glGetString(GL_VERSION));
+        LOGGER.info(glGetString(GL_VENDOR));
+        LOGGER.info(glGetString(GL_RENDERER));
         
         ContextCapabilities capabilities = GLContext.getCapabilities();
 
-        System.out.println("GL_ARB_framebuffer_object: " + capabilities.GL_ARB_framebuffer_object);
-        System.out.println("GL_ARB_occlusion_query: " + capabilities.GL_ARB_occlusion_query);
-        System.out.println("GL_NV_fog_distance: " + capabilities.GL_NV_fog_distance);
+        LOGGER.info("GL_ARB_framebuffer_object: {}", capabilities.GL_ARB_framebuffer_object);
+        LOGGER.info("GL_ARB_occlusion_query: {}", capabilities.GL_ARB_occlusion_query);
+        LOGGER.info("GL_NV_fog_distance: {}", capabilities.GL_NV_fog_distance);
         
         enableOcclusionCheck = capabilities.GL_ARB_occlusion_query;
         enableSphericalFog = capabilities.GL_NV_fog_distance;
@@ -40,13 +42,13 @@ public class OpenGLHelper {
         
 		if(minecraft.gameSettings.disableShaders.value) {
 			Shaders.enableShaders = false;
-			System.out.println("Shaders disabled in options file!");
+			LOGGER.info("Shaders disabled in options file!");
 			return;
 		}
 		
 		Shaders.enableShaders = capabilities.GL_ARB_framebuffer_object && capabilities.OpenGL20;
-		
-		System.out.println("Enable Shaders: " + Shaders.enableShaders);
+
+        LOGGER.info("Enable Shaders: {}", Shaders.enableShaders);
     }
 	
 	public static void checkError(String info) {
@@ -61,8 +63,8 @@ public class OpenGLHelper {
 			if(!errors.contains(info)) {
 				errors.add(info);
 				String error = errorCode + " (" + getErrorDescription(errorCode) + "): " + info;
-	            System.out.println("########## GL ERROR ##########");
-				System.out.println("OpenGL Error "+error);
+	            LOGGER.error("########## GL ERROR ##########");
+                LOGGER.error("OpenGL Error {}", error);
 			}
 		}
 	}
diff --git a/src/main/java/net/minecraft/client/render/ParticleEngine.java b/src/main/java/net/minecraft/client/render/ParticleEngine.java
new file mode 100644
index 000000000..94ddc68ca
--- /dev/null
+++ b/src/main/java/net/minecraft/client/render/ParticleEngine.java
@@ -0,0 +1,210 @@
+package net.minecraft.client.render;
+
+import java.util.*;
+
+import net.minecraft.client.render.camera.ICamera;
+import net.minecraft.client.entity.particle.TerrainParticle;
+import net.minecraft.client.entity.particle.Particle;
+import net.minecraft.client.render.texture.stitcher.TextureRegistry;
+import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.core.util.helper.MathHelper;
+import net.minecraft.core.util.helper.Side;
+import net.minecraft.core.world.World;
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
+import org.lwjgl.opengl.GL11;
+
+/**
+ * Handles rendering and ticking of client-side particles.
+ */
+public final class ParticleEngine {
+    public static final int MISC_TEXTURE = 0;
+    public static final int TERRAIN_TEXTURE = 1;
+    public static final int ITEM_TEXTURE = 2;
+    public static final int ENTITY_PARTICLE_TEXTURE = 3;
+    public static final int TEXTURE_COUNT = 4;
+
+    private World world;
+    private final List<Particle>[] particles;
+    private final Random rand;
+
+    public ParticleEngine(World world) {
+        particles = new ArrayList[TEXTURE_COUNT];
+        rand = new Random();
+        if (world != null) {
+            this.world = world;
+        }
+        for (int i = 0; i < particles.length; i++) {
+            particles[i] = new ArrayList<>();
+        }
+    }
+
+    /**
+     * Adds a new particle to the engine.
+     * @param p The particle to add.
+     */
+    public void add(Particle p) {
+        int t = p.getParticleTexture();
+        if (particles[t].size() >= 4000) {
+            particles[t].remove(0);
+        }
+        particles[t].add(p);
+    }
+
+    /**
+     * Ticks all the particles in the engine.
+     */
+    public void tick() {
+        for (int tt = 0; tt < particles.length; tt++) {
+            for (int i = 0; i < particles[tt].size(); i++) {
+                Particle p = particles[tt].get(i);
+                p.tick();
+                if (p.removed) {
+                    particles[tt].remove(i--);
+                }
+            }
+        }
+    }
+
+    /**
+     * Renders all the particles in the engine.
+     * @param camera The camera relative to whose perspective the particles should be drawn.
+     * @param partialTick The time since the last tick.
+     */
+    public void renderParticles(ICamera camera, float partialTick) {
+        double yRot = camera.getYRot(partialTick);
+        double xRot = camera.getXRot(partialTick);
+        float xa = MathHelper.cos((float) (yRot * Math.PI) / 180F);
+        float za = MathHelper.sin((float) (yRot * Math.PI) / 180F);
+        float xa2 = -za * MathHelper.sin((float) ((xRot * Math.PI) / 180F));
+        float za2 = xa * MathHelper.sin((float) ((xRot * Math.PI) / 180F));
+        float ya = MathHelper.cos((float) ((xRot * Math.PI) / 180F));
+        double xOff = camera.getX(partialTick);
+        double yOff = camera.getY(partialTick);
+        double zOff = camera.getZ(partialTick);
+
+        for (int tt = 0; tt < 3; tt++) {
+            if (particles[tt].isEmpty()) {
+                continue;
+            }
+            int texture = 0;
+            if (tt == MISC_TEXTURE) {
+                texture = TextureRegistry.particleAtlas.id();
+            }
+            if (tt == TERRAIN_TEXTURE) {
+                texture = TextureRegistry.blockAtlas.id();
+            }
+            if (tt == ITEM_TEXTURE) {
+                texture = TextureRegistry.itemAtlas.id();
+            }
+            GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
+            Tessellator tessellator = Tessellator.instance;
+            tessellator.startDrawingQuads();
+            for (int i = 0; i < particles[tt].size(); i++) {
+                Particle p = particles[tt].get(i);
+                p.render(tessellator, partialTick, xOff, yOff, zOff, xa, ya, za, xa2, za2);
+            }
+
+            tessellator.draw();
+        }
+    }
+
+    /**
+     * Renders all the particles in the engine whose texture type is ENTITY_PARTICLE_TEXTURE.
+     * These particles are drawn using OpenGL normal-based lighting, unlike the other particles,
+     * as they are full 3D rather than billboarded sprites.
+     * @param camera The camera relative to whose perspective the particles should be drawn.
+     * @param partialTick The time since the last tick.
+     */
+    public void renderLitParticles(ICamera camera, float partialTick) {
+        int tt = ENTITY_PARTICLE_TEXTURE;
+        if (particles[tt].isEmpty()) {
+            return;
+        }
+        double xOff = camera.getX(partialTick);
+        double yOff = camera.getY(partialTick);
+        double zOff = camera.getZ(partialTick);
+        Tessellator tessellator = Tessellator.instance;
+        for (int i = 0; i < particles[tt].size(); i++) {
+            Particle p = particles[tt].get(i);
+            p.render(tessellator, partialTick, xOff, yOff, zOff, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F);
+        }
+
+    }
+
+    /**
+     * Sets the world used to contain any managed particles.
+     * @param world The world to use.
+     */
+    public void setWorld(World world) {
+        this.world = world;
+        for (int i = 0; i < TEXTURE_COUNT; i++) {
+            particles[i].clear();
+        }
+    }
+
+    /**
+     * Produces a burst of terrain particles at the location a block is destroyed.
+     * @param x The X coordinate of the destroyed block.
+     * @param y The Y coordinate of the destroyed block.
+     * @param z The Z coordinate of the destroyed block.
+     * @param id The ID of the destroyed block.
+     * @param data The metadata value of the destroyed block.
+     */
+    public void destroy(int x, int y, int z, int id, int data) {
+        Block block = Block.blocksList[id];
+        if (block == null) return;
+        int amount = 4;
+        if (block == Blocks.FIRE) {
+            return;
+        }
+        for (int xx = 0; xx < amount; xx++) {
+            for (int yy = 0; yy < amount; yy++) {
+                for (int zz = 0; zz < amount; zz++) {
+                    double xp = x + (xx + 0.5D) / amount;
+                    double yp = y + (yy + 0.5D) / amount;
+                    double zp = z + (zz + 0.5D) / amount;
+                    Side side = Side.getSideById(rand.nextInt(6));
+                    add((new TerrainParticle(world, xp, yp, zp, xp - x - 0.5D, yp - y - 0.5D, zp - z - 0.5D, block, side, data)).init(x, y, z));
+                }
+            }
+        }
+    }
+
+    /**
+     * Produces falling terrain particles along the side of a block.
+     * @param x The X coordinate of the block.
+     * @param y The Y coordinate of the block.
+     * @param z The Z coordinate of the block.
+     * @param side The side along which to produce particles.
+     */
+    public void crack(int x, int y, int z, Side side) {
+        int id = world.getBlockId(x, y, z);
+        if (id == 0) {
+            return;
+        }
+        Block block = Block.blocksList[id];
+        float r = 0.1F;
+        double xp = x + rand.nextDouble() * (block.maxX - block.minX - (r * 2.0F)) + r + block.minX;
+        double yp = y + rand.nextDouble() * (block.maxY - block.minY - (r * 2.0F)) + r + block.minY;
+        double zp = z + rand.nextDouble() * (block.maxZ - block.minZ - (r * 2.0F)) + r + block.minZ;
+        if (side == Side.BOTTOM) {
+            yp = (y + block.minY) - r;
+        } else if (side == Side.TOP) {
+            yp = (y + block.maxY) + r;
+        } else if (side == Side.NORTH) {
+            zp = (z + block.minZ) - r;
+        } else if (side == Side.SOUTH) {
+            zp = (z + block.maxZ) + r;
+        } else if (side == Side.WEST) {
+            xp = (x + block.minX) - r;
+        } else if (side == Side.EAST) {
+            xp = x + block.maxX + r;
+        }
+        add((new TerrainParticle(world, xp, yp, zp, 0.0D, 0.0D, 0.0D, block, side, world.getBlockMetadata(x, y, z))).init(x, y, z).setPower(0.2F).setScale(0.6F));
+    }
+
+    public int countParticles() {
+        return particles[MISC_TEXTURE].size() + particles[TERRAIN_TEXTURE].size() + particles[ITEM_TEXTURE].size();
+    }
+}
diff --git a/src/main/java/net/minecraft/client/render/RenderBlocks.java b/src/main/java/net/minecraft/client/render/RenderBlocks.java
index 7423d47e6..859cd1d46 100644
--- a/src/main/java/net/minecraft/client/render/RenderBlocks.java
+++ b/src/main/java/net/minecraft/client/render/RenderBlocks.java
@@ -983,7 +983,7 @@ public class RenderBlocks
         }
     }
 
-    public void renderBlockAsItem(Tessellator tessellator, BlockModel<Block> blockModel, Block block, float var2)
+    public void renderBlockAsItem(Tessellator tessellator, BlockModel<?> blockModel, Block block, float var2)
     {
         blockModel.setBlockBoundsForItemRender();
         GL11.glTranslatef(-0.5F, -0.5F, -0.5F);
diff --git a/src/main/java/net/minecraft/client/render/RenderGlobal.java b/src/main/java/net/minecraft/client/render/RenderGlobal.java
index 0f28d5b52..84728a943 100644
--- a/src/main/java/net/minecraft/client/render/RenderGlobal.java
+++ b/src/main/java/net/minecraft/client/render/RenderGlobal.java
@@ -4,8 +4,8 @@ import net.minecraft.client.GLAllocation;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.particle.Particle;
 import net.minecraft.client.entity.particle.ParticleDispatcher;
-import net.minecraft.client.gui.GuiPhotoMode;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
+import net.minecraft.client.gui.PhotoModeScreen;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
 import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.block.model.LeavesBlockModel;
@@ -37,11 +37,13 @@ import net.minecraft.core.world.AuroraProvider;
 import net.minecraft.core.world.LevelListener;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.season.Seasons;
+import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.weather.Weathers;
 import org.lwjgl.opengl.ARBOcclusionQuery;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL15;
 
+import java.awt.*;
 import java.nio.IntBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -77,7 +79,7 @@ public class RenderGlobal
     public static final int RENDER_CHUNK_SIZE = 16;
     public static final int RENDER_LIST_BASE_WIDTH = 48;
 
-    public RenderGlobal(Minecraft minecraft, RenderEngine renderengine)
+    public RenderGlobal(Minecraft minecraft, TextureManager textureManager)
     {
         tileEntities = new ArrayList<>();
         chunkRenderersToUpdate = new ArrayList<>();
@@ -94,7 +96,7 @@ public class RenderGlobal
         prevSortZ = -9999D;
         frustumCheckOffset = 0;
         mc = minecraft;
-        renderEngine = renderengine;
+        this.textureManager = textureManager;
         glRenderListBase = GLAllocation.generateDisplayLists(RENDER_LIST_BASE_WIDTH * RENDER_LIST_BASE_WIDTH * RENDER_LIST_BASE_WIDTH * 3);
         occlusionEnabled = OpenGLHelper.enableOcclusionCheck;
         if(occlusionEnabled)
@@ -348,7 +350,7 @@ public class RenderGlobal
         double rotationX = Math.cos(((cameraYaw * Math.PI) / 180D));
         double rotationZ = Math.sin(((cameraYaw * Math.PI) / 180D));
 
-        renderEngine.bindTexture(renderEngine.loadTexture("/assets/minecraft/textures/environment/aurora.png"));
+        textureManager.bindTexture(textureManager.loadTexture("/assets/minecraft/textures/environment/aurora.png"));
         double time = worldObj.getWorldTime() + partialTick;
         AuroraProvider aurora = worldObj.auroraProvider;
 
@@ -410,8 +412,8 @@ public class RenderGlobal
             renderEntitiesStartupCounter--;
             return;
         }
-        BlockEntityRenderDispatcher.instance.cacheActiveRenderInfo(worldObj, renderEngine, mc.fontRenderer, camera, partialTick);
-        EntityRenderDispatcher.instance.cacheActiveRenderInfo(worldObj, renderEngine, mc.fontRenderer, camera, mc.gameSettings, partialTick);
+        BlockEntityRenderDispatcher.instance.cacheActiveRenderInfo(worldObj, textureManager, mc.font, camera, partialTick);
+        EntityRenderDispatcher.instance.cacheActiveRenderInfo(worldObj, textureManager, mc.font, camera, mc.gameSettings, partialTick);
         countEntitiesTotal = 0;
         countEntitiesRendered = 0;
         countEntitiesHidden = 0;
@@ -817,7 +819,7 @@ public class RenderGlobal
 
     public void drawSky(float partialTick)
     {
-        if(!mc.theWorld.getWorldType().hasSky() || mc.currentScreen instanceof GuiModelViewer)
+        if(!mc.theWorld.getWorldType().hasSky() || mc.currentScreen instanceof ModelViewerScreen)
         {
             return;
         }
@@ -884,25 +886,98 @@ public class RenderGlobal
         GL11.glRotatef(celestialAngle * 360F, 0.0F, 0.0F, 1.0F);
 
         // Render sun
-        float f15 = 30F;
-        renderEngine.loadTexture("/terrain/sun.png").bind();
+        float size = 30F;
+        textureManager.loadTexture("/terrain/sun.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, sunAlpha);
         t.startDrawingQuads();
-        t.addVertexWithUV(-f15, 100D, -f15, 0.0D, 0.0D);
-        t.addVertexWithUV(f15, 100D, -f15, 1.0D, 0.0D);
-        t.addVertexWithUV(f15, 100D, f15, 1.0D, 1.0D);
-        t.addVertexWithUV(-f15, 100D, f15, 0.0D, 1.0D);
+        t.addVertexWithUV(-size, 100D, -size, 0.0D, 0.0D);
+        t.addVertexWithUV(size, 100D, -size, 1.0D, 0.0D);
+        t.addVertexWithUV(size, 100D, size, 1.0D, 1.0D);
+        t.addVertexWithUV(-size, 100D, size, 0.0D, 1.0D);
         t.draw();
 
+        // Render Rainbow
+        if (worldObj.rainbowTicks > 0 || (!Double.isNaN(rainbowBrightness) && rainbowBrightness > 0)){
+            // Calculates the progress through the rainbow, with peak brightness halfway through its lifespawn
+            final float halfRainbowLength = (worldObj.startingRainbowTicks/2f);
+            float rainbowTimeScalar = 1 - (Math.abs((worldObj.rainbowTicks + partialTick) - halfRainbowLength) / halfRainbowLength);
+
+            // Calculates the potential max rainbow brightness based on time of day
+            float timeScalar;
+            float angDeg = celestialAngle * 360;
+            if (angDeg >= 0 && angDeg < 180){
+                double angDiff = MathHelper.deltaAngle(angDeg, 80.0);
+                timeScalar = 1 - (float) (Math.sqrt(angDiff * angDiff) / 90f);
+            } else {
+                double angDiff = MathHelper.deltaAngle(angDeg, 280.0);
+                timeScalar = 1 - (float) (Math.sqrt(angDiff * angDiff) / 90f);
+            }
+
+            // Cutoff zeros out part of the range and then rescales it
+            final float cutoff = 2.25f;
+            timeScalar -= 1 - (1/cutoff);
+            if (timeScalar < 0) timeScalar = 0;
+            timeScalar *= cutoff;
+            timeScalar *= rainbowTimeScalar;
+
+            Weather[] blocked = worldObj.getBlockBiome(MathHelper.floor(mc.thePlayer.x), MathHelper.floor(mc.thePlayer.y), MathHelper.floor(mc.thePlayer.z)).blockedWeathers;
+            boolean isWeatherBlocked = false;
+            for (Weather w : blocked){
+                if (w.equals(worldObj.weatherManager.getLastWeather())) {
+                    isWeatherBlocked = true;
+                    break;
+                }
+            }
+
+            if (isWeatherBlocked){
+                targetRainbowBrightness = 0;
+            } else {
+                targetRainbowBrightness = timeScalar;
+            }
+
+            if (Double.isNaN(rainbowBrightness)) {
+                rainbowBrightness = targetRainbowBrightness;
+            }
+
+            double totalDelta = targetRainbowBrightness - rainbowBrightness;
+            rainbowBrightnessDelta = totalDelta / 100;
+            rainbowBrightness += rainbowBrightnessDelta * partialTick;
+
+            // Draws and colors ring textures to make the rainbow
+            textureManager.loadTexture("/terrain/rainbow.png").bind();
+            t.startDrawingQuads();
+            final int iterations = 10;
+            for (int i = 0; i < iterations; i++) {
+                size = 200F - i * 4;
+                int color = Color.HSBtoRGB(i/(float)iterations, 1, (float) (0.3f * rainbowBrightness));
+                float colR = ((color >> 16) & 0xFF)/255f;
+                float colG = ((color >>  8) & 0xFF)/255f;
+                float colB = ((color >>  0) & 0xFF)/255f;
+                float rainbowAlpha = (float) ((0.35f - (0.15f * Math.abs(i - iterations/2)/(iterations/2f))) * rainbowBrightness);
+                t.setColorRGBA_F(colR, colG, colB, rainbowAlpha);
+                t.addVertexWithUV(-size, -100D, size, 1.0D, 1.0D);
+                t.addVertexWithUV(size, -100D, size, 0.0D, 1.0D);
+                t.addVertexWithUV(size, -100D, -size, 0.0D, 0.0D);
+                t.addVertexWithUV(-size, -100D, -size, 1.0D, 0.0D);
+            }
+            t.draw();
+        } else {
+            rainbowBrightness = 0;
+            rainbowBrightnessDelta = 0;
+            targetRainbowBrightness = 0;
+        }
+
+
+
         // Render moon
-        f15 = 20F;
-        renderEngine.loadTexture("/terrain/moon.png").bind();
+        size = 20F;
+        textureManager.loadTexture("/terrain/moon.png").bind();
         GL11.glColor4f(1.0F, 1.0F, 1.0F, sunAlpha);
         t.startDrawingQuads();
-        t.addVertexWithUV(-f15, -100D, f15, 1.0D, 1.0D);
-        t.addVertexWithUV(f15, -100D, f15, 0.0D, 1.0D);
-        t.addVertexWithUV(f15, -100D, -f15, 0.0D, 0.0D);
-        t.addVertexWithUV(-f15, -100D, -f15, 1.0D, 0.0D);
+        t.addVertexWithUV(-size, -100D, size, 1.0D, 1.0D);
+        t.addVertexWithUV(size, -100D, size, 0.0D, 1.0D);
+        t.addVertexWithUV(size, -100D, -size, 0.0D, 0.0D);
+        t.addVertexWithUV(-size, -100D, -size, 1.0D, 0.0D);
         t.draw();
 
         GL11.glDisable(GL11.GL_TEXTURE_2D);
@@ -938,7 +1013,7 @@ public class RenderGlobal
         {
             return;
         }
-        if (mc.currentScreen instanceof GuiPhotoMode)
+        if (mc.currentScreen instanceof PhotoModeScreen)
         {
             return;
         }
@@ -952,7 +1027,7 @@ public class RenderGlobal
         byte cloudRadius = 32;
         int i = 256 / cloudRadius;
         Tessellator tessellator = Tessellator.instance;
-        renderEngine.loadTexture("/assets/minecraft/textures/environment/clouds.png").bind();
+        textureManager.loadTexture("/assets/minecraft/textures/environment/clouds.png").bind();
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
         Vec3 dimensionColor = worldObj.getDimensionColor(mc.activeCamera, partialTick);
@@ -975,10 +1050,10 @@ public class RenderGlobal
         {
             for(int cloudZ = -cloudRadius * i; cloudZ < cloudRadius * i; cloudZ += cloudRadius)
             {
-                tessellator.addVertexWithUV(cloudX + 0,           cloudHeight, cloudZ + cloudRadius, (float)(cloudX + 0)           * f6 + f10, (float)(cloudZ + cloudRadius) * f6 + f11);
+                tessellator.addVertexWithUV(cloudX,           cloudHeight, cloudZ + cloudRadius, (float)(cloudX)           * f6 + f10, (float)(cloudZ + cloudRadius) * f6 + f11);
                 tessellator.addVertexWithUV(cloudX + cloudRadius, cloudHeight, cloudZ + cloudRadius, (float)(cloudX + cloudRadius) * f6 + f10, (float)(cloudZ + cloudRadius) * f6 + f11);
-                tessellator.addVertexWithUV(cloudX + cloudRadius, cloudHeight, cloudZ + 0,           (float)(cloudX + cloudRadius) * f6 + f10, (float)(cloudZ + 0)           * f6 + f11);
-                tessellator.addVertexWithUV(cloudX + 0,           cloudHeight, cloudZ + 0,           (float)(cloudX + 0)           * f6 + f10, (float)(cloudZ + 0)           * f6 + f11);
+                tessellator.addVertexWithUV(cloudX + cloudRadius, cloudHeight, cloudZ,           (float)(cloudX + cloudRadius) * f6 + f10, (float)(cloudZ)           * f6 + f11);
+                tessellator.addVertexWithUV(cloudX,           cloudHeight, cloudZ,           (float)(cloudX)           * f6 + f10, (float)(cloudZ)           * f6 + f11);
             }
 
         }
@@ -1020,7 +1095,7 @@ public class RenderGlobal
         int j = MathHelper.floor(dz / 2048D);
         dx -= i * 2048;
         dz -= j * 2048;
-        renderEngine.loadTexture("/assets/minecraft/textures/environment/clouds.png").bind();
+        textureManager.loadTexture("/assets/minecraft/textures/environment/clouds.png").bind();
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
         float f13 = 1F / 256F;
@@ -1266,7 +1341,7 @@ public class RenderGlobal
 
     public void drawSelectionBox(ICamera camera, HitResult hitResult, float partialTick)
     {
-        if (mc.gameSettings.immersiveMode.drawOutline() && mc.gameSettings.blockOutlineWidth.value > 0.01f && !(mc.currentScreen instanceof GuiModelViewer))
+        if (mc.gameSettings.immersiveMode.drawOutline() && mc.gameSettings.blockOutlineWidth.value > 0.01f && !(mc.currentScreen instanceof ModelViewerScreen))
         {
             GL11.glEnable(GL11.GL_BLEND);
             GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
@@ -1475,10 +1550,10 @@ public class RenderGlobal
         Float[] points = volume.getBakedLineCoords();
         for (int i = 0; i < points.length; i += 3)
         {
-            float expand0 = ((points[i + 0] - 0.5f) * 2) * expand;
+            float expand0 = ((points[i] - 0.5f) * 2) * expand;
             float expand1 = ((points[i + 1] - 0.5f) * 2) * expand;
             float expand2 = ((points[i + 2] - 0.5f) * 2) * expand;
-            t.addVertex(points[i + 0] + xOffset + expand0, points[i + 1] + yOffset + expand1, points[i + 2] + zOffset + expand2);
+            t.addVertex(points[i] + xOffset + expand0, points[i + 1] + yOffset + expand1, points[i + 2] + zOffset + expand2);
         }
         t.draw();
     }
@@ -1555,9 +1630,9 @@ public class RenderGlobal
         if(soundPath != null)
         {
             if (author != null && !author.isEmpty()){
-                mc.ingameGUI.setRecordPlayingMessage(author + " - " + I18n.getInstance().translateKey(soundPath));
+                mc.ingameHud.setRecordPlayingMessage(author + " - " + I18n.getInstance().translateKey(soundPath));
             } else {
-                mc.ingameGUI.setRecordPlayingMessage(I18n.getInstance().translateKey(soundPath));
+                mc.ingameHud.setRecordPlayingMessage(I18n.getInstance().translateKey(soundPath));
             }
         }
         mc.sndManager.playMusic(soundPath, x, y, z, 1.0F, 1.0F);
@@ -1567,15 +1642,7 @@ public class RenderGlobal
 	public void playSound(Entity player, String soundPath, SoundCategory category, double x, double y, double z,
                           float volume, float pitch)
     {
-        float soundDistance = 16F;
-        if(volume > 1.0F)
-        {
-            soundDistance *= volume;
-        }
-        if(mc.activeCamera.distanceToSqr(x, y, z) < (double)(soundDistance * soundDistance))
-        {
-            mc.sndManager.playSoundAt(soundPath, category, (float)x, (float)y, (float)z, volume, pitch);
-        }
+        mc.sndManager.playSoundAt(soundPath, category, (float)x, (float)y, (float)z, volume, pitch);
     }
     
     @Override
@@ -1588,7 +1655,7 @@ public class RenderGlobal
 	public void addParticle(String particleId, double x, double y, double z,
                             double motionX, double motionY, double motionZ, int data, double maxDistance)
     {
-        if(mc == null || mc.activeCamera == null || mc.effectRenderer == null) {
+        if(mc == null || mc.activeCamera == null || mc.particleEngine == null) {
             return;
         }
         double d6 = mc.activeCamera.getX() - x;
@@ -1600,7 +1667,7 @@ public class RenderGlobal
         }
         Particle fx = ParticleDispatcher.getInstance().getDispatch(particleId).newParticle(worldObj, x, y, z, motionX, motionY, motionZ, data);
         if (fx != null){
-            mc.effectRenderer.addEffect(fx);
+            mc.particleEngine.add(fx);
         }
     }
     
@@ -1675,7 +1742,7 @@ public class RenderGlobal
 
                     worldObj.playBlockSoundEffect(null, (float)x + 0.5F, (float)y + 0.5F, (float)z + 0.5F, block, EnumBlockSoundEffectType.MINE);
                 }
-                mc.effectRenderer.addBlockDestroyEffects(x, y, z, data, worldObj.getBlockMetadata(x, y, z));
+                mc.particleEngine.destroy(x, y, z, data, worldObj.getBlockMetadata(x, y, z));
                 break;
 
             case EVENT_DOOR_SOUND: // Door sound
@@ -1717,7 +1784,7 @@ public class RenderGlobal
 
     public List<BlockEntity> tileEntities;
     private World worldObj;
-    private final RenderEngine renderEngine;
+    private final TextureManager textureManager;
     private final List<ChunkRenderer> chunkRenderersToUpdate;
     private ChunkRenderer[] sortedChunkRenderers;
     private ChunkRenderer[] chunkRenderers;
@@ -1725,7 +1792,7 @@ public class RenderGlobal
     private int renderChunksTall;
     private int renderChunksDeep;
     private int glRenderListBase;
-    private Minecraft mc;
+    private final Minecraft mc;
     private RenderBlocks globalRenderBlocks;
     private IntBuffer glOcclusionQueryBase;
     private boolean occlusionEnabled;
@@ -1736,8 +1803,8 @@ public class RenderGlobal
     private float cloudVelocityX;
     private float cloudVelocityZ;
     
-    private int starGLCallList;
-    private int glSkyList;
+    private final int starGLCallList;
+    private final int glSkyList;
     private int minBlockX;
     private int minBlockY;
     private int minBlockZ;
@@ -1749,7 +1816,7 @@ public class RenderGlobal
     private int countEntitiesTotal;
     private int countEntitiesRendered;
     private int countEntitiesHidden;
-    int dummyBuf50k[];
+    int[] dummyBuf50k;
     IntBuffer occlusionResult;
     private int renderersLoaded;
     private int renderersBeingClipped;
@@ -1772,4 +1839,8 @@ public class RenderGlobal
     private double auroraBrightness = 0.0f;
     private double targetAuroraBrightness = Double.NaN;
     private double auroraBrightnessDelta = Double.NaN;
+
+    private double rainbowBrightness = 0.0f;
+    private double targetRainbowBrightness = Double.NaN;
+    private double rainbowBrightnessDelta = Double.NaN;
 }
diff --git a/src/main/java/net/minecraft/client/render/RenderEngine.java b/src/main/java/net/minecraft/client/render/TextureManager.java
similarity index 91%
rename from src/main/java/net/minecraft/client/render/RenderEngine.java
rename to src/main/java/net/minecraft/client/render/TextureManager.java
index 3de2fa842..6b60ab460 100644
--- a/src/main/java/net/minecraft/client/render/RenderEngine.java
+++ b/src/main/java/net/minecraft/client/render/TextureManager.java
@@ -13,9 +13,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.GLAllocation;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.popup.GuiPopup;
+import net.minecraft.client.gui.popup.PopupScreen;
 import net.minecraft.client.gui.popup.PopupBuilder;
 import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.render.colorizer.Colorizers;
@@ -51,9 +52,10 @@ import net.minecraft.core.util.helper.Buffer;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.opengl.GL11;
+import org.slf4j.Logger;
 
-public class RenderEngine {
-
+public class TextureManager {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public final Minecraft mc;
 
 	public final Map<Integer, Texture> idToTextureMap = new HashMap<>();
@@ -68,7 +70,7 @@ public class RenderEngine {
 	private boolean clampTexture;
 	private boolean blurTexture;
 
-	public RenderEngine(Minecraft minecraft, TexturePackList texturePacks, GameSettings gameSettings) {
+	public TextureManager(Minecraft minecraft, TexturePackList texturePacks, GameSettings gameSettings) {
 		this.mc = minecraft;
 		
 		this.clampTexture = false;
@@ -79,7 +81,7 @@ public class RenderEngine {
 	}
 	
 	public void initDynamicTextures(List<Throwable> errors) {
-		System.out.println("Initializing Dynamic Textures...");
+		LOGGER.info("Initializing Dynamic Textures...");
 
 		dynamicTextures.clear();
 
@@ -131,7 +133,7 @@ public class RenderEngine {
 		for (AtlasStitcher stitcher : TextureRegistry.stitcherMap.values()){
 			for (IconCoordinate c : stitcher.textureMap.values()) {
 				if (c.hasMeta("animation")) {
-					System.out.println("Icon '" + c.namespaceId + "' has 'animation' meta!");
+                    LOGGER.debug("Icon '{}' has 'animation' meta!", c.namespaceId);
 					addDynamicTextureOverride(new DynamicTextureCustom(c, c.getMeta("animation", AnimationProperties.class)), true);
 				}
 			}
@@ -161,7 +163,7 @@ public class RenderEngine {
 			idToTextureMap.put(texture.id(), texture);
 			return texture;
 		} catch (Exception e) {
-			e.printStackTrace();
+            LOGGER.error("Failed to create texture for '{}'!", name, e);
 		}
 		return null;
 	}
@@ -271,7 +273,7 @@ public class RenderEngine {
 					updateDynamicTexture(dynamicTexture);
 				}
 			} catch(Exception e){
-				new RuntimeException("Exception while updating dynamic for '" + dynamicTexture.targetTexture.namespaceId + "'. Removing from dynamic texture pool and skipping!", e).printStackTrace();
+                LOGGER.error("Exception while updating dynamic for '{}'. Removing from dynamic texture pool and skipping!", dynamicTexture.targetTexture.namespaceId, e);
 				dynamicTextures.remove(dynamicTexture.targetTexture.namespaceId); // Remove broken texture
 			}
 		}
@@ -292,7 +294,7 @@ public class RenderEngine {
     	
     	refreshTextures(errors);
     	
-        if(errors.size() > 0) {
+        if(!errors.isEmpty()) {
         	String string = createErrorString(errors);
         	
         	if(mc.currentScreen != null) {
@@ -302,36 +304,35 @@ public class RenderEngine {
                 builder.closeOnEsc(0);
                 builder.withMessageBox("what", mc.resolution.scaledHeight - 120, string, Integer.MAX_VALUE);
                 builder.withButtonGroup("ok", new String[] {"gui.options.button.done"}, new int[] {0});
-            	GuiPopup popup = builder.build();
+            	PopupScreen popup = builder.build();
             	
-            	mc.displayGuiScreen(popup);
+            	mc.displayScreen(popup);
         	}else {
         		String[] lines = string.split("\n");
-        		
-        		for(int i=0; i < lines.length; i++) {
-        			mc.ingameGUI.addChatMessage(lines[i]);	
-        		}
+
+                for (String line : lines) {
+                    mc.ingameHud.addChatMessage(line);
+                }
         	}
         }
 	}
 	
 	private String createErrorString(List<Throwable> errors) {
-		if(errors.size() == 0) {
+		if(errors.isEmpty()) {
 			return "";
 		}
 		
     	StringBuilder str = new StringBuilder();
     	
     	int readableErrorCount = 0;
-    	
-    	for(int i=0; i < errors.size(); i++) {
-    		Throwable e = errors.get(i);
-    		if(e instanceof TexturePackException) {
-    			addErrorText(str, e, 0);
-    			readableErrorCount++;
-    		}
-    		e.printStackTrace();
-    	}
+
+        for (Throwable e : errors) {
+            if (e instanceof TexturePackException) {
+                addErrorText(str, e, 0);
+                readableErrorCount++;
+            }
+			LOGGER.error("Unexpected Exception", e);
+        }
     	
     	if(readableErrorCount == 0) {
     		str.append("An unexpected error has occurred! Check the log for more information!");
@@ -345,7 +346,7 @@ public class RenderEngine {
 			str.append(' ');
 		}
 		
-		str.append(e.getMessage() + "\n");
+		str.append(e.getMessage()).append("\n");
 		
 		Throwable cause = e.getCause();
 		if(cause instanceof TexturePackException) {
@@ -365,7 +366,7 @@ public class RenderEngine {
 		for (AtlasStitcher stitcher : TextureRegistry.stitcherMap.values()){
 			stitcher.preinit();
 		}
-		System.out.println("Took '" + (System.nanoTime() - start)/1_000_000_000d + "' seconds to load atlases.");
+        LOGGER.debug("Took '{}' seconds to load atlases.", (System.nanoTime() - start) / 1_000_000_000d);
 
 		initDynamicTextures(errors);
 
@@ -386,7 +387,7 @@ public class RenderEngine {
 
 		Colors.loadColors();
 		
-		mc.fontRenderer = new FontRenderer(mc, gameSettings, "/font/default.png", this);
+		mc.font = new Font(mc, gameSettings, this);
 		
 		mc.skinVariantList.refresh(errors);
 		mc.mainMenuBackground.refresh(errors);
diff --git a/src/main/java/net/minecraft/client/render/WorldRenderer.java b/src/main/java/net/minecraft/client/render/WorldRenderer.java
index 4416e744b..bda14c8c8 100644
--- a/src/main/java/net/minecraft/client/render/WorldRenderer.java
+++ b/src/main/java/net/minecraft/client/render/WorldRenderer.java
@@ -5,6 +5,7 @@ import static org.lwjgl.opengl.GL11.*;
 import java.util.List;
 import java.util.Random;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.world.chunk.provider.ChunkProviderDynamic;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.util.phys.Vec3;
@@ -16,12 +17,11 @@ import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.particle.WaterDropParticle;
 import net.minecraft.client.entity.particle.SmokeParticle;
 import net.minecraft.client.entity.player.LocalPlayer;
-import net.minecraft.client.gui.GuiPhotoMode;
-import net.minecraft.client.gui.modelviewer.GuiModelViewer;
+import net.minecraft.client.gui.PhotoModeScreen;
+import net.minecraft.client.gui.modelviewer.ModelViewerScreen;
 import net.minecraft.client.input.InputType;
 import net.minecraft.client.input.MouseFilter;
 import net.minecraft.client.input.PlayerInput;
-import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.render.camera.CameraUtil;
 import net.minecraft.client.render.camera.EntityCamera;
 import net.minecraft.client.render.camera.EntityCameraFirstPerson;
@@ -47,9 +47,11 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.world.chunk.provider.IChunkProvider;
 import net.minecraft.core.world.weather.Weather;
+import org.slf4j.Logger;
 
 public class WorldRenderer
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static final long nsPerSecond = 1_000_000_000L;
     public final LightmapHelper lightmapHelper;
     public Minecraft mc;
@@ -58,12 +60,12 @@ public class WorldRenderer
     public FogManager fogManager;
     private int rendererUpdateCount;
     private Entity pointedEntity;
-    private MouseFilter mouseFilterXAxis;
-    private MouseFilter mouseFilterYAxis;
+    private final MouseFilter mouseFilterXAxis;
+    private final MouseFilter mouseFilterYAxis;
     private float fovModifier;
     private float fovModifierLast;
     private long systemTime;
-    private Random random;
+    private final Random random;
     private int rainSoundCounter;
     public boolean zooming = false;
     private float zoomProgress;
@@ -263,7 +265,7 @@ public class WorldRenderer
         if (mc.activeCamera instanceof EntityCamera)
         {
             Mob entityliving = ((EntityCamera) mc.activeCamera).mob;
-            if (mc.currentScreen instanceof GuiPhotoMode)
+            if (mc.currentScreen instanceof PhotoModeScreen)
             {
                 mc.activeCamera = new EntityCameraIsometric(mc, entityliving);
             }
@@ -298,16 +300,16 @@ public class WorldRenderer
         setupCamera(partialTick);
         mc.activeCamera.applyGlTransformations();
 
-        if(!(mc.currentScreen instanceof GuiPhotoMode) && !mc.gameSettings.lockCamera.value)
+        if(!(mc.currentScreen instanceof PhotoModeScreen) && !mc.gameSettings.lockCamera.value)
         {
             glRotatef((float) mc.activeCamera.getXRot(partialTick), 1.0F, 0.0F, 0.0F);
             glRotatef((float) (mc.activeCamera.getYRot(partialTick) + 180F), 0.0F, 1.0F, 0.0F);
         }
 
-        if (mc.currentScreen instanceof GuiPhotoMode)
+        if (mc.currentScreen instanceof PhotoModeScreen)
         {
-            glRotatef(((GuiPhotoMode)mc.currentScreen).getTilt(partialTick), 1.0F, 0.0F, 0.0F);
-            glRotatef(45f + 45F * ((GuiPhotoMode)mc.currentScreen).getRotation(partialTick), 0.0F, 1.0F, 0.0F);
+            glRotatef(((PhotoModeScreen)mc.currentScreen).getTilt(partialTick), 1.0F, 0.0F, 0.0F);
+            glRotatef(45f + 45F * ((PhotoModeScreen)mc.currentScreen).getRotation(partialTick), 0.0F, 1.0F, 0.0F);
         }
     }
 
@@ -322,12 +324,12 @@ public class WorldRenderer
         } else {
             zoomProgress = 0;
         }
-        if (mc.currentScreen instanceof GuiPhotoMode)
+        if (mc.currentScreen instanceof PhotoModeScreen)
         {
-            double div = java.lang.Math.pow(2, ((GuiPhotoMode)mc.currentScreen).getZoom(partialTick));
+            double div = java.lang.Math.pow(2, ((PhotoModeScreen)mc.currentScreen).getZoom(partialTick));
             glTranslatef(1, 1, 0);
             glOrtho(0, mc.resolution.width / div, 0, mc.resolution.height / div, farPlaneDistance * -2.0f, farPlaneDistance * 2.0f);
-            glTranslatef(((GuiPhotoMode)mc.currentScreen).getPanX(partialTick), -((GuiPhotoMode)mc.currentScreen).getPanY(partialTick), 0);
+            glTranslatef(((PhotoModeScreen)mc.currentScreen).getPanX(partialTick), -((PhotoModeScreen)mc.currentScreen).getPanY(partialTick), 0);
         } else
         {
             GLU.gluPerspective(fov, (float)mc.resolution.width / (float)mc.resolution.height, 0.05F, farPlaneDistance * 2.0F);
@@ -335,7 +337,7 @@ public class WorldRenderer
         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
         hurtCameraEffect(partialTick);
-        if(mc.gameSettings.viewBobbing.value && !(mc.currentScreen instanceof GuiPhotoMode))
+        if(mc.gameSettings.viewBobbing.value && !(mc.currentScreen instanceof PhotoModeScreen))
         {
             setupViewBobbing(partialTick);
         }
@@ -375,7 +377,7 @@ public class WorldRenderer
         {
             setupViewBobbing(partialTick);
         }
-        if(mc.gameSettings.thirdPersonView.value == 0 && !(mc.currentScreen instanceof GuiPhotoMode) && !(!(mc.activeCamera instanceof EntityCamera) || ((EntityCamera) mc.activeCamera).mob.isPlayerSleeping()) && mc.gameSettings.immersiveMode.drawHand())
+        if(mc.gameSettings.thirdPersonView.value == 0 && !(mc.currentScreen instanceof PhotoModeScreen) && !(!(mc.activeCamera instanceof EntityCamera) || ((EntityCamera) mc.activeCamera).mob.isPlayerSleeping()) && mc.gameSettings.immersiveMode.drawHand())
         {
             lightmapHelper.enableLightmapRendering();
             if(!zooming) itemRenderer.renderItemInFirstPerson(partialTick);
@@ -524,9 +526,9 @@ public class WorldRenderer
                     {
                         Thread.sleep(l1);
                     }
-                    catch(InterruptedException interruptedexception)
+                    catch(InterruptedException e)
                     {
-                        interruptedexception.printStackTrace();
+                        LOGGER.error("", e);
                     }
                 }
                 Debug.change("misc");
@@ -534,7 +536,7 @@ public class WorldRenderer
             systemTime = System.nanoTime();
             
             Debug.change("hud");
-            mc.ingameGUI.renderGameOverlay(partialTick, mc.currentScreen != null, mouseX, mouseY);
+            mc.ingameHud.renderGameOverlay(partialTick, mc.currentScreen != null, mouseX, mouseY);
             Debug.change("misc");
         } else
         {
@@ -557,9 +559,9 @@ public class WorldRenderer
                     {
                         Thread.sleep(l2);
                     }
-                    catch(InterruptedException interruptedexception1)
+                    catch(InterruptedException e)
                     {
-                        interruptedexception1.printStackTrace();
+                        LOGGER.error("", e);
                     }
                 }
                 Debug.change("misc");
@@ -574,7 +576,7 @@ public class WorldRenderer
                 mouseX = (int) mc.controllerInput.cursorX;
                 mouseY = (int) mc.controllerInput.cursorY;
             }
-            mc.currentScreen.drawScreen(mouseX, mouseY, partialTick);
+            mc.currentScreen.render(mouseX, mouseY, partialTick);
             if(mc.inputType == InputType.CONTROLLER && mc.currentScreen != null) {
                 mc.currentScreen.drawControllerCursor();
             }
@@ -588,7 +590,7 @@ public class WorldRenderer
         Colorizers.update(false);
         
         RenderGlobal renderGlobal = mc.renderGlobal;
-        EffectRenderer effectRenderer = mc.effectRenderer;
+        ParticleEngine particleEngine = mc.particleEngine;
         
         glEnable(GL_CULL_FACE);
         glEnable(GL_DEPTH_TEST);
@@ -626,7 +628,7 @@ public class WorldRenderer
         setupCameraTransform(partialTicks);
         Frustum.getFrustum();
         Debug.change("sky");
-        if((mc.gameSettings.renderDistance.value > 4) /* Used to use Renderdistance rendersky! */ && !(mc.currentScreen instanceof GuiModelViewer))
+        if((mc.gameSettings.renderDistance.value > 4) /* Used to use Renderdistance rendersky! */ && !(mc.currentScreen instanceof ModelViewerScreen))
         {
             fogManager.setupFog(FogManager.FOG_MODE_SKY, farPlaneDistance, partialTicks);
             glDisable(GL_FOG);
@@ -691,10 +693,10 @@ public class WorldRenderer
         }
         
         Debug.change("particles");
-        effectRenderer.renderParticlesAtOrigin(partialTicks);
+        particleEngine.renderLitParticles(mc.activeCamera, partialTicks);
         Lighting.disable();
         fogManager.setupFog(FogManager.FOG_MODE_NORMAL, farPlaneDistance, partialTicks);
-        effectRenderer.renderParticles(mc.activeCamera, partialTicks);
+        particleEngine.renderParticles(mc.activeCamera, partialTicks);
 
         lightmapHelper.disableLightmapRendering();
         
@@ -810,7 +812,7 @@ public class WorldRenderer
             }
             if(Block.blocksList[i2].blockMaterial == Material.lava)
             {
-                mc.effectRenderer.addEffect(new SmokeParticle(world, (float)randX + f1, (double)((float)y + 0.1F) - Block.blocksList[i2].minY, (float)randZ + f2, 0.0D, 0.0D, 0.0D));
+                mc.particleEngine.add(new SmokeParticle(world, (float)randX + f1, (double)((float)y + 0.1F) - Block.blocksList[i2].minY, (float)randZ + f2, 0.0D, 0.0D, 0.0D));
                 continue;
             }
             if(random.nextInt(++l) == 0)
@@ -819,7 +821,7 @@ public class WorldRenderer
                 d1 = (double)((float)y + 0.1F) - Block.blocksList[i2].minY;
                 d2 = (float)randZ + f2;
             }
-            mc.effectRenderer.addEffect(new WaterDropParticle(world, (float)randX + f1, (double)((float)y + 0.1F) - Block.blocksList[i2].minY, (float)randZ + f2));
+            mc.particleEngine.add(new WaterDropParticle(world, (float)randX + f1, (double)((float)y + 0.1F) - Block.blocksList[i2].minY, (float)randZ + f2));
         }
 
         if(l > 0 && random.nextInt(3) < rainSoundCounter++)
@@ -851,7 +853,7 @@ public class WorldRenderer
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         glAlphaFunc(516, 0.01F);
 
-        mc.renderEngine.loadTexture(weather.getPrecipitationTexture(world)).bind();
+        mc.textureManager.loadTexture(weather.getPrecipitationTexture(world)).bind();
         
         double nextPosX = mc.activeCamera.getX(partialTick);
         double nextPosY = mc.activeCamera.getY(partialTick);
@@ -922,9 +924,9 @@ public class WorldRenderer
                 blockedWeather:
                 for(int z = posZ - radiusEffect; z <= posZ + radiusEffect; z++) {
                     int y = world.findTopSolidBlock(x, z);
-                    Biome biomegenbase1 = world.getBlockBiome(x, y, z);
-                    for (int q = 0; q < biomegenbase1.blockedWeathers.length; q++) {
-                        if (biomegenbase1.blockedWeathers[q] == weather) {
+                    Biome biome = world.getBlockBiome(x, y, z);
+                    for (int q = 0; q < biome.blockedWeathers.length; q++) {
+                        if (biome.blockedWeathers[q] == weather) {
                             continue blockedWeather;
                         }
                     }
diff --git a/src/main/java/net/minecraft/client/render/block/model/BlockModel.java b/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
index d74eae690..02887fe03 100644
--- a/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
+++ b/src/main/java/net/minecraft/client/render/block/model/BlockModel.java
@@ -56,7 +56,7 @@ public abstract class BlockModel<T extends Block>
     public void resetRenderBlocks(){
         renderBlocks.renderAllFaces = false;
         renderBlocks.enableAO = false;
-        renderBlocks.overbright = false;
+//        renderBlocks.overbright = false;
         renderBlocks.useInventoryTint = true;
         renderBlocks.flipTexture = false;
         renderBlocks.overrideBlockTexture = null;
diff --git a/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java b/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
index cadad76b5..4cc8d5591 100644
--- a/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
+++ b/src/main/java/net/minecraft/client/render/block/model/BlockModelDispatcher.java
@@ -19,12 +19,12 @@ public class BlockModelDispatcher
         addDispatch(dispatchable.block, dispatchable);
     }
     @Override
-    public void addDispatch(Block item, BlockModel dispatchable)
+    public void addDispatch(Block key, BlockModel value)
     {
-        if (dispatches.containsValue(item)){
-            throw new IllegalArgumentException("Block '" + item.toString() + "' already assigned a model!");
+        if (dispatches.containsValue(key)){
+            throw new IllegalArgumentException("Block '" + key.toString() + "' already assigned a model!");
         }
-        dispatches.put(item, dispatchable);
+        dispatches.put(key, value);
     }
     @Override
     protected BlockModel getDefault()
diff --git a/src/main/java/net/minecraft/client/render/block/model/RepeaterBlockModel.java b/src/main/java/net/minecraft/client/render/block/model/RepeaterBlockModel.java
index 827541ee0..4defe0983 100644
--- a/src/main/java/net/minecraft/client/render/block/model/RepeaterBlockModel.java
+++ b/src/main/java/net/minecraft/client/render/block/model/RepeaterBlockModel.java
@@ -2,6 +2,7 @@ package net.minecraft.client.render.block.model;
 
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.tessellator.Tessellator;
+import net.minecraft.core.Global;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.RepeaterBlock;
@@ -52,9 +53,9 @@ public class RepeaterBlockModel extends StandardBlockModel<RepeaterBlock> {
         	tessellator.setLightmapCoord(lmc);
         }else {
     		brightness = getBlockBrightness(renderBlocks.blockAccess, x, y, z);
-    		if(Block.lightEmission[block.id] > 0) {
+    		if(Block.lightEmission[block.id] > 0 || Global.accessor.isFullbrightEnabled()) {
     			brightness = 1.0f;
-    		}	
+    		}
         }
         tessellator.setColorOpaque_F(brightness, brightness, brightness);
         double d = -0.1875D;
@@ -85,8 +86,13 @@ public class RepeaterBlockModel extends StandardBlockModel<RepeaterBlock> {
                 break;
         }
         TorchBlockModel<Block> modelTorch = block.isRepeaterPowered ? modelTorchActive : modelTorchIdle;
-        modelTorch.renderTorchAtAngle(tessellator, (double)x + d1, (double)y + d, (double)z + d2, 0.0D, 0.0D);
-        modelTorch.renderTorchAtAngle(tessellator, (double)x + d3, (double)y + d, (double)z + d4, 0.0D, 0.0D);
+        if (renderBlocks.overbright && block.isRepeaterPowered) {
+            modelTorch.renderTorchAtAngle(tessellator, (double)x + d1, (double)y + d, (double)z + d2, 0.0D, 0.0D);
+            modelTorch.renderTorchAtAngle(tessellator, (double)x + d3, (double)y + d, (double)z + d4, 0.0D, 0.0D);
+        } else if (!renderBlocks.overbright) {
+            modelTorch.renderTorchAtAngle(tessellator, (double)x + d1, (double)y + d, (double)z + d2, 0.0D, 0.0D);
+            modelTorch.renderTorchAtAngle(tessellator, (double)x + d3, (double)y + d, (double)z + d4, 0.0D, 0.0D);
+        }
         return true;
     }
     @Override
diff --git a/src/main/java/net/minecraft/client/render/blockentity/BlockEntityRenderer.java b/src/main/java/net/minecraft/client/render/blockentity/BlockEntityRenderer.java
index bd9dd308a..887f15cf6 100644
--- a/src/main/java/net/minecraft/client/render/blockentity/BlockEntityRenderer.java
+++ b/src/main/java/net/minecraft/client/render/blockentity/BlockEntityRenderer.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render.blockentity;
 
-import net.minecraft.client.render.FontRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.Font;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.BlockEntityRenderDispatcher;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.entity.BlockEntity;
@@ -19,8 +19,8 @@ public abstract class BlockEntityRenderer<T extends BlockEntity>
 
     protected void loadTexture(String texturePath)
     {
-        RenderEngine renderengine = renderDispatcher.renderEngine;
-        renderengine.bindTexture(renderengine.loadTexture(texturePath));
+        TextureManager textureManager = renderDispatcher.textureManager;
+        textureManager.bindTexture(textureManager.loadTexture(texturePath));
     }
 
     public void setRenderDispatcher(BlockEntityRenderDispatcher renderDispatcher)
@@ -32,9 +32,9 @@ public abstract class BlockEntityRenderer<T extends BlockEntity>
     {
     }
 
-    public FontRenderer getFontRenderer()
+    public Font getFont()
     {
-        return renderDispatcher.getFontRenderer();
+        return renderDispatcher.getFont();
     }
 
     protected BlockEntityRenderDispatcher renderDispatcher;
diff --git a/src/main/java/net/minecraft/client/render/blockentity/FlagBlockEntityRenderer.java b/src/main/java/net/minecraft/client/render/blockentity/FlagBlockEntityRenderer.java
index 824274de5..1183fc4b0 100644
--- a/src/main/java/net/minecraft/client/render/blockentity/FlagBlockEntityRenderer.java
+++ b/src/main/java/net/minecraft/client/render/blockentity/FlagBlockEntityRenderer.java
@@ -41,7 +41,7 @@ public class FlagBlockEntityRenderer extends BlockEntityRenderer<FlagBlockEntity
     {
         if (flagRenderer == null)
         {
-            flagRenderer = new FlagRenderer(renderDispatcher.renderEngine);
+            flagRenderer = new FlagRenderer(renderDispatcher.textureManager);
         }
         flagRenderer.updateTexture(tileEntity);
         
@@ -68,7 +68,7 @@ public class FlagBlockEntityRenderer extends BlockEntityRenderer<FlagBlockEntity
         GL11.glPushMatrix();
         GL11.glRotatef(windDirection + sway, 0.0f, 1.0f, 0.0f);
         flagModel.renderFlag();
-        renderDispatcher.renderEngine.bindTexture(flagRenderer.getTexture());
+        renderDispatcher.textureManager.bindTexture(flagRenderer.getTexture());
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_ONE_MINUS_SRC_COLOR, GL11.GL_SRC_COLOR);
         flagModel.renderFlagOverlay();
diff --git a/src/main/java/net/minecraft/client/render/blockentity/SignBlockEntityRenderer.java b/src/main/java/net/minecraft/client/render/blockentity/SignBlockEntityRenderer.java
index 417b93bf0..01785c6bc 100644
--- a/src/main/java/net/minecraft/client/render/blockentity/SignBlockEntityRenderer.java
+++ b/src/main/java/net/minecraft/client/render/blockentity/SignBlockEntityRenderer.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render.blockentity;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.LightmapHelper;
 import net.minecraft.client.render.model.SignModel;
 import net.minecraft.client.render.tessellator.Tessellator;
@@ -71,7 +71,7 @@ public class SignBlockEntityRenderer extends BlockEntityRenderer<SignBlockEntity
         GL11.glScalef(scale, -scale, -scale);
         signModel.func_887_a();
         GL11.glPopMatrix();
-        FontRenderer fontrenderer = getFontRenderer();
+        Font font = getFont();
 
         // Render overlay
         GL11.glPushMatrix();
@@ -114,7 +114,7 @@ public class SignBlockEntityRenderer extends BlockEntityRenderer<SignBlockEntity
             {
                 text = "> " + text + " <";
             }
-            fontrenderer.drawString(text, -fontrenderer.getStringWidth(text) / 2, line * 10 - tileEntity.signText.length * 5, color);
+            font.drawString(text, -font.getStringWidth(text) / 2, line * 10 - tileEntity.signText.length * 5, color);
         }
         GL11.glPopMatrix();
 
diff --git a/src/main/java/net/minecraft/client/render/camera/EntityCameraIsometric.java b/src/main/java/net/minecraft/client/render/camera/EntityCameraIsometric.java
index 59fb70b86..6eba0fcae 100644
--- a/src/main/java/net/minecraft/client/render/camera/EntityCameraIsometric.java
+++ b/src/main/java/net/minecraft/client/render/camera/EntityCameraIsometric.java
@@ -1,7 +1,7 @@
 package net.minecraft.client.render.camera;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiPhotoMode;
+import net.minecraft.client.gui.PhotoModeScreen;
 import net.minecraft.core.entity.Mob;
 
 public class EntityCameraIsometric
@@ -13,9 +13,9 @@ public class EntityCameraIsometric
 
     @Override
     public boolean showPlayer() {
-        if (mc.currentScreen instanceof GuiPhotoMode)
+        if (mc.currentScreen instanceof PhotoModeScreen)
         {
-            return ((GuiPhotoMode)mc.currentScreen).showPlayer;
+            return ((PhotoModeScreen)mc.currentScreen).showPlayer;
         }
 
         return true;
diff --git a/src/main/java/net/minecraft/client/render/colorizer/Colorizers.java b/src/main/java/net/minecraft/client/render/colorizer/Colorizers.java
index c5228dce4..b33ce4ee2 100644
--- a/src/main/java/net/minecraft/client/render/colorizer/Colorizers.java
+++ b/src/main/java/net/minecraft/client/render/colorizer/Colorizers.java
@@ -8,6 +8,7 @@ import java.util.List;
 
 import javax.imageio.ImageIO;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.texturepack.TexturePack;
 import net.minecraft.core.Global;
@@ -17,9 +18,10 @@ import net.minecraft.core.world.World;
 import net.minecraft.core.world.season.Season;
 import net.minecraft.core.world.season.SeasonManagerCycle;
 import net.minecraft.core.world.season.Seasons;
+import org.slf4j.Logger;
 
 public class Colorizers {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public static Minecraft mc;
 	
 	private static List<Colorizer> allColorizers = null;
@@ -58,7 +60,7 @@ public class Colorizers {
 			colorizer.setup(mc, seasons);
 			TexturePack texturePack = colorizer.getTexturePack();
 			if(texturePack != null) {
-				System.out.println("Using " + colorizer.name + " color from texture pack " + texturePack.fileName);	
+                LOGGER.info("Using {} color from texture pack {}", colorizer.name, texturePack.fileName);
 			}
 		}
 	}
@@ -117,7 +119,7 @@ public class Colorizers {
 		lastSeason = currentSeason;
 		lastSeasonProgress = seasonProgress;
 		
-		System.out.println("Updating Colorizers");
+		LOGGER.info("Updating Colorizers");
 		
 		Season season1, season2;
 		float blendFactor;
@@ -200,7 +202,9 @@ public class Colorizers {
 			throw new RuntimeException("Loading colormap: '" + path + "'", e);
 		}finally {
 			try {
-				in.close();
+				if (in != null) {
+					in.close();
+				}
 			}catch (Exception e) {}
 		}
 
diff --git a/src/main/java/net/minecraft/client/render/customatlas/CustomAtlasHandler.java b/src/main/java/net/minecraft/client/render/customatlas/CustomAtlasHandler.java
index b1f3c7740..8ba478553 100644
--- a/src/main/java/net/minecraft/client/render/customatlas/CustomAtlasHandler.java
+++ b/src/main/java/net/minecraft/client/render/customatlas/CustomAtlasHandler.java
@@ -10,14 +10,17 @@ import java.util.Map;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.texturepack.TexturePack;
 import net.minecraft.client.render.texturepack.TexturePackCustom;
 import net.minecraft.client.render.texturepack.TexturePackList;
 import net.minecraft.client.util.helper.Textures;
+import net.minecraft.core.Global;
+import org.slf4j.Logger;
 
 public class CustomAtlasHandler {
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static Atlas legacyTerrainAtlas = null;
 	private static Atlas legacyItemsAtlas = null;
 	
@@ -204,7 +207,7 @@ public class CustomAtlasHandler {
 	}
 	
 	public static void log(String str) {
-		System.out.println(str);
+		LOGGER.info(str);
 	}
 	
 	static interface Filter {
diff --git a/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java b/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java
index f473eab84..f16e4bb50 100644
--- a/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java
+++ b/src/main/java/net/minecraft/client/render/dynamictexture/DynamicTextureCustom.java
@@ -3,12 +3,14 @@ package net.minecraft.client.render.dynamictexture;
 import java.awt.image.BufferedImage;
 import java.util.Random;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.render.texture.meta.AnimationProperties;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texturepack.TexturePackException;
+import org.slf4j.Logger;
 
 public class DynamicTextureCustom extends DynamicTexture {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static final Random rand = new Random();
 	
 	private final int frameCount;
@@ -153,7 +155,7 @@ public class DynamicTextureCustom extends DynamicTexture {
 				}
 			}
 		} catch (Exception e) {
-			e.printStackTrace();
+            LOGGER.error("Exception while transferring frame '{}'!", frame, e);
 		}
 	}
 	
diff --git a/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java b/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java
index 01ee41827..b70f3f9a1 100644
--- a/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java
+++ b/src/main/java/net/minecraft/client/render/entity/EntityRenderer.java
@@ -3,10 +3,10 @@ package net.minecraft.client.render.entity;
 import org.lwjgl.opengl.GL11;
 
 import net.minecraft.client.render.EntityRenderDispatcher;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.ImageParser;
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
@@ -38,11 +38,11 @@ public abstract class EntityRenderer<T extends Entity>
 
     protected void bindTexture(String texturePath)
     {
-        RenderEngine renderEngine = renderDispatcher.renderEngine;
-        renderEngine.bindTexture(renderEngine.loadTexture(texturePath));
+        TextureManager textureManager = renderDispatcher.textureManager;
+        textureManager.bindTexture(textureManager.loadTexture(texturePath));
     }
     public boolean bindDownloadableTexture(String urlTexture, String backupTexture, ImageParser imageParser) {
-        return renderDispatcher.renderEngine.bindDownloadableTexture(urlTexture, backupTexture, imageParser);
+        return renderDispatcher.textureManager.bindDownloadableTexture(urlTexture, backupTexture, imageParser);
     }
     
     private void renderFire(Tessellator tessellator, T entity, double x, double y, double z, float partialTick)
@@ -101,8 +101,8 @@ public abstract class EntityRenderer<T extends Entity>
     {
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-        RenderEngine renderengine = renderDispatcher.renderEngine;
-        renderengine.bindTexture(renderengine.loadTexture("/assets/minecraft/textures/misc/shadow.png"));
+        TextureManager textureManager = renderDispatcher.textureManager;
+        textureManager.bindTexture(textureManager.loadTexture("/assets/minecraft/textures/misc/shadow.png"));
         World world = getWorld();
         GL11.glDepthMask(false);
         double lerpX = entity.xo + (entity.x - entity.xo) * (double)partialTick;
@@ -281,8 +281,8 @@ public abstract class EntityRenderer<T extends Entity>
         }
     }
 
-    public FontRenderer getFontRenderer()
+    public Font getFont()
     {
-        return renderDispatcher.getFontRenderer();
+        return renderDispatcher.getFont();
     }
 }
diff --git a/src/main/java/net/minecraft/client/render/entity/MobRenderer.java b/src/main/java/net/minecraft/client/render/entity/MobRenderer.java
index d817112cb..acfbdbb35 100644
--- a/src/main/java/net/minecraft/client/render/entity/MobRenderer.java
+++ b/src/main/java/net/minecraft/client/render/entity/MobRenderer.java
@@ -1,24 +1,21 @@
 package net.minecraft.client.render.entity;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.item.model.ItemModelDispatcher;
 import net.minecraft.client.render.model.BaseModel;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.Global;
 import net.minecraft.core.entity.Mob;
-import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL12;
-
-// Referenced classes of package net.minecraft.src:
-//            Render, BaseModel, Mob, MathHelper,
-//            RenderManager, Tessellator, FontRenderer, Entity
+import org.slf4j.Logger;
 
 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 BaseModel mainModel;
     protected BaseModel armorModel;
@@ -150,7 +147,7 @@ public class MobRenderer<T extends Mob> extends EntityRenderer<T>
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Render exception in class '{}'!", getClass().getSimpleName(), exception);
         }
         GL11.glEnable(GL11.GL_CULL_FACE);
         GL11.glPopMatrix();
@@ -229,7 +226,7 @@ public class MobRenderer<T extends Mob> extends EntityRenderer<T>
         {
             return;
         }
-        final FontRenderer fontrenderer = getFontRenderer();
+        final Font font = getFont();
         final float f1 = 1.6F;
         final float f2 = 0.01666667F * f1;
         GL11.glPushMatrix();
@@ -246,7 +243,7 @@ public class MobRenderer<T extends Mob> extends EntityRenderer<T>
         byte byte0 = 0;
         GL11.glDisable(3553 /* GL_TEXTURE_2D */);
         tessellator.startDrawingQuads();
-        final int j = fontrenderer.getStringWidth(s) / 2;
+        final int j = font.getStringWidth(s) / 2;
         tessellator.setColorRGBA_F(0.0F, 0.0F, 0.0F, 0.25F);
         tessellator.addVertex(-j - 1, -1 + byte0, 0.0D);
         tessellator.addVertex(-j - 1, 8 + byte0, 0.0D);
@@ -254,10 +251,10 @@ public class MobRenderer<T extends Mob> extends EntityRenderer<T>
         tessellator.addVertex(j + 1, -1 + byte0, 0.0D);
         tessellator.draw();
         GL11.glEnable(3553 /* GL_TEXTURE_2D */);
-        fontrenderer.drawString(s, -fontrenderer.getStringWidth(s) / 2, byte0, 0x20ffffff);
+        font.drawString(s, -font.getStringWidth(s) / 2, byte0, 0x20ffffff);
         if (!depthTest) GL11.glEnable(2929 /* GL_DEPTH_TEST */);
         GL11.glDepthMask(true);
-        fontrenderer.drawString(s, -fontrenderer.getStringWidth(s) / 2, byte0, 0xFFFFFF);
+        font.drawString(s, -font.getStringWidth(s) / 2, byte0, 0xFFFFFF);
         GL11.glEnable(2896 /* GL_LIGHTING */);
         GL11.glDisable(3042 /* GL_BLEND */);
         GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
diff --git a/src/main/java/net/minecraft/client/render/entity/PlayerRenderer.java b/src/main/java/net/minecraft/client/render/entity/PlayerRenderer.java
index 659b8a848..31d64760f 100644
--- a/src/main/java/net/minecraft/client/render/entity/PlayerRenderer.java
+++ b/src/main/java/net/minecraft/client/render/entity/PlayerRenderer.java
@@ -3,7 +3,7 @@ package net.minecraft.client.render.entity;
 import net.minecraft.client.Minecraft;
 
 import net.minecraft.client.entity.player.LocalPlayer;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.PlayerSkinParser;
 import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
@@ -155,7 +155,7 @@ public class PlayerRenderer extends MobRenderer<Player>
                     }
                 } else
                 {
-                    FontRenderer fontrenderer = getFontRenderer();
+                    Font font = getFont();
                     GL11.glPushMatrix();
                     GL11.glTranslatef((float)d + 0.0F, (float)d1 + 2.3F, (float)d2);
                     GL11.glNormal3f(0.0F, 1.0F, 0.0F);
@@ -169,7 +169,7 @@ public class PlayerRenderer extends MobRenderer<Player>
                     GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
                     GL11.glDisable(GL11.GL_TEXTURE_2D);
                     tessellator.startDrawingQuads();
-                    int i = fontrenderer.getStringWidth(s) / 2;
+                    int i = font.getStringWidth(s) / 2;
                     tessellator.setColorRGBA_F(0.0F, 0.0F, 0.0F, 0.25F);
                     tessellator.addVertex(-i - 1, -1D, 0.0D);
                     tessellator.addVertex(-i - 1, 8D, 0.0D);
@@ -178,7 +178,7 @@ public class PlayerRenderer extends MobRenderer<Player>
                     tessellator.draw();
                     GL11.glEnable(GL11.GL_TEXTURE_2D);
                     GL11.glDepthMask(true);
-                    fontrenderer.drawString(s, -fontrenderer.getStringWidth(s) / 2, 0, 0x20ffffff);
+                    font.drawString(s, -font.getStringWidth(s) / 2, 0, 0x20ffffff);
                     GL11.glEnable(GL11.GL_LIGHTING);
                     GL11.glDisable(GL11.GL_BLEND);
                     GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
diff --git a/src/main/java/net/minecraft/client/render/item/model/BlockItemModel.java b/src/main/java/net/minecraft/client/render/item/model/BlockItemModel.java
index 9f16c0e72..fdea38f0b 100644
--- a/src/main/java/net/minecraft/client/render/item/model/BlockItemModel.java
+++ b/src/main/java/net/minecraft/client/render/item/model/BlockItemModel.java
@@ -1,10 +1,10 @@
 package net.minecraft.client.render.item.model;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.ItemRenderer;
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.block.color.BlockColorDispatcher;
 import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
@@ -101,7 +101,7 @@ public class BlockItemModel extends StandardItemModel {
         }
     }
     @Override
-    public void renderItemIntoGui(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemStack, int x, int y, float brightness, float alpha) {
+    public void renderItemIntoGui(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemStack, int x, int y, float brightness, float alpha) {
         if (itemStack == null) return;
         GL11.glEnable(GL_BLEND);
         GL11.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -131,7 +131,7 @@ public class BlockItemModel extends StandardItemModel {
             BlockModel.renderBlocks.useInventoryTint = true;
             GL11.glPopMatrix();
         } else {
-            super.renderItemIntoGui(tessellator, fontrenderer, renderengine, itemStack, x, y, brightness, alpha);
+            super.renderItemIntoGui(tessellator, font, textureManager, itemStack, x, y, brightness, alpha);
         }
         GL11.glEnable(GL_CULL_FACE);
         GL11.glDisable(GL_BLEND);
diff --git a/src/main/java/net/minecraft/client/render/item/model/BowItemModel.java b/src/main/java/net/minecraft/client/render/item/model/BowItemModel.java
index 3ba604844..dda734c48 100644
--- a/src/main/java/net/minecraft/client/render/item/model/BowItemModel.java
+++ b/src/main/java/net/minecraft/client/render/item/model/BowItemModel.java
@@ -2,9 +2,9 @@ package net.minecraft.client.render.item.model;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.entity.player.RemotePlayer;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.ItemRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.Entity;
@@ -47,7 +47,7 @@ public class BowItemModel extends StandardItemModel {
         }
     }
     @Override
-    public void renderItemIntoGui(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemStack, int x, int y, float brightness, float alpha) {
+    public void renderItemIntoGui(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemStack, int x, int y, float brightness, float alpha) {
         Minecraft mc = Minecraft.getMinecraft(this);
         Item nextArrow = getNextArrow(mc.thePlayer);
         if (itemStack == mc.thePlayer.getHeldItem() && nextArrow != null){
@@ -72,7 +72,7 @@ public class BowItemModel extends StandardItemModel {
             glEnable(GL_CULL_FACE);
             glDisable(GL11.GL_BLEND);
         }
-        super.renderItemIntoGui(tessellator, fontrenderer, renderengine, itemStack, x, y, brightness, alpha);
+        super.renderItemIntoGui(tessellator, font, textureManager, itemStack, x, y, brightness, alpha);
     }
     public Item getNextArrow(Player player){
         if (player instanceof RemotePlayer){
diff --git a/src/main/java/net/minecraft/client/render/item/model/ItemModel.java b/src/main/java/net/minecraft/client/render/item/model/ItemModel.java
index 65013fe00..4bbbde18c 100644
--- a/src/main/java/net/minecraft/client/render/item/model/ItemModel.java
+++ b/src/main/java/net/minecraft/client/render/item/model/ItemModel.java
@@ -1,9 +1,9 @@
 package net.minecraft.client.render.item.model;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.ItemRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.Entity;
@@ -28,15 +28,15 @@ public abstract class ItemModel {
     }
     public abstract void renderItem(Tessellator tessellator, ItemRenderer renderer, ItemStack itemstack, @Nullable Entity entity, float brightness, boolean handheldTransform);
     public abstract void renderItemThirdPerson(Tessellator tessellator, ItemRenderer renderer, Entity entity, ItemStack itemstack, boolean handheldTransform);
-    public void renderItemIntoGui(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemstack, int x, int y, float alpha) {
-        renderItemIntoGui(tessellator, fontrenderer, renderengine, itemstack, x, y, 1.0f, alpha);
+    public void renderItemIntoGui(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemstack, int x, int y, float alpha) {
+        renderItemIntoGui(tessellator, font, textureManager, itemstack, x, y, 1.0f, alpha);
     }
-    public abstract void renderItemIntoGui(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemStack, int x, int y, float brightness, float alpha);
-    public void renderItemOverlayIntoGUI(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemstack, int x, int y, float alpha) {
-        renderItemOverlayIntoGUI(tessellator, fontrenderer, renderengine, itemstack, x, y, null, alpha);
+    public abstract void renderItemIntoGui(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemStack, int x, int y, float brightness, float alpha);
+    public void renderItemOverlayIntoGUI(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemstack, int x, int y, float alpha) {
+        renderItemOverlayIntoGUI(tessellator, font, textureManager, itemstack, x, y, null, alpha);
     }
 
-    public abstract void renderItemOverlayIntoGUI(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemstack, int x, int y, String override, float alpha);
+    public abstract void renderItemOverlayIntoGUI(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemstack, int x, int y, String override, float alpha);
     public abstract void renderAsItemEntity(Tessellator tessellator, @Nullable Entity entity, Random random, ItemStack itemstack, int renderCount, float yaw, float brightness, float partialTick);
     public abstract void renderItemInWorld(Tessellator tessellator, Entity entity, ItemStack itemStack, float brightness, float alpha, boolean worldTransform);
     public abstract IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack);
diff --git a/src/main/java/net/minecraft/client/render/item/model/ItemModelNone.java b/src/main/java/net/minecraft/client/render/item/model/ItemModelNone.java
index 47b371ccb..655d998ca 100644
--- a/src/main/java/net/minecraft/client/render/item/model/ItemModelNone.java
+++ b/src/main/java/net/minecraft/client/render/item/model/ItemModelNone.java
@@ -1,8 +1,8 @@
 package net.minecraft.client.render.item.model;
 
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.ItemRenderer;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.entity.Entity;
@@ -33,12 +33,12 @@ public class ItemModelNone extends ItemModel{
     }
 
     @Override
-    public void renderItemIntoGui(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemStack, int x, int y, float brightness, float alpha) {
+    public void renderItemIntoGui(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemStack, int x, int y, float brightness, float alpha) {
 
     }
 
     @Override
-    public void renderItemOverlayIntoGUI(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemstack, int x, int y, String override, float alpha) {
+    public void renderItemOverlayIntoGUI(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemstack, int x, int y, String override, float alpha) {
 
     }
 
diff --git a/src/main/java/net/minecraft/client/render/item/model/MapItemModel.java b/src/main/java/net/minecraft/client/render/item/model/MapItemModel.java
index b2b99f46b..85de3d540 100644
--- a/src/main/java/net/minecraft/client/render/item/model/MapItemModel.java
+++ b/src/main/java/net/minecraft/client/render/item/model/MapItemModel.java
@@ -26,7 +26,7 @@ import org.lwjgl.opengl.GL12;
 
 public class MapItemModel extends StandardItemModel {
     private final Minecraft mc = Minecraft.getMinecraft(Minecraft.class);
-    private final MapItemRenderer renderMapInstance = new MapItemRenderer(mc.fontRenderer, mc.gameSettings, mc.renderEngine);
+    private final MapItemRenderer renderMapInstance = new MapItemRenderer(mc.font, mc.gameSettings, mc.textureManager);
 
     public MapItemModel(Item item, String namespace) {
         super(item, namespace);
@@ -64,7 +64,7 @@ public class MapItemModel extends StandardItemModel {
         GL11.glEnable(GL12.GL_RESCALE_NORMAL);
 
         // Render both player arms
-        mc.renderEngine.bindDownloadableTexture(mc.thePlayer.skinURL, mc.thePlayer.getEntityTexture(), PlayerSkinParser.instance);
+        mc.textureManager.bindDownloadableTexture(mc.thePlayer.skinURL, mc.thePlayer.getEntityTexture(), PlayerSkinParser.instance);
         PlayerRenderer playerRenderer = (PlayerRenderer) (EntityRenderer<? extends Entity>) EntityRenderDispatcher.instance.getRenderer(mc.thePlayer);
 
         GL11.glPushMatrix();
@@ -102,7 +102,7 @@ public class MapItemModel extends StandardItemModel {
         GL11.glNormal3f(0.0F, 0.0F, -1F);
 
         // Render paper background of map
-        mc.renderEngine.bindTexture(mc.renderEngine.loadTexture("/assets/minecraft/textures/misc/mapbg.png"));
+        mc.textureManager.bindTexture(mc.textureManager.loadTexture("/assets/minecraft/textures/misc/mapbg.png"));
         tessellator.startDrawingQuads();
         final byte expansion = 7; // makes the edges extend around the actual map data by a bit
         tessellator.addVertexWithUV(-expansion,     128 + expansion, 0.0D, 0.0D, 1.0D);
@@ -113,7 +113,7 @@ public class MapItemModel extends StandardItemModel {
 
         ItemMapSavedData mapData = Items.MAP.getOrCreateSavedData(stack, mc.theWorld);
         if (mapData == null) return;
-        renderMapInstance.renderMap(mc.renderEngine, mapData, brightness);
+        renderMapInstance.renderMap(mc.textureManager, mapData, brightness);
     }
     @Override
     public @NotNull IconCoordinate getIcon(@Nullable Entity entity, ItemStack itemStack){
diff --git a/src/main/java/net/minecraft/client/render/item/model/StandardItemModel.java b/src/main/java/net/minecraft/client/render/item/model/StandardItemModel.java
index ff5bf5749..568cf2247 100644
--- a/src/main/java/net/minecraft/client/render/item/model/StandardItemModel.java
+++ b/src/main/java/net/minecraft/client/render/item/model/StandardItemModel.java
@@ -2,10 +2,10 @@ package net.minecraft.client.render.item.model;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.EntityRenderDispatcher;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.ItemRenderer;
 import net.minecraft.client.render.LightmapHelper;
-import net.minecraft.client.render.RenderEngine;
+import net.minecraft.client.render.TextureManager;
 import net.minecraft.client.render.texture.stitcher.IconCoordinate;
 import net.minecraft.client.render.texture.stitcher.TextureRegistry;
 import net.minecraft.client.render.tessellator.Tessellator;
@@ -133,7 +133,7 @@ public class StandardItemModel extends ItemModel{
     }
 
     @Override
-    public void renderItemIntoGui(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemStack, int x, int y, float brightness, float alpha) {
+    public void renderItemIntoGui(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemStack, int x, int y, float brightness, float alpha) {
         if (itemStack == null) return;
         Minecraft mc = Minecraft.getMinecraft(this);
         glEnable(GL_BLEND);
@@ -158,7 +158,7 @@ public class StandardItemModel extends ItemModel{
     }
 
     @Override
-    public void renderItemOverlayIntoGUI(Tessellator tessellator, FontRenderer fontrenderer, RenderEngine renderengine, ItemStack itemstack, int x, int y, String override, float alpha) {
+    public void renderItemOverlayIntoGUI(Tessellator tessellator, Font font, TextureManager textureManager, ItemStack itemstack, int x, int y, String override, float alpha) {
         glEnable(GL_BLEND);
         glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
         if (itemstack == null) {
@@ -169,7 +169,7 @@ public class StandardItemModel extends ItemModel{
             String s = override != null ? override : "" + itemstack.stackSize;
             GL11.glDisable(GL_LIGHTING);
             GL11.glDisable(GL_DEPTH_TEST);
-            fontrenderer.drawStringWithShadow(s, (x + 19) - 2 - fontrenderer.getStringWidth(s), y + 6 + 3, 0xffffff | (a << 24));
+            font.drawStringWithShadow(s, (x + 19) - 2 - font.getStringWidth(s), y + 6 + 3, 0xffffff | (a << 24));
             GL11.glEnable(GL_LIGHTING);
             GL11.glEnable(GL_DEPTH_TEST);
         }
diff --git a/src/main/java/net/minecraft/client/render/shader/PhotoModeRenderer.java b/src/main/java/net/minecraft/client/render/shader/PhotoModeRenderer.java
index 77e4786c5..0c5c34dde 100644
--- a/src/main/java/net/minecraft/client/render/shader/PhotoModeRenderer.java
+++ b/src/main/java/net/minecraft/client/render/shader/PhotoModeRenderer.java
@@ -1,20 +1,20 @@
 package net.minecraft.client.render.shader;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiPhotoMode;
+import net.minecraft.client.gui.PhotoModeScreen;
 
 public class PhotoModeRenderer extends ShadersRenderer {
 
 	public static final String[] shaders = new String[] { null, "blur", "silhouette", "vignette", "tiltshift", "outline", "outline2", "eerie", "sepia", "inverted", "distantblur" };
 
-	public final GuiPhotoMode guiPhotoMode;
+	public final PhotoModeScreen screen;
 
 	private int selectedShader = 0;
 
-	public PhotoModeRenderer(Minecraft minecraft, GuiPhotoMode guiPhotoMode) {
+	public PhotoModeRenderer(Minecraft minecraft, PhotoModeScreen screen) {
 		super(minecraft);
 
-		this.guiPhotoMode = guiPhotoMode;
+		this.screen = screen;
 		
 		if(!Shaders.enableShaders) throw new RuntimeException("Shaders disabled!");
 	}
diff --git a/src/main/java/net/minecraft/client/render/shader/Shader.java b/src/main/java/net/minecraft/client/render/shader/Shader.java
index 8fa88bf29..6a9af19cc 100644
--- a/src/main/java/net/minecraft/client/render/shader/Shader.java
+++ b/src/main/java/net/minecraft/client/render/shader/Shader.java
@@ -6,10 +6,12 @@ import static org.lwjgl.opengl.GL20.*;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.render.OpenGLHelper;
+import org.slf4j.Logger;
 
 public class Shader {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private int program;
 	
 	private int vertexShader;
@@ -45,15 +47,15 @@ public class Shader {
 		int vertexShaderCompileStatus = glGetShaderi(vertexShader, GL_COMPILE_STATUS);
 		
 		if(fragmentShaderCompileStatus != GL_TRUE || vertexShaderCompileStatus != GL_TRUE) {
-			System.err.println("Shader "+name+" compile error");
+            LOGGER.error("Shader {} compile error", name);
 			
 			if(vertexShaderCompileStatus != GL_TRUE) {
-				System.err.println("Vertex Shader Info Log:");
-				System.err.println(glGetShaderInfoLog(vertexShader, glGetShaderi(vertexShader, GL_INFO_LOG_LENGTH)));
+				LOGGER.error("Vertex Shader Info Log:");
+				LOGGER.error(glGetShaderInfoLog(vertexShader, glGetShaderi(vertexShader, GL_INFO_LOG_LENGTH)));
 			}
 			if(fragmentShaderCompileStatus != GL_TRUE) {
-				System.err.println("Vertex Shader Info Log:");
-				System.err.println(glGetShaderInfoLog(fragmentShader, glGetShaderi(fragmentShader, GL_INFO_LOG_LENGTH)));
+				LOGGER.error("Vertex Shader Info Log:");
+				LOGGER.error(glGetShaderInfoLog(fragmentShader, glGetShaderi(fragmentShader, GL_INFO_LOG_LENGTH)));
 			}
 			
 			delete();
@@ -69,8 +71,8 @@ public class Shader {
 		
 		int programLinkStatus = glGetProgrami(program, GL_LINK_STATUS);
 		if(programLinkStatus != GL_TRUE) {
-			System.err.println("Program Link Error: ");
-			System.err.println(glGetProgramInfoLog(program, glGetProgrami(program, GL_INFO_LOG_LENGTH)));
+			LOGGER.error("Program Link Error: ");
+			LOGGER.error(glGetProgramInfoLog(program, glGetProgrami(program, GL_INFO_LOG_LENGTH)));
 			
 			delete();
 			return this;
diff --git a/src/main/java/net/minecraft/client/render/shader/ShaderProviderExternal.java b/src/main/java/net/minecraft/client/render/shader/ShaderProviderExternal.java
index 27c535350..d6e45a2cd 100644
--- a/src/main/java/net/minecraft/client/render/shader/ShaderProviderExternal.java
+++ b/src/main/java/net/minecraft/client/render/shader/ShaderProviderExternal.java
@@ -3,10 +3,12 @@ package net.minecraft.client.render.shader;
 import java.io.File;
 
 import com.b100.utils.StringUtils;
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
 
 public class ShaderProviderExternal implements ShaderProvider {
-	
-	private File dir;
+	private static final Logger LOGGER = LogUtils.getLogger();
+	private final File dir;
 	
 	public ShaderProviderExternal(File dir) {
 		this.dir = dir;
@@ -16,13 +18,13 @@ public class ShaderProviderExternal implements ShaderProvider {
 	public String getShaderSource(String name) {
 		File file = new File(dir, name);
 		if(!file.exists()) {
-			System.err.println("File " + file.getAbsolutePath() + " does not exist!");
+            LOGGER.error("File {} does not exist!", file.getAbsolutePath());
 			return null;
 		}
 		try {
 			return StringUtils.getFileContentAsString(file);
 		}catch (Exception e) {
-			e.printStackTrace();
+            LOGGER.error("Exception reading shader file '{}'!", file.getPath(), e);
 			return null;
 		}
 	}
diff --git a/src/main/java/net/minecraft/client/render/shader/ShaderProviderInternal.java b/src/main/java/net/minecraft/client/render/shader/ShaderProviderInternal.java
index 48d30d673..da6097a29 100644
--- a/src/main/java/net/minecraft/client/render/shader/ShaderProviderInternal.java
+++ b/src/main/java/net/minecraft/client/render/shader/ShaderProviderInternal.java
@@ -3,10 +3,12 @@ package net.minecraft.client.render.shader;
 import java.io.InputStream;
 
 import com.b100.utils.StringUtils;
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
 
 public class ShaderProviderInternal implements ShaderProvider {
-
-	private String dir;
+	private static final Logger LOGGER = LogUtils.getLogger();
+	private final String dir;
 	
 	public ShaderProviderInternal(String dir) {
 		this.dir = dir;
@@ -15,24 +17,18 @@ public class ShaderProviderInternal implements ShaderProvider {
 	@Override
 	public String getShaderSource(String name) {
 		String path = dir + name;
-		
-		InputStream stream = null;
-		try {
-			stream = ShaderProviderInternal.class.getResourceAsStream(dir + name);
-			if(stream != null) {
-				return StringUtils.readInputString(stream);
-			}else {
-				System.err.println("Resource " + path + " does not exist!");
-				return null;
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-			return null;
-		} finally {
-			try {
-				stream.close();
-			}catch (Exception e) {}
-		}
+
+        try (InputStream stream = ShaderProviderInternal.class.getResourceAsStream(dir + name)) {
+            if (stream != null) {
+                return StringUtils.readInputString(stream);
+            } else {
+                LOGGER.error("Resource {} does not exist!", path);
+                return null;
+            }
+        } catch (Exception e) {
+            LOGGER.error("Exception reading shader resource '{}{}'!", dir, name, e);
+            return null;
+        }
 	}
 
 }
diff --git a/src/main/java/net/minecraft/client/render/shader/Shaders.java b/src/main/java/net/minecraft/client/render/shader/Shaders.java
index b30f7540f..7ad75a21e 100644
--- a/src/main/java/net/minecraft/client/render/shader/Shaders.java
+++ b/src/main/java/net/minecraft/client/render/shader/Shaders.java
@@ -4,7 +4,7 @@ package net.minecraft.client.render.shader;
 import static org.lwjgl.opengl.GL11.*;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiPhotoMode;
+import net.minecraft.client.gui.PhotoModeScreen;
 import net.minecraft.client.render.camera.CameraUtil;
 import net.minecraft.core.block.material.Material;
 
@@ -103,12 +103,12 @@ public abstract class Shaders {
 			shader.uniformFloat("gMod", 1.0f);
 			shader.uniformFloat("bMod", 1.0f);
 		}
-		shader.uniformFloat("photoMode", minecraft.currentScreen instanceof GuiPhotoMode);
+		shader.uniformFloat("photoMode", minecraft.currentScreen instanceof PhotoModeScreen);
 		shader.uniformFloat("guiOpened", minecraft.currentScreen != null);
 		
-		if(minecraft.currentScreen instanceof GuiPhotoMode) {
-			GuiPhotoMode guiPhotoMode = (GuiPhotoMode) minecraft.currentScreen;
-			shader.uniformFloat("intensity", guiPhotoMode.intensityValue);
+		if(minecraft.currentScreen instanceof PhotoModeScreen) {
+			PhotoModeScreen photoModeScreen = (PhotoModeScreen) minecraft.currentScreen;
+			shader.uniformFloat("intensity", photoModeScreen.intensityValue);
 		}else {
 			shader.uniformFloat("intensity", 1.0f);
 		}
diff --git a/src/main/java/net/minecraft/client/render/shader/ShadersRenderer.java b/src/main/java/net/minecraft/client/render/shader/ShadersRenderer.java
index 8f1773f20..08f607cab 100644
--- a/src/main/java/net/minecraft/client/render/shader/ShadersRenderer.java
+++ b/src/main/java/net/minecraft/client/render/shader/ShadersRenderer.java
@@ -10,6 +10,7 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.FloatBuffer;
 
+import com.mojang.logging.LogUtils;
 import org.lwjgl.util.vector.Matrix4f;
 
 import net.minecraft.client.Minecraft;
@@ -20,9 +21,10 @@ import net.minecraft.client.render.texture.Texture;
 import net.minecraft.client.render.camera.CameraUtil;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.material.Material;
+import org.slf4j.Logger;
 
 public class ShadersRenderer implements Renderer {
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public Minecraft mc;
 	
 	protected final Framebuffer worldFramebuffer = new Framebuffer();
@@ -216,8 +218,8 @@ public class ShadersRenderer implements Renderer {
 			
 			boolean filtering = mc.gameSettings.renderScale.value.useLinearFiltering;
 			int filterMode = filtering ? GL_LINEAR : GL_NEAREST;
-			
-			System.out.println("Display: "+fbWidth+" x "+fbHeight+", Render: "+renderWidth+" x "+renderHeight);
+
+            LOGGER.info("Display: {} x {}, Render: {} x {}", fbWidth, fbHeight, renderWidth, renderHeight);
 			
 			worldFramebuffer.bind();
 
@@ -259,7 +261,7 @@ public class ShadersRenderer implements Renderer {
 		}
 	}
 	public void reload() {
-		System.out.println("Reloading Shaders...");
+		LOGGER.info("Reloading Shaders...");
 
 		glUseProgram(0);
 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -299,7 +301,7 @@ public class ShadersRenderer implements Renderer {
 	
 	public ShaderProvider getShader() {
 		String override = mc.gameSettings.shaderOverride.value;
-		if(override != null && override.length() > 0) {
+		if(override != null && !override.isEmpty()) {
 			return new ShaderProviderExternal(new File(Global.accessor.getMinecraftDir(), "shaders/" + override));
 		}else {
 			return internal;
diff --git a/src/main/java/net/minecraft/client/render/tessellator/TessellatorStandard.java b/src/main/java/net/minecraft/client/render/tessellator/TessellatorStandard.java
index 79b4fe822..ec3aeb0fe 100644
--- a/src/main/java/net/minecraft/client/render/tessellator/TessellatorStandard.java
+++ b/src/main/java/net/minecraft/client/render/tessellator/TessellatorStandard.java
@@ -3,15 +3,17 @@ package net.minecraft.client.render.tessellator;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.render.terrain.VertexConfig;
 import net.minecraft.client.render.terrain.VertexData;
 import net.minecraft.core.util.helper.MathHelper;
+import org.slf4j.Logger;
 
 public class TessellatorStandard extends TessellatorBase {
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public VertexData data;
 	public boolean drawing;
-	
+
 	private int color;
 	
 	private int lightmapCoord;
@@ -79,7 +81,7 @@ public class TessellatorStandard extends TessellatorBase {
 		if(data.buffer.capacity() < data.buffer.position() + 64) {
 			int newSize = data.buffer.capacity() * 2;
 			
-			System.out.println("Expanding Tessellator Buffer (" + data.buffer.capacity() + " -> " + newSize + ")");
+			LOGGER.info("Expanding Tessellator Buffer (" + data.buffer.capacity() + " -> " + newSize + ")");
 			
 			ByteBuffer newBuffer = ByteBuffer.allocateDirect(newSize).order(ByteOrder.nativeOrder());
 			data.buffer.flip();
diff --git a/src/main/java/net/minecraft/client/render/texture/FileTexture.java b/src/main/java/net/minecraft/client/render/texture/FileTexture.java
index 4922c53e3..1557368bf 100644
--- a/src/main/java/net/minecraft/client/render/texture/FileTexture.java
+++ b/src/main/java/net/minecraft/client/render/texture/FileTexture.java
@@ -1,9 +1,11 @@
 package net.minecraft.client.render.texture;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.texture.meta.TextureMetaHandler;
 import net.minecraft.client.render.texturepack.TexturePack;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -12,7 +14,7 @@ import static net.minecraft.client.util.helper.Textures.missingTexture;
 import static net.minecraft.client.util.helper.Textures.readImage;
 
 public class FileTexture extends Texture{
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     protected final String sourcePath;
 
     protected TextureMetaHandler metaHandler = new TextureMetaHandler();
@@ -59,7 +61,7 @@ public class FileTexture extends Texture{
                     metaHandler.loadFromStream(stream);
                 }
             } catch (Exception e) {
-                e.printStackTrace();
+                LOGGER.error("Failed to load data for '{}.mcmeta'!", sourcePath, e);
             }
 
             try (InputStream imageStream = pack.getResourceAsStream(sourcePath)) {
@@ -76,10 +78,8 @@ public class FileTexture extends Texture{
 
     @Override
     public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append("Source: ").append(sourcePath).append("\n");
-        builder.append("Meta: \n").append(metaHandler);
-        return builder.toString();
+        return "Source: " + sourcePath + "\n" +
+                "Meta: \n" + metaHandler;
     }
 
 }
diff --git a/src/main/java/net/minecraft/client/render/texture/Texture.java b/src/main/java/net/minecraft/client/render/texture/Texture.java
index 86b753d83..35453be3f 100644
--- a/src/main/java/net/minecraft/client/render/texture/Texture.java
+++ b/src/main/java/net/minecraft/client/render/texture/Texture.java
@@ -4,17 +4,20 @@ import static net.minecraft.core.util.helper.Buffer.buffer;
 import static org.lwjgl.opengl.GL11.*;
 import static org.lwjgl.opengl.GL12.GL_TEXTURE_MAX_LEVEL;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.GLAllocation;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.option.enums.MipmapType;
 import net.minecraft.client.render.texture.meta.TextureProperties;
 import net.minecraft.core.util.helper.Buffer;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
 
 import java.awt.image.BufferedImage;
 import java.nio.ByteBuffer;
 
 public class Texture {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public static boolean debugMipmap = false;
 	protected static final boolean fixArtifacts = true;
 	
@@ -141,7 +144,7 @@ public class Texture {
 	}
 
 	protected void generateMipmaps(ByteBuffer buffer, BufferedImage image, int levels, boolean smooth) {
-		System.out.println("Generating Mipmaps...");
+		LOGGER.info("Generating Mipmaps...");
 
 		final int width = image.getWidth();
 		final int height = image.getHeight();
diff --git a/src/main/java/net/minecraft/client/render/texture/meta/TextureMetaHandler.java b/src/main/java/net/minecraft/client/render/texture/meta/TextureMetaHandler.java
index a679a2b34..d65097a7c 100644
--- a/src/main/java/net/minecraft/client/render/texture/meta/TextureMetaHandler.java
+++ b/src/main/java/net/minecraft/client/render/texture/meta/TextureMetaHandler.java
@@ -6,16 +6,19 @@ import com.google.gson.GsonBuilder;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParseException;
 import com.google.gson.JsonParser;
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.render.texture.meta.gui.GuiTextureProperties;
 import net.minecraft.client.render.texture.meta.gui.GuiTexturePropertiesAdapter;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
 
 import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Map;
 
 public class TextureMetaHandler {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private static final Gson GSON;
     static {
         GsonBuilder builder = new GsonBuilder();
@@ -35,19 +38,15 @@ public class TextureMetaHandler {
         cachedData.clear();
     }
 
-    public void loadFromStream(InputStream stream) {
+    public void loadFromStream(InputStream stream) throws JsonParseException {
         String jsonString;
         try {
             jsonString = StringUtils.readInputString(stream);
         } catch (Exception e) {
-            e.printStackTrace();
+            LOGGER.error("Failed to read json string from stream!", e);
             return;
         }
-        try {
-            metaJson = JsonParser.parseString(jsonString).getAsJsonObject();
-        } catch (JsonParseException e) { // TODO, replace with proper non-fatal error logging
-            e.printStackTrace();
-        }
+        metaJson = JsonParser.parseString(jsonString).getAsJsonObject();
     }
 
     public boolean has(String key) {
diff --git a/src/main/java/net/minecraft/client/render/texture/stitcher/AtlasStitcher.java b/src/main/java/net/minecraft/client/render/texture/stitcher/AtlasStitcher.java
index f8c9aa240..5a1913d90 100644
--- a/src/main/java/net/minecraft/client/render/texture/stitcher/AtlasStitcher.java
+++ b/src/main/java/net/minecraft/client/render/texture/stitcher/AtlasStitcher.java
@@ -3,7 +3,6 @@ package net.minecraft.client.render.texture.stitcher;
 import java.awt.AlphaComposite;
 import java.awt.Graphics2D;
 import java.awt.image.BufferedImage;
-import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -16,6 +15,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.texture.Texture;
 import net.minecraft.client.render.texturepack.TexturePack;
@@ -25,8 +25,10 @@ import org.jetbrains.annotations.Nullable;
 
 import net.minecraft.client.render.customatlas.CustomAtlasHandler;
 import net.minecraft.client.util.helper.Textures;
+import org.slf4j.Logger;
 
 public class AtlasStitcher extends Texture {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static final String rootAssetPath = "/assets";
     public Map<NamespaceID, IconCoordinate> textureMap = new HashMap<>();
     public BufferedImage atlas;
@@ -71,11 +73,11 @@ public class AtlasStitcher extends Texture {
             try {
                 f.get();
             } catch (InterruptedException | ExecutionException e) {
-                e.printStackTrace();
+                LOGGER.error("", e);
             }
         }
         service.shutdown();
-        System.out.println("Took '" + (System.nanoTime() - startTime)/1_000_000_000d + "' seconds to load images.");
+        LOGGER.debug("Took '{}' seconds to load images.", (System.nanoTime() - startTime) / 1_000_000_000d);
     }
 
     @Override
@@ -156,7 +158,7 @@ public class AtlasStitcher extends Texture {
             this.defaultTexture = defaultTexture;
         }
         @Override
-        public IconCoordinate call() throws Exception {
+        public IconCoordinate call() {
             coordinate.resetMetadata();
             BufferedImage image = CustomAtlasHandler.getTextureOverride(mc.texturePackList, coordinate.sourceImage);
             if(image == null) {
@@ -166,10 +168,8 @@ public class AtlasStitcher extends Texture {
                         try {
                             image = Textures.readImageUnhandled(pack.getResourceAsStream(coordinate.sourceImage));
                             if (image != null) break;
-                        } catch (IOException io) {
-                            io.printStackTrace();
                         } catch (Exception e) {
-                            e.printStackTrace();
+                            LOGGER.error("", e);
                         }
                     }
                     String metaPath = coordinate.sourceImage + ".mcmeta";
@@ -177,14 +177,14 @@ public class AtlasStitcher extends Texture {
                         try (InputStream stream = pack.getResourceAsStream(metaPath)){
                             coordinate.initMetadata(stream);
                         } catch (Exception e) {
-                            e.printStackTrace();
+                            LOGGER.error("Failed to initiate metadata for '{}'!", coordinate.namespaceId, e);
                         }
                     }
                 }
 
             }
             if (image == null || image == Textures.missingTexture){
-                System.out.println(coordinate.sourceImage + " could not be found!");
+                LOGGER.warn("{} could not be found!", coordinate.sourceImage);
                 if (defaultTexture != null){
                     image = Textures.readImage(mc.texturePackList.getResourceAsStream(defaultTexture));
                 }
diff --git a/src/main/java/net/minecraft/client/render/texture/stitcher/IconCoordinate.java b/src/main/java/net/minecraft/client/render/texture/stitcher/IconCoordinate.java
index d135a867f..7f70fb9d0 100644
--- a/src/main/java/net/minecraft/client/render/texture/stitcher/IconCoordinate.java
+++ b/src/main/java/net/minecraft/client/render/texture/stitcher/IconCoordinate.java
@@ -1,15 +1,18 @@
 package net.minecraft.client.render.texture.stitcher;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.render.texture.meta.TextureMetaHandler;
 import net.minecraft.core.util.collection.NamespaceID;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
 
 import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.io.InputStream;
 
 public class IconCoordinate implements Comparable<IconCoordinate> {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public int iconX;
     public int iconY;
     public int width;
@@ -103,7 +106,11 @@ public class IconCoordinate implements Comparable<IconCoordinate> {
     }
 
     protected void initMetadata(InputStream stream) {
-        metaHandler.loadFromStream(stream);
+        try {
+            metaHandler.loadFromStream(stream);
+        } catch (Exception e) {
+            LOGGER.error("Failed to load metadata for '{}'!", namespaceId, e);
+        }
     }
 
     public boolean hasMeta(String key) {
diff --git a/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java b/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java
index 070eee5f0..d1da1f01c 100644
--- a/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java
+++ b/src/main/java/net/minecraft/client/render/texture/stitcher/TextureRegistry.java
@@ -2,9 +2,11 @@ package net.minecraft.client.render.texture.stitcher;
 
 
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.util.HardIllegalArgumentException;
 import net.minecraft.core.util.collection.NamespaceID;
 import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
 
 import java.io.IOException;
 import java.net.URI;
@@ -23,6 +25,7 @@ import java.util.Objects;
 import java.util.stream.Stream;
 
 public class TextureRegistry {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static HashMap<String, AtlasStitcher> stitcherMap = new HashMap<>();
     @SuppressWarnings("unused")
     public static AtlasStitcher blockAtlas = register("block", new AtlasStitcher("textures/block", false, true, "/assets/minecraft/textures/block/texture_missing.png"));
@@ -86,8 +89,7 @@ public class TextureRegistry {
                 initializeAllFiles("minecraft", stitcher, stitcher != artAtlas);
             }
         } catch (Exception e) {
-            new RuntimeException(e).printStackTrace();
-            System.out.println("Failed to fully initialize assets, some issue may occur!");
+            LOGGER.warn("Failed to fully initialize assets, some issue may occur!", e);
         }
     }
 
@@ -117,7 +119,7 @@ public class TextureRegistry {
         try {
             uri = Objects.requireNonNull(TextureRegistry.class.getResource(directory)).toURI();
         } catch (NullPointerException npe) {
-            System.out.println("Failed to load directory '" + directory + "'! Skipping!");
+            LOGGER.warn("Failed to load directory '{}'! Skipping!", directory);
             return new String[0];
         }
 
diff --git a/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java b/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java
index 033205367..46d80c445 100644
--- a/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java
+++ b/src/main/java/net/minecraft/client/render/texturepack/TexturePack.java
@@ -3,6 +3,7 @@ package net.minecraft.client.render.texturepack;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
+import java.net.URL;
 import java.nio.file.*;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -10,9 +11,12 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.stream.Stream;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
+import org.slf4j.Logger;
 
 public abstract class TexturePack {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public String packId;
 	public String fileName;
 	public ManifestBase manifest;
@@ -50,9 +54,11 @@ public abstract class TexturePack {
 
 		if (!directory.endsWith("/")) directory = directory + "/";
 
-		try
+		label: try
 		{
-			URI uri = TexturePack.class.getResource(directory).toURI();
+			URL url = TexturePack.class.getResource(directory);
+			if (url == null) break label;
+			URI uri = url.toURI();
 			Path myPath;
 			FileSystem fileSystem = null;
 			if (uri.getScheme().equals("jar"))
@@ -87,7 +93,7 @@ public abstract class TexturePack {
 		}
 		catch (Exception e)
 		{
-			e.printStackTrace();
+            LOGGER.error("Exception while loading all files in directory '{}' at '{}'!", directory, packId, e);
 		}
 
 		return paths.toArray(new String[0]);
diff --git a/src/main/java/net/minecraft/client/render/texturepack/TexturePackCustom.java b/src/main/java/net/minecraft/client/render/texturepack/TexturePackCustom.java
index 6fe225e61..aa7b7a23c 100644
--- a/src/main/java/net/minecraft/client/render/texturepack/TexturePackCustom.java
+++ b/src/main/java/net/minecraft/client/render/texturepack/TexturePackCustom.java
@@ -3,7 +3,6 @@ package net.minecraft.client.render.texturepack;
 import java.awt.image.BufferedImage;
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -14,18 +13,22 @@ import java.util.List;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.texture.BufferedTexture;
 import net.minecraft.client.render.texturepack.Manifest.ManifestException;
+import org.slf4j.Logger;
 
 import javax.imageio.ImageIO;
 
 public class TexturePackCustom extends TexturePack
 {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private BufferedTexture thumbnailImage;
 	private BufferedImage thumbnailBuffer;
 	public final File file;
 	private ZipFile zipFile;
+	public boolean debug = false;
 
     public TexturePackCustom(File file)
     {
@@ -34,6 +37,10 @@ public class TexturePackCustom extends TexturePack
         this.file = file;
     }
 
+	public void setDebug() {
+		debug = true;
+	}
+
 	@Override
 	public void readTexturePackManifest()
 		throws IOException {
@@ -42,21 +49,14 @@ public class TexturePackCustom extends TexturePack
 			ZipEntry manifestEntry = zipFile.getEntry("manifest.json");
 			if(manifestEntry != null) {
 				// manifest.json exists
-				
-				InputStream in = null;
-				try {
-					in = zipFile.getInputStream(manifestEntry);
-					readManifest(in);
-				}catch (Exception e) {
-					// TODO
-					e.printStackTrace();
-				}finally {
-					try {
-						in.close();
-					}catch (Exception e) {}
-				}
+
+                try (InputStream in = zipFile.getInputStream(manifestEntry)) {
+                    readManifest(in);
+                } catch (Exception e) {
+                    LOGGER.error("Exception reading manifest for '{}'!", packId, e);
+                }
 			}else {
-				// Assume its an old texture pack
+				// Assume it's an old texture pack
 
 				String name = file.getName();
 				String line1 = "";
@@ -64,25 +64,12 @@ public class TexturePackCustom extends TexturePack
 				
 				ZipEntry packTxtEntry = zipFile.getEntry("pack.txt");
 				if(packTxtEntry != null) {
-					InputStream in = null;
-					BufferedReader br = null;
-					try {
-						in = zipFile.getInputStream(packTxtEntry);
-						br = new BufferedReader(new InputStreamReader(in));
-
-						line1 = br.readLine();
-						line2 = br.readLine();
-					}catch (Exception e) {
-						// TODO
-						e.printStackTrace();
-					}finally {
-						try {
-							in.close();
-						}catch (Exception e) {}
-						try {
-							br.close();
-						}catch (Exception e) {}
-					}
+                    try (InputStream in = zipFile.getInputStream(packTxtEntry); BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
+                        line1 = br.readLine();
+                        line2 = br.readLine();
+                    } catch (Exception e) {
+                        LOGGER.error("Exception reading pack.txt for '{}'!", packId, e);
+                    }
 				}
 				
 				this.manifest = new ManifestFallback(name, line1, line2, 0);
@@ -90,18 +77,11 @@ public class TexturePackCustom extends TexturePack
 		} else if (file.isDirectory()) {
 			File manifestFile = new File(this.file, "manifest.json");
 			if(manifestFile.exists()) {
-				InputStream in = null;
-				try {
-					in = new FileInputStream(manifestFile);
-					readManifest(in);
-				}catch (Exception e) {
-					// TODO
-					e.printStackTrace();
-				}finally {
-					try {
-						in.close();
-					}catch (Exception e) {}
-				}
+                try (InputStream in = Files.newInputStream(manifestFile.toPath())) {
+                    readManifest(in);
+                } catch (Exception e) {
+                    LOGGER.error("Exception reading manifest for '{}'!", packId, e);
+                }
 			}else {
 				// Assume its an old texture pack
 
@@ -111,25 +91,12 @@ public class TexturePackCustom extends TexturePack
 				
 				File packTxtFile = new File(this.file, "pack.txt");
 				if(packTxtFile.exists()) {
-					InputStream in = null;
-					BufferedReader br = null;
-					try {
-						in = new FileInputStream(packTxtFile);
-						br = new BufferedReader(new InputStreamReader(in));
-
-						line1 = br.readLine();
-						line2 = br.readLine();
-					}catch (Exception e) {
-						// TODO
-						e.printStackTrace();
-					}finally {
-						try {
-							in.close();
-						}catch (Exception e) {}
-						try {
-							br.close();
-						}catch (Exception e) {}
-					}
+                    try (InputStream in = Files.newInputStream(packTxtFile.toPath()); BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
+                        line1 = br.readLine();
+                        line2 = br.readLine();
+                    } catch (Exception e) {
+                        LOGGER.error("Exception reading pack.txt for '{}'!", packId, e);
+                    }
 				}
 				
 				this.manifest = new ManifestFallback(name, line1, line2, 0);
@@ -160,10 +127,10 @@ public class TexturePackCustom extends TexturePack
 			this.manifest = new Manifest(file, in);
 		}catch (ManifestException e) {
 			this.manifest = new ManifestFallback(fileName, "Manifest Error: " + e.getMessage(), "", -1);
-			e.printStackTrace();
+			LOGGER.error("Manifest Error!", e);
 		}catch (Exception e) {
 			this.manifest = new ManifestFallback(fileName, "Manifest Error", "", -1);
-			e.printStackTrace();
+			LOGGER.error("Manifest Error!", e);
 		}
 	}
 
@@ -183,14 +150,14 @@ public class TexturePackCustom extends TexturePack
     {
         if(thumbnailBuffer != null && thumbnailImage == null)
         {
-            thumbnailImage = minecraft.renderEngine.loadBufferedTexture(thumbnailBuffer);
+            thumbnailImage = minecraft.textureManager.loadBufferedTexture(thumbnailBuffer);
         }
         if(thumbnailBuffer != null)
         {
-            minecraft.renderEngine.bindTexture(thumbnailImage);
+            minecraft.textureManager.bindTexture(thumbnailImage);
         } else
         {
-			minecraft.renderEngine.loadTexture("/assets/minecraft/textures/gui/unknown_pack.png").bind();
+			minecraft.textureManager.loadTexture("/assets/minecraft/textures/gui/unknown_pack.png").bind();
         }
     }
 
diff --git a/src/main/java/net/minecraft/client/render/texturepack/TexturePackDefault.java b/src/main/java/net/minecraft/client/render/texturepack/TexturePackDefault.java
index 8954c1e4a..b2f11687e 100644
--- a/src/main/java/net/minecraft/client/render/texturepack/TexturePackDefault.java
+++ b/src/main/java/net/minecraft/client/render/texturepack/TexturePackDefault.java
@@ -6,11 +6,14 @@ import java.io.InputStream;
 
 import javax.imageio.ImageIO;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.texture.BufferedTexture;
+import org.slf4j.Logger;
 
 public class TexturePackDefault extends TexturePack
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private BufferedTexture texturePackThumbnailTexture;
     private BufferedImage texturePackThumbnail;
 
@@ -23,9 +26,9 @@ public class TexturePackDefault extends TexturePack
         {
             texturePackThumbnail = ImageIO.read(TexturePackDefault.class.getResource("/pack.png"));
         }
-        catch(IOException ioexception)
+        catch(IOException e)
         {
-            ioexception.printStackTrace();
+            LOGGER.error("Failed to read thumbnail for '{}'!", packId, e);
         }
     }
 
@@ -43,15 +46,15 @@ public class TexturePackDefault extends TexturePack
     {
         if(texturePackThumbnail != null && texturePackThumbnailTexture == null)
         {
-            texturePackThumbnailTexture = minecraft.renderEngine.loadBufferedTexture(texturePackThumbnail);
+            texturePackThumbnailTexture = minecraft.textureManager.loadBufferedTexture(texturePackThumbnail);
         }
         if(texturePackThumbnail != null)
         {
-            minecraft.renderEngine.bindTexture(texturePackThumbnailTexture);
+            minecraft.textureManager.bindTexture(texturePackThumbnailTexture);
         }
         else
         {
-            minecraft.renderEngine.loadTexture("/assets/minecraft/textures/gui/unknown_pack.png").bind();
+            minecraft.textureManager.loadTexture("/assets/minecraft/textures/gui/unknown_pack.png").bind();
         }
     }
 
diff --git a/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java b/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
index 1d5b68f9d..ae6498673 100644
--- a/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
+++ b/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
@@ -1,20 +1,24 @@
 package net.minecraft.client.render.texturepack;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.sound.SoundRepository;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 public class TexturePackList
 {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static final String SEPERATOR = "<-=-=->";
     private List<TexturePack> availableTexturePacks = new ArrayList<>();
     private final TexturePack defaultTexturePack = new TexturePackDefault();
@@ -84,13 +88,13 @@ public class TexturePackList
 		}
 	}
 	public void refresh(){
-		mc.renderEngine.refreshTexturesAndDisplayErrors();
-		mc.fontRenderer = new FontRenderer(mc, mc.gameSettings, "/font/default.png", mc.renderEngine);
+		mc.textureManager.refreshTexturesAndDisplayErrors();
+		mc.font = new Font(mc, mc.gameSettings, mc.textureManager);
 		mc.renderGlobal.loadRenderers();
 		if (mc.currentScreen != null) {
-			mc.currentScreen.refreshFontRenderer();
+			mc.currentScreen.updateFont();
 		}
-		mc.renderEngine.updateDynamicTextures(false);
+		mc.textureManager.updateDynamicTextures(false);
 		SoundRepository.reload();
 	}
 
@@ -100,31 +104,29 @@ public class TexturePackList
 		boolean update = false;
 		
 		if(texturePackDir.exists() && texturePackDir.isDirectory()) {
-			File[] filesInDir = texturePackDir.listFiles();
-			
-			if(filesInDir != null) {
+			File[] filesArr = texturePackDir.listFiles();
+
+			if(filesArr != null) {
+                List<File> fileList = new ArrayList<>(Arrays.asList(filesArr));
 				if (mc.gameSettings.enableDevResourceLoading.value) { // Load project resources as an available texture pack
-					File[] tempList = new File[filesInDir.length + 1];
-					for (int i = 0; i < tempList.length; i++) {
-						if (i < tempList.length - 1){
-							tempList[i] = filesInDir[i];
-						} else {
-							File local = new File("./src/main/resources");
-							System.out.println(local.getAbsoluteFile());
-							tempList[i] = local;
-						}
+					File resources = new File("./src/main/resources");
+					fileList.add(resources);
+
+					File devPacksPath = new File("./devPacks");
+					File[] devPacks = devPacksPath.listFiles();
+					if (devPacks != null) {
+                        fileList.addAll(Arrays.asList(devPacks));
 					}
-					filesInDir = tempList;
 				}
 
-				for(File file : filesInDir) {
+				for(File file : fileList) {
 					if(!isTexturePack(file)) {
 						continue;
 					}
 					String id = getTexturePackID(file);
 					try {
 						if(!texturePackIDs.containsKey(id)) {
-							TexturePack pack = new TexturePackCustom(file);
+							TexturePackCustom pack = new TexturePackCustom(file);
 							pack.packId = id;
 							pack.readZipFile();
 							pack.readTexturePackManifest();
@@ -137,7 +139,7 @@ public class TexturePackList
 						TexturePack pack = texturePackIDs.get(id);
 						currentTexturePacks.add(pack);
 					}catch (IOException e) {
-						e.printStackTrace();
+                        LOGGER.error("Failed to make texturepack for file '{}'!", file.getPath(), e);
 					}
 				}
 			}
@@ -145,7 +147,7 @@ public class TexturePackList
 		List<TexturePack> previousTexturePacks = this.availableTexturePacks;
 		previousTexturePacks.removeAll(currentTexturePacks);
 		
-		if(previousTexturePacks.size() > 0) {
+		if(!previousTexturePacks.isEmpty()) {
 			update = true;
 		}
 		
diff --git a/src/main/java/net/minecraft/client/sound/CodecMus.java b/src/main/java/net/minecraft/client/sound/CodecMus.java
index 66b9cd587..7a205306b 100644
--- a/src/main/java/net/minecraft/client/sound/CodecMus.java
+++ b/src/main/java/net/minecraft/client/sound/CodecMus.java
@@ -4,20 +4,19 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 
+import com.mojang.logging.LogUtils;
 import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
 import paulscode.sound.codecs.CodecJOrbis;
 
-// Referenced classes of package net.minecraft.src:
-//            DecoderInputStream
-
 public class CodecMus extends CodecJOrbis {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     @Override
 	protected InputStream openInputStream() {
         try {
             return new DecoderInputStream(url, urlConnection.getInputStream());
         } catch (IOException e) {
-            e.printStackTrace();
+            LOGGER.error("Exception decoding stream '{}'!", url.getPath(), e);
             return null;
         }
     }
@@ -51,17 +50,17 @@ public class CodecMus extends CodecJOrbis {
         }
 
         @Override
-        public int read(byte abyte0[], int i, int j)
+        public int read(byte @NotNull [] b, int i, int j)
         {
             try {
-                j = inputStream.read(abyte0, i, j);
+                j = inputStream.read(b, i, j);
             } catch (IOException e) {
-                e.printStackTrace();
+                LOGGER.error("CodecMus data read error!", e);
                 return 0;
             }
             for(int k = 0; k < j; k++)
             {
-                byte byte0 = abyte0[i + k] ^= hash >> 8;
+                byte byte0 = b[i + k] ^= hash >> 8;
                 hash = hash * 0x1dba038f + 0x14ee3 * byte0;
             }
 
diff --git a/src/main/java/net/minecraft/client/sound/NamedSoundRepository.java b/src/main/java/net/minecraft/client/sound/NamedSoundRepository.java
index c49bd0eda..173e5796d 100644
--- a/src/main/java/net/minecraft/client/sound/NamedSoundRepository.java
+++ b/src/main/java/net/minecraft/client/sound/NamedSoundRepository.java
@@ -9,9 +9,9 @@ import com.google.gson.JsonParseException;
 import com.google.gson.JsonParser;
 import net.minecraft.client.render.texturepack.TexturePack;
 import net.minecraft.core.data.registry.Registry;
+import net.minecraft.core.lang.I18n;
 
 import java.io.File;
-import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
 import java.util.ArrayList;
@@ -61,6 +61,9 @@ public class NamedSoundRepository extends Registry<SoundEvent> {
                     }
                 }
             }
+            if (e.getValue().subtitleKey != null) {
+                I18n.getInstance().translateKey(e.getValue().subtitleKey);
+            }
         }
 
         thrown.forEach(Throwable::printStackTrace);
@@ -101,7 +104,7 @@ public class NamedSoundRepository extends Registry<SoundEvent> {
 
             SoundEvent soundEvent = eventMap.get(fieldName);
             if (soundEvent == null || replaceEvent) {
-                soundEvent = new SoundEvent(fieldName, subtitle);
+                soundEvent = new SoundEvent(this,fieldName, subtitle);
             }
             if (subtitle != null) {
                 soundEvent.subtitleKey = subtitle;
@@ -122,13 +125,13 @@ public class NamedSoundRepository extends Registry<SoundEvent> {
                     for (JsonElement element : sounds) {
                         if (element.isJsonPrimitive()) {
                             try {
-                                soundEvent.addSoundEntry(getSoundEntry(pack, element.getAsString()));
+                                soundEvent.addSoundEntry(getSoundEntry(soundEvent, pack, element.getAsString()));
                             } catch (RuntimeException ex) {
                                 throwableList.add(ex);
                             }
                         } else if (element.isJsonObject()) {
                             try {
-                                soundEvent.addSoundEntry(getSoundEntry(pack, element.getAsJsonObject()));
+                                soundEvent.addSoundEntry(getSoundEntry(soundEvent, pack, element.getAsJsonObject()));
                             } catch (RuntimeException ex) {
                                 throwableList.add(ex);
                             }
@@ -140,11 +143,22 @@ public class NamedSoundRepository extends Registry<SoundEvent> {
         }
     }
 
-    public SoundEntry getSoundEntry(TexturePack pack, String path) {
-        return new SoundEntry(this, pack,path, 1, false, SoundEntry.Type.FILE);
+    public SoundEntry getSoundEntry(SoundEvent event, TexturePack pack, String path) {
+        return new SoundEntry
+            (
+                event,
+                pack,
+                path,
+                1f,
+                1f,
+                1,
+                16,
+                false,
+                SoundEntry.Type.FILE
+            );
     }
 
-    public SoundEntry getSoundEntry(TexturePack pack, JsonObject jObj) throws JsonParseException {
+    public SoundEntry getSoundEntry(SoundEvent event, TexturePack pack, JsonObject jObj) throws JsonParseException {
         String name = jObj.get("name").getAsString(); // Required
 
         float volume = 1;
@@ -182,7 +196,18 @@ public class NamedSoundRepository extends Registry<SoundEvent> {
             type = jObj.get("type").getAsString();
         }
 
-        return new SoundEntry(this, pack, name, weight, stream, SoundEntry.Type.valueOf(type.toUpperCase(Locale.ROOT)));
+        return new SoundEntry
+            (
+                event,
+                pack,
+                name,
+                volume,
+                pitch,
+                weight,
+                attenuation_distance,
+                stream,
+                SoundEntry.Type.valueOf(type.toUpperCase(Locale.ROOT)
+                ));
     }
 
     private JsonElement loadStreamAsElement(InputStream stream) throws JsonParseException {
diff --git a/src/main/java/net/minecraft/client/sound/SoundCategoryHelper.java b/src/main/java/net/minecraft/client/sound/SoundCategoryHelper.java
index 9c710092d..73fa45e5a 100644
--- a/src/main/java/net/minecraft/client/sound/SoundCategoryHelper.java
+++ b/src/main/java/net/minecraft/client/sound/SoundCategoryHelper.java
@@ -1,14 +1,17 @@
 package net.minecraft.client.sound;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.option.GameSettings;
 import net.minecraft.client.option.VolumeOption;
 import net.minecraft.core.sound.SoundCategory;
+import org.slf4j.Logger;
 
 import java.lang.reflect.Field;
 import java.util.HashMap;
 
 public class SoundCategoryHelper
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private static final HashMap<SoundCategory, Field> VOLUME_FIELDS = new HashMap<>();
 
     static
@@ -52,7 +55,7 @@ public class SoundCategoryHelper
         }
         catch (Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Failed to get volume for category '{}'!", field.getName(), e);
             return 0.0f;
         }
     }
@@ -69,7 +72,7 @@ public class SoundCategoryHelper
         }
         catch (Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Failed to get effective volume for category '{}'!", field.getName(), e);
             return 0.0f;
         }
     }
@@ -86,7 +89,7 @@ public class SoundCategoryHelper
         }
         catch (Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Failed to set volume for category '{}'!", field.getName(), e);
         }
     }
 }
diff --git a/src/main/java/net/minecraft/client/sound/SoundEngine.java b/src/main/java/net/minecraft/client/sound/SoundEngine.java
index 39640ef00..41ff4cf9c 100644
--- a/src/main/java/net/minecraft/client/sound/SoundEngine.java
+++ b/src/main/java/net/minecraft/client/sound/SoundEngine.java
@@ -3,12 +3,14 @@ package net.minecraft.client.sound;
 import java.net.URL;
 import java.util.Random;
 
+import com.mojang.logging.LogUtils;
 import net.betterthanadventure.sound.LibraryLWJGL3OpenAL;
 import net.minecraft.client.Minecraft;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.client.option.GameSettings;
+import org.slf4j.Logger;
 import paulscode.sound.SoundSystem;
 import paulscode.sound.SoundSystemConfig;
 import paulscode.sound.codecs.CodecJOrbis;
@@ -16,8 +18,8 @@ import paulscode.sound.codecs.CodecWav;
 
 public class SoundEngine
 {
-	private static final int SOUND_DISTANCE = 16; // TODO have the sound engine handle sound distance again
-	private static final int MUSIC_INTERVAL = 6000;
+	private static final Logger LOGGER = LogUtils.getLogger();
+  private static final int MUSIC_INTERVAL = 6000;
 	private static SoundSystem soundSystem;
 	private static boolean loaded = false;
 
@@ -48,9 +50,9 @@ public class SoundEngine
 		if (soundSystem == null) return;
 		this.muted = muted;
 		if (this.muted) {
-			soundSystem.setVolume("BgMusic", 0.0f);
+			soundSystem.setVolume(BG_MUSIC, 0.0f);
 		} else {
-			soundSystem.setVolume("BgMusic", SoundCategoryHelper.getEffectiveVolume(SoundCategory.MUSIC, options));
+			soundSystem.setVolume(BG_MUSIC, SoundCategoryHelper.getEffectiveVolume(SoundCategory.MUSIC, options));
 		}
 	}
 
@@ -112,7 +114,7 @@ public class SoundEngine
 			// TODO a more sane way of grouping music pools with our new system
 			SoundEvent event;
             if (mc != null && mc.thePlayer != null && !mc.thePlayer.world.canBlockSeeTheSky(MathHelper.floor(mc.thePlayer.x), MathHelper.floor(mc.thePlayer.y), MathHelper.floor(mc.thePlayer.z))) {
-				event = SoundRepository.SOUNDS.getRandomSoundFromCategory("ambient.cave.");
+				event = SoundRepository.SOUNDS.getSoundEvent("ambient.cave");
             } else {
 				event = SoundRepository.SOUNDS.getRandomSoundFromCategory("music.");
             }
@@ -120,9 +122,10 @@ public class SoundEngine
 			SoundEntry entry = event.getRandomEntry();
             if (entry != null) {
                 ticksBeforeMusic = random.nextInt(MUSIC_INTERVAL) + MUSIC_INTERVAL;
-                soundSystem.backgroundMusic("BgMusic", entry.getURL(), entry.name, false);
-                soundSystem.setVolume("BgMusic", SoundCategoryHelper.getEffectiveVolume(SoundCategory.MUSIC, options));
-                soundSystem.play("BgMusic");
+                soundSystem.backgroundMusic(BG_MUSIC, entry.getURL(), entry.name, false);
+				soundSystem.setPitch(BG_MUSIC, entry.pitch);
+                soundSystem.setVolume(BG_MUSIC, SoundCategoryHelper.getEffectiveVolume(SoundCategory.MUSIC, options) * entry.volume);
+                soundSystem.play(BG_MUSIC);
             }
         }
     }
@@ -178,12 +181,15 @@ public class SoundEngine
 						volume = 1.0F;
 					}
 					volume *= 0.25F;
-					soundSystem.setPitch(soundID, pitch);
-					soundSystem.setVolume(soundID, volume * SoundCategoryHelper.getEffectiveVolume(category, options));
+					soundSystem.setPitch(soundID, pitch * entry.pitch);
+					soundSystem.setVolume(soundID, volume * SoundCategoryHelper.getEffectiveVolume(category, options) * entry.volume);
 					soundSystem.play(soundID);
 				}
+				if (entry.parent.hasSubtitle()) {
+					mc.subtitleTracker.heardSound(entry.parent, 0, 0, 0);
+				}
 			} else if (entry.type == SoundEntry.Type.EVENT) {
-				playSoundWithIdAtPos(entry.name, category, 0, 0, 0, volume, pitch, soundID);
+				playSoundWithID(entry.name, category, volume, pitch, soundID);
 			}
 		}
 	}
@@ -194,26 +200,32 @@ public class SoundEngine
 
 	public void playSoundWithIdAtPos(SoundEntry entry, SoundCategory category, float x, float y, float z, float volume, final float pitch, String soundID) {
 		if (entry != null) {
+			float soundDistance = entry.attenuationDistance;
+			if(volume > 1.0F)
+			{
+				soundDistance *= volume;
+			}
+			if(mc.activeCamera.distanceToSqr(x, y, z) > (double)(soundDistance * soundDistance)) return;
+
 			if (entry.type == SoundEntry.Type.FILE) {
 				URL url = entry.getURL();
 				if (url != null){
-					float f5 = 16F;
-					if (volume > 1.0F)
-					{
-						f5 *= volume;
-					}
 					if (entry.shouldStream) {
-						soundSystem.newStreamingSource(volume > 1.0F, soundID, url, entry.name, false, x, y, z, 2, f5);
+						soundSystem.newStreamingSource(volume > 1.0F, soundID, url, entry.name, false, x, y, z, 2, soundDistance);
 					} else {
-						soundSystem.newSource(volume > 1.0F, soundID, url, entry.name, false, x, y, z, 0, f5);
+						soundSystem.newSource(volume > 1.0F, soundID, url, entry.name, false, x, y, z, 2, soundDistance);
 					}
 					if (volume > 1.0F) {
 						volume = 1.0F;
 					}
-					soundSystem.setPitch(soundID, pitch);
-					soundSystem.setVolume(soundID, volume * SoundCategoryHelper.getEffectiveVolume(category, options));
+
+					soundSystem.setPitch(soundID, pitch * entry.pitch);
+					soundSystem.setVolume(soundID, volume * SoundCategoryHelper.getEffectiveVolume(category, options) * entry.volume);
 					soundSystem.play(soundID);
 				}
+				if (entry.parent.hasSubtitle()) {
+					mc.subtitleTracker.heardSound(entry.parent, x, y, z);
+				}
 			} else if (entry.type == SoundEntry.Type.EVENT) {
 				playSoundWithIdAtPos(entry.name, category, x, y, z, volume, pitch, soundID);
 			}
@@ -230,7 +242,6 @@ public class SoundEngine
 		{
 			return;
 		}
-		final String streaming = STREAMING;
 		if (soundSystem.playing(STREAMING))
 		{
 			soundSystem.stop(STREAMING);
@@ -245,13 +256,13 @@ public class SoundEngine
 			{
 				soundSystem.stop(BG_MUSIC);
 			}
-			final float streamingVolume = 16F;
 			if (entry.type == SoundEntry.Type.FILE) {
 				URL url = entry.getURL();
 				if (url != null) {
-					soundSystem.newStreamingSource(true, streaming, url, entry.name, false, x, y, z, 2, streamingVolume * 4F);
-					soundSystem.setVolume(streaming, 0.5F * options.masterVolume.value);
-					soundSystem.play(streaming);
+					soundSystem.newStreamingSource(true, STREAMING, url, entry.name, false, x, y, z, 2, entry.attenuationDistance);
+					soundSystem.setPitch(STREAMING, pitch * entry.pitch);
+					soundSystem.setVolume(STREAMING, volume * entry.volume * options.masterVolume.value);
+					soundSystem.play(STREAMING);
 				}
 			} else if (entry.type == SoundEntry.Type.EVENT) {
 				playMusic(entry.name, x, y, z, volume, pitch);
@@ -283,8 +294,7 @@ public class SoundEngine
 			}
 			options.saveOptions();
         } catch (final Throwable throwable) {
-            throwable.printStackTrace();
-            System.err.println("error linking with the LibraryJavaSound plug-in");
+			LOGGER.error("Error linking with the LibraryJavaSound plug-in", throwable);
         }
         loaded = true;
     }
diff --git a/src/main/java/net/minecraft/client/sound/SoundEntry.java b/src/main/java/net/minecraft/client/sound/SoundEntry.java
index c08925db0..ddf1aca97 100644
--- a/src/main/java/net/minecraft/client/sound/SoundEntry.java
+++ b/src/main/java/net/minecraft/client/sound/SoundEntry.java
@@ -9,7 +9,7 @@ import java.net.MalformedURLException;
 import java.net.URL;
 
 public class SoundEntry {
-    public final @NotNull NamedSoundRepository parent;
+    public final @NotNull SoundEvent parent;
     public final @NotNull TexturePack pack;
 
     public final @NotNull String name;
@@ -19,6 +19,21 @@ public class SoundEntry {
      */
     public final int weight;
 
+    /**
+     * Distance the sound can be heard
+     */
+    public final int attenuationDistance;
+
+    /**
+     * Volume to play the sound with
+     */
+    public final float volume;
+
+    /**
+     * Pitch to play the sound with
+     */
+    public final float pitch;
+
     /**
      *  Whether the audio should be played as a stream or not
      */
@@ -31,15 +46,29 @@ public class SoundEntry {
 
     protected @Nullable File file;
 
-    public SoundEntry(@NotNull NamedSoundRepository parent, @NotNull TexturePack pack, @NotNull String name, int weight, boolean shouldStream, @NotNull Type type) {
-        this.parent = parent;
+    public SoundEntry
+        (
+        @NotNull SoundEvent parentEvent, @NotNull TexturePack pack,
+        @NotNull String name,
+        float volume,
+        float pitch,
+        int weight,
+        int attenuationDistance,
+        boolean shouldStream,
+        @NotNull Type type
+    )
+    {
+        this.parent = parentEvent;
         this.pack = pack;
         this.name = name;
+        this.volume = volume;
+        this.pitch = pitch;
         this.weight = weight;
+        this.attenuationDistance = attenuationDistance;
         this.shouldStream = shouldStream;
         this.type = type;
         if (type == Type.FILE) {
-            file = new File(parent.rootFile, name);
+            file = new File(parentEvent.parentRepo.rootFile, name);
         } else {
             file = null;
         }
diff --git a/src/main/java/net/minecraft/client/sound/SoundEvent.java b/src/main/java/net/minecraft/client/sound/SoundEvent.java
index 5cd95112f..de56f08ca 100644
--- a/src/main/java/net/minecraft/client/sound/SoundEvent.java
+++ b/src/main/java/net/minecraft/client/sound/SoundEvent.java
@@ -10,9 +10,11 @@ import java.util.Random;
 public class SoundEvent {
     private final WeightedRandomBag<SoundEntry> entryBag = new WeightedRandomBag<>();
 
+    public final @NotNull NamedSoundRepository parentRepo;
     private final @NotNull String id;
     protected @Nullable String subtitleKey;
-    public SoundEvent(@NotNull String eventID, @Nullable String subtitleKey) {
+    public SoundEvent(@NotNull NamedSoundRepository parentRepo, @NotNull String eventID, @Nullable String subtitleKey) {
+        this.parentRepo = parentRepo;
         this.id = eventID;
         this.subtitleKey = subtitleKey;
     }
diff --git a/src/main/java/net/minecraft/client/util/debug/Debug.java b/src/main/java/net/minecraft/client/util/debug/Debug.java
index 30d5acd52..7afeeaf8f 100644
--- a/src/main/java/net/minecraft/client/util/debug/Debug.java
+++ b/src/main/java/net/minecraft/client/util/debug/Debug.java
@@ -1,12 +1,15 @@
 package net.minecraft.client.util.debug;
 
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 public class Debug {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public static boolean enable = true;
 	
 	static final Profiler baseProfiler = new Profiler("base", null);
@@ -31,7 +34,7 @@ public class Debug {
 	
 	public static void reset() {
 		if(currentProfiler != baseProfiler) {
-			System.out.println("Invalid profiler state: " +(currentProfiler != null ? currentProfiler.name : null));
+            LOGGER.warn("Invalid profiler state: {}", currentProfiler != null ? currentProfiler.name : null);
 			currentProfiler = baseProfiler;
 		}
 		reset(currentProfiler);
diff --git a/src/main/java/net/minecraft/client/util/debug/DebugRender.java b/src/main/java/net/minecraft/client/util/debug/DebugRender.java
index 999f6a95c..05bdbb1ba 100644
--- a/src/main/java/net/minecraft/client/util/debug/DebugRender.java
+++ b/src/main/java/net/minecraft/client/util/debug/DebugRender.java
@@ -6,7 +6,7 @@ import org.lwjgl.input.Keyboard;
 import org.lwjgl.opengl.Display;
 
 import net.minecraft.client.Minecraft;
-import net.minecraft.client.render.FontRenderer;
+import net.minecraft.client.render.Font;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.util.debug.Debug.Profiler;
 import net.minecraft.core.util.helper.MathHelper;
@@ -64,7 +64,7 @@ public class DebugRender {
 		resetFrametimes();
 	}
 	
-	public static void render(FontRenderer fontRenderer) {
+	public static void render(Font font) {
 		frametimes[pos] = selectedProfiler.time;
 		baseframetimes[pos] = Debug.baseProfiler.time;
 		pos++;
@@ -117,10 +117,10 @@ public class DebugRender {
 		
 		int fps = Debug.getFps();
 		if(fps >= 0) {
-			fontRenderer.drawString("fps: " + fps, x1, y1 - 2 * lineHeight, 0xFFFFFFFF);
+			font.drawString("fps: " + fps, x1, y1 - 2 * lineHeight, 0xFFFFFFFF);
 		}
-		fontRenderer.drawString("avg: " + (getAvgTime(frametimes) / 1000.0) + " ms", x1, y1 - lineHeight, 0xFFFFFFFF);
-		fontRenderer.drawString(selectedProfiler.name + ": ", x1, y1, 0xFFFFFFFF);
+		font.drawString("avg: " + (getAvgTime(frametimes) / 1000.0) + " ms", x1, y1 - lineHeight, 0xFFFFFFFF);
+		font.drawString(selectedProfiler.name + ": ", x1, y1, 0xFFFFFFFF);
 		for(int i=0; i < selectedProfiler.allProfilers.size(); i++) {
 			Profiler profiler = selectedProfiler.allProfilers.get(i);
 
@@ -128,7 +128,7 @@ public class DebugRender {
 			if(i == selection) {
 				color = 0xFF00FFFF;
 			}
-			fontRenderer.drawString(i + ": " + profiler.name, x1, y1 + (i + 1) * lineHeight, color);
+			font.drawString(i + ": " + profiler.name, x1, y1 + (i + 1) * lineHeight, color);
 		}
 		glEnable(GL_ALPHA_TEST);
 	}
diff --git a/src/main/java/net/minecraft/client/util/dispatch/Dispatcher.java b/src/main/java/net/minecraft/client/util/dispatch/Dispatcher.java
index 8aba76169..6ab13035e 100644
--- a/src/main/java/net/minecraft/client/util/dispatch/Dispatcher.java
+++ b/src/main/java/net/minecraft/client/util/dispatch/Dispatcher.java
@@ -5,24 +5,33 @@ import java.util.Map;
 
 // T = source class
 // U = dispatched class
-public abstract class Dispatcher<T, U>
-{
+public abstract class Dispatcher<T, U> {
     protected final Map<T, U> dispatches;
 
-    public Dispatcher()
-    {
+    public Dispatcher() {
         dispatches = new HashMap<>();
     }
 
-    public void addDispatch(T item, U dispatchable)
-    {
-        dispatches.put(item, dispatchable);
+    /**
+     * Adds a new entry to the dispatcher.
+     * @param key The item to use as a key.
+     * @param value The item that looking up the key will produce.
+     */
+    public void addDispatch(T key, U value) {
+        dispatches.put(key, value);
     }
 
-    public U getDispatch(T item)
-    {
-        return dispatches.getOrDefault(item, getDefault());
+    /**
+     * Fetches an entry from the dispatcher.
+     * @param key The key to look up.
+     * @return The value from the dispatcher, or a default value generated by getDefault().
+     */
+    public U getDispatch(T key) {
+        return dispatches.getOrDefault(key, getDefault());
     }
 
+    /**
+     * Returns the default value for the dispatcher.
+     */
     protected abstract U getDefault();
 }
diff --git a/src/main/java/net/minecraft/client/util/helper/GuiItemDragHandler.java b/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java
similarity index 94%
rename from src/main/java/net/minecraft/client/util/helper/GuiItemDragHandler.java
rename to src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java
index 4f2d26f4c..a179ad506 100644
--- a/src/main/java/net/minecraft/client/util/helper/GuiItemDragHandler.java
+++ b/src/main/java/net/minecraft/client/util/helper/ItemDragHandler.java
@@ -11,17 +11,17 @@ import org.lwjgl.input.Keyboard;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiContainer;
-import net.minecraft.client.gui.GuiRenderItem;
+import net.minecraft.client.gui.container.AbstractContainerScreen;
+import net.minecraft.client.gui.ItemElement;
 import net.minecraft.core.InventoryAction;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.slot.Slot;
 
-public class GuiItemDragHandler extends Gui {
+public class ItemDragHandler extends Gui {
 	
 	public final Minecraft mc;
-	public final GuiContainer container;
-	public final GuiRenderItem guiRenderItem;
+	public final AbstractContainerScreen container;
+	public final ItemElement itemElement;
 	
 	private int renderOffsetX;
 	private int renderOffsetY;
@@ -45,10 +45,10 @@ public class GuiItemDragHandler extends Gui {
 	private boolean lastClickHoldingItem = false;
 	private boolean doubleClick = false;
 	
-	public GuiItemDragHandler(Minecraft minecraft, GuiContainer container, GuiRenderItem renderItem) {
+	public ItemDragHandler(Minecraft minecraft, AbstractContainerScreen screen, ItemElement itemElement) {
 		this.mc = minecraft;
-		this.container = container;
-		this.guiRenderItem = renderItem;
+		this.container = screen;
+		this.itemElement = itemElement;
 	}
 	
 	public void drawScreen(int mouseX, int mouseY, float partialTicks) {
@@ -123,7 +123,7 @@ public class GuiItemDragHandler extends Gui {
 		if(stack != null) {
 			renderItemStack.stackSize = Math.min(renderItemStack.getMaxStackSize(), renderItemStack.stackSize + stack.stackSize);
 		}
-		guiRenderItem.render(renderItemStack, slot.x, slot.y);
+		itemElement.render(renderItemStack, slot.x, slot.y);
 	}
 	
 	public void mouseEvent(final int x, final int y, int button, boolean pressed) {
diff --git a/src/main/java/net/minecraft/client/util/helper/Textures.java b/src/main/java/net/minecraft/client/util/helper/Textures.java
index 923ae46fe..9de2b4a8d 100644
--- a/src/main/java/net/minecraft/client/util/helper/Textures.java
+++ b/src/main/java/net/minecraft/client/util/helper/Textures.java
@@ -16,6 +16,7 @@ import java.util.List;
 
 import javax.imageio.ImageIO;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.util.helper.Buffer;
 import org.lwjgl.opengl.GL12;
 
@@ -23,9 +24,10 @@ import com.b100.utils.ImageUtils;
 
 import net.minecraft.client.GLAllocation;
 import net.minecraft.client.render.OpenGLHelper;
+import org.slf4j.Logger;
 
 public class Textures {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public static BufferedImage missingTexture;
 	
 	static {
@@ -107,25 +109,27 @@ public class Textures {
 		File folder = new File("dumpTextures");
 		if(folder.exists()) {
 			File[] files = folder.listFiles();
-			for(int i=0; i < files.length; i++) {
-				files[i].delete();
+			if (files != null) {
+				for (File file : files) {
+					file.delete();
+				}
 			}
 		}
 		
 		OpenGLHelper.checkError("pre texture dump");
-		
-		System.out.println("Dump Textures...");
+
+		LOGGER.info("Dump Textures...");
 		
 		List<Integer> textureList = GLAllocation.textureNames;
 		for(int i=0; i < textureList.size(); i++) {
 			Integer tex = textureList.get(i);
-			
-			System.out.println("Tex: " + tex);
+
+            LOGGER.debug("Tex: {}", tex);
 			
 			glBindTexture(GL_TEXTURE_2D, tex);
 			int maxLevel = glGetTexParameteri(GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL);
-			
-			System.out.println("Max Level: " + maxLevel);
+
+            LOGGER.debug("Max Level: {}", maxLevel);
 			
 			for(int level = 0; level <= maxLevel; level++) {
 				int w = glGetTexLevelParameteri(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH);
@@ -136,8 +140,8 @@ public class Textures {
 				if(w == 0 || h == 0) {
 					break;
 				}
-				
-				System.out.println("Level " + level + ": " + w + " x " + h);
+
+                LOGGER.debug("Level {}: {} x {}", level, w, h);
 				
 				int size = w * h * 4;
 				Buffer.checkBufferSize(size);
@@ -153,12 +157,12 @@ public class Textures {
 					ImageUtils.saveExternalImage(getImage(buffer, w, h, false, false), new File(folder, "tex"+tex+"-level"+level+"-opaque.png"));
 
 				}else {
-					System.out.println("Cannot get pixel data");
+					LOGGER.warn("Cannot get pixel data");
 				}
 			}
 		}
-		
-		System.out.println("Dumped textures into " + folder.getAbsolutePath());
+
+        LOGGER.info("Dumped textures into {}", folder.getAbsolutePath());
 		OpenGLHelper.checkError("texture dump");
 	}
 	
@@ -168,7 +172,7 @@ public class Textures {
 			file.createNewFile();
 			ImageIO.write(image, "png", file);
 		}catch (Exception e) {
-			e.printStackTrace();
+            LOGGER.error("Failed to save image to file '{}'!", file.getPath(), e);
 		}
 	}
 	
@@ -182,8 +186,8 @@ public class Textures {
 		int h = glGetTexLevelParameteri(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT);
 		
 		if(w == 0 || h == 0) return null;
-		
-		System.out.println("Texture "+texture+" Size: "+w+" x "+h);
+
+        LOGGER.debug("Texture {} Size: {} x {}", texture, w, h);
 		
 		Buffer.reset();
 		Buffer.checkBufferSize(w * h * 16);
diff --git a/src/main/java/net/minecraft/client/world/WorldBlockPositionType.java b/src/main/java/net/minecraft/client/world/WorldBlockPositionType.java
deleted file mode 100644
index dabe74d91..000000000
--- a/src/main/java/net/minecraft/client/world/WorldBlockPositionType.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package net.minecraft.client.world;
-
-
-// Referenced classes of package net.minecraft.src:
-//            WorldClient
-
-class WorldBlockPositionType
-{
-    int x;
-    int y;
-    int z;
-    int delayTicks;
-    int blockId;
-    int metadata;
-    final WorldClient worldClient; /* synthetic field */
-
-    public WorldBlockPositionType(WorldClient worldclient, int x, int y, int z, int blockId, int metadata) {
-        this.worldClient = worldclient;
-        this.x = x;
-        this.y = y;
-        this.z = z;
-        this.delayTicks = 80;
-        this.blockId = blockId;
-        this.metadata = metadata;
-    }
-}
diff --git a/src/main/java/net/minecraft/client/world/WorldClient.java b/src/main/java/net/minecraft/client/world/WorldClient.java
index 8b8c932a3..a3d361827 100644
--- a/src/main/java/net/minecraft/client/world/WorldClient.java
+++ b/src/main/java/net/minecraft/client/world/WorldClient.java
@@ -69,6 +69,10 @@ public class WorldClient extends World {
             }
         }
 		updateSeasonAndLight();
+        if(rainbowTicks > 0)
+        {
+            rainbowTicks--;
+        }
     }
 
     public void processPackets() {
@@ -201,13 +205,13 @@ public class WorldClient extends World {
     }
 
     @Override
-	public boolean setBlockMetadata(int i, int j, int k, int l)
+	public boolean setBlockMetadata(int x, int y, int z, int meta)
     {
-        int i1 = getBlockId(i, j, k);
-        int j1 = getBlockMetadata(i, j, k);
-        if(super.setBlockMetadata(i, j, k, l))
+        int blockID = getBlockId(x, y, z);
+        int currentMeta = getBlockMetadata(x, y, z);
+        if(super.setBlockMetadata(x, y, z, meta))
         {
-            positionTypesList.add(new WorldBlockPositionType(this, i, j, k, i1, j1));
+            positionTypesList.add(new WorldBlockPositionType(x, y, z, blockID, currentMeta));
             return true;
         } else
         {
@@ -216,13 +220,13 @@ public class WorldClient extends World {
     }
 
     @Override
-	public boolean setBlockAndMetadata(int i, int j, int k, int l, int i1)
+	public boolean setBlockAndMetadata(int x, int y, int z, int id, int meta)
     {
-        int j1 = getBlockId(i, j, k);
-        int k1 = getBlockMetadata(i, j, k);
-        if(super.setBlockAndMetadata(i, j, k, l, i1))
+        int blockId = getBlockId(x, y, z);
+        int blockMeta = getBlockMetadata(x, y, z);
+        if(super.setBlockAndMetadata(x, y, z, id, meta))
         {
-            positionTypesList.add(new WorldBlockPositionType(this, i, j, k, j1, k1));
+            positionTypesList.add(new WorldBlockPositionType(x, y, z, blockId, blockMeta));
             return true;
         } else
         {
@@ -237,7 +241,7 @@ public class WorldClient extends World {
         int meta = getBlockMetadata(x, y, z);
         if(super.setBlock(x, y, z, id))
         {
-            positionTypesList.add(new WorldBlockPositionType(this, x, y, z, blockId, meta));
+            positionTypesList.add(new WorldBlockPositionType(x, y, z, blockId, meta));
             return true;
         } else
         {
@@ -268,4 +272,23 @@ public class WorldClient extends World {
     public void sendGlobalMessage(String message){
 
     }
+
+    static class WorldBlockPositionType
+    {
+        int x;
+        int y;
+        int z;
+        int delayTicks;
+        int blockId;
+        int metadata;
+
+        public WorldBlockPositionType(int x, int y, int z, int blockId, int metadata) {
+            this.x = x;
+            this.y = y;
+            this.z = z;
+            this.delayTicks = 80;
+            this.blockId = blockId;
+            this.metadata = metadata;
+        }
+    }
 }
diff --git a/src/main/java/net/minecraft/client/world/chunk/provider/ChunkProviderStatic.java b/src/main/java/net/minecraft/client/world/chunk/provider/ChunkProviderStatic.java
index eb7aaa0e8..d29bd8e4d 100644
--- a/src/main/java/net/minecraft/client/world/chunk/provider/ChunkProviderStatic.java
+++ b/src/main/java/net/minecraft/client/world/chunk/provider/ChunkProviderStatic.java
@@ -1,5 +1,7 @@
 package net.minecraft.client.world.chunk.provider;
 
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
 import net.minecraft.core.world.ProgressListener;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.chunk.Chunk;
@@ -7,6 +9,7 @@ import net.minecraft.core.world.chunk.EmptyChunk;
 import net.minecraft.core.world.chunk.IChunkLoader;
 import net.minecraft.core.world.chunk.provider.IChunkProvider;
 import net.minecraft.core.world.generate.chunk.ChunkGenerator;
+import org.slf4j.Logger;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -18,12 +21,24 @@ import java.util.Arrays;
 public class ChunkProviderStatic
     implements IChunkProvider
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private final Chunk blankChunk;
+    public ChunkGenerator chunkGenerator;
+    private final IChunkLoader chunkLoader;
+    private final Chunk[] chunks;
+    private final World worldObj;
+    int lastQueriedChunkXPos;
+    int lastQueriedChunkZPos;
+    private Chunk lastQueriedChunk;
+    private int curChunkX;
+    private int curChunkY;
+
 
     public ChunkProviderStatic(World world, IChunkLoader ichunkloader, ChunkGenerator chunkGenerator)
     {
         chunks = new Chunk[1024];
-        lastQueriedChunkXPos = 0xc4653601;
-        lastQueriedChunkZPos = 0xc4653601;
+        lastQueriedChunkXPos = Integer.MIN_VALUE;
+        lastQueriedChunkZPos = Integer.MIN_VALUE;
         blankChunk = new EmptyChunk(world, 0, 0);
         worldObj = world;
         chunkLoader = ichunkloader;
@@ -170,7 +185,7 @@ public class ChunkProviderStatic
         return chunks[i1];
     }
 
-    private Chunk loadChunk(int i, int j)
+    private Chunk loadChunk(int chunkX, int chunkZ)
     {
         if(chunkLoader == null)
         {
@@ -178,7 +193,7 @@ public class ChunkProviderStatic
         }
         try
         {
-            Chunk chunk = chunkLoader.loadChunk(worldObj, i, j);
+            Chunk chunk = chunkLoader.loadChunk(worldObj, chunkX, chunkZ);
             if(chunk != null)
             {
                 chunk.lastSaveTime = worldObj.getWorldTime();
@@ -187,7 +202,7 @@ public class ChunkProviderStatic
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Error loading chunk at X:{}, Z:{}", chunkX, chunkZ, exception);
         }
         return blankChunk;
     }
@@ -203,9 +218,9 @@ public class ChunkProviderStatic
             chunk.lastSaveTime = worldObj.getWorldTime();
             chunkLoader.saveChunk(worldObj, chunk);
         }
-        catch(IOException ioexception)
+        catch(IOException e)
         {
-            ioexception.printStackTrace();
+            LOGGER.error("Error saving chunk at X:{}, Z:{}", chunk.xPosition, chunk.zPosition, e);
         }
     }
 
@@ -271,7 +286,7 @@ public class ChunkProviderStatic
     {
         return false;
     }
-    
+
     @Override
     public void unloadAllChunks()
     {
@@ -292,21 +307,10 @@ public class ChunkProviderStatic
     @Override
     public String getInfoString()
     {
-        return (new StringBuilder()).append("ChunkCache: ").append(chunks.length).toString();
+        return "ChunkCache: " + chunks.length;
     }
 
     public IChunkLoader getChunkLoader() {
         return chunkLoader;
     }
-
-    private Chunk blankChunk;
-    public ChunkGenerator chunkGenerator;
-    private IChunkLoader chunkLoader;
-    private Chunk chunks[];
-    private World worldObj;
-    int lastQueriedChunkXPos;
-    int lastQueriedChunkZPos;
-    private Chunk lastQueriedChunk;
-    private int curChunkX;
-    private int curChunkY;
 }
diff --git a/src/main/java/net/minecraft/core/MinecraftAccessor.java b/src/main/java/net/minecraft/core/MinecraftAccessor.java
index 289efaf3d..d2b5e8084 100644
--- a/src/main/java/net/minecraft/core/MinecraftAccessor.java
+++ b/src/main/java/net/minecraft/core/MinecraftAccessor.java
@@ -22,4 +22,5 @@ public interface MinecraftAccessor
     default boolean isFullbrightEnabled() {
     	return false;
     }
+
 }
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/core/achievement/Achievements.java b/src/main/java/net/minecraft/core/achievement/Achievements.java
index f6448eaab..244e95ecc 100644
--- a/src/main/java/net/minecraft/core/achievement/Achievements.java
+++ b/src/main/java/net/minecraft/core/achievement/Achievements.java
@@ -1,16 +1,19 @@
 package net.minecraft.core.achievement;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.gui.achievements.data.AchievementPages;
+import net.minecraft.core.Global;
 import net.minecraft.core.block.Blocks;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.util.collection.NamespaceID;
+import org.slf4j.Logger;
 
 import java.util.ArrayList;
 import java.util.List;
 
 public abstract class Achievements
 {
-    
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static List<Achievement> achievementList = new ArrayList<>();
     public static Achievement OPEN_INVENTORY =
         new Achievement(new NamespaceID("minecraft", "open_inventory"), "openInventory", 0, 0, Items.BOOK, null)
@@ -202,6 +205,6 @@ public abstract class Achievements
         if (hasInit) return;
         hasInit = true;
         AchievementPages.init();
-        System.out.println(achievementList.size() + " Achievements");
+        LOGGER.info("{} Achievements", achievementList.size());
     }
 }
diff --git a/src/main/java/net/minecraft/core/achievement/stat/StatsCounter.java b/src/main/java/net/minecraft/core/achievement/stat/StatsCounter.java
index 7508c0be3..e6da28072 100644
--- a/src/main/java/net/minecraft/core/achievement/stat/StatsCounter.java
+++ b/src/main/java/net/minecraft/core/achievement/stat/StatsCounter.java
@@ -5,6 +5,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
+import java.util.UUID;
 
 import com.b100.json.JsonParser;
 import com.b100.json.element.JsonArray;
@@ -12,15 +13,18 @@ import com.b100.json.element.JsonElement;
 import com.b100.json.element.JsonEntry;
 import com.b100.json.element.JsonObject;
 import com.b100.utils.FileUtils;
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
 import net.minecraft.core.MD5String;
 import net.minecraft.core.achievement.Achievement;
 import net.minecraft.core.player.Session;
 import net.minecraft.core.util.HardIllegalArgumentException;
 import net.minecraft.core.util.collection.NamespaceID;
 import org.jetbrains.annotations.Unmodifiable;
+import org.slf4j.Logger;
 
 public class StatsCounter {
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private final Map<Stat, Integer> sessionStats; // Local copy of stats used by the client
 	private final Map<Stat, Integer> savedStats;
 	private boolean modified;
@@ -132,7 +136,7 @@ public class StatsCounter {
 				if (file.getName().startsWith("stats_") && file.getName().endsWith(".dat")) {
 					File destination = new File(statsFolder, file.getName());
 					if (!destination.exists()) {
-						System.out.println("Relocating " + file.getName());
+                        LOGGER.info("Relocating {}", file.getName());
 						file.renameTo(destination);
 					}
 				}
@@ -162,31 +166,31 @@ public class StatsCounter {
 						stat = StatList.StatConverter.getStatFromDeprecatedID(Integer.parseInt(statId));
 					}
 				} catch (HardIllegalArgumentException | NumberFormatException e){
-					e.printStackTrace();
+                    LOGGER.warn("Exception parsing statID: '{}'", statId, e);
 					continue;
 				}
 
 
 				if(stat == null) {
-					System.out.println(statId + " is not a valid stat");
+                    LOGGER.warn("{} is not a valid stat", statId);
 					continue;
 				}
 				map.put(stat, value);
 			}
 		} catch (Exception e) {
-			e.printStackTrace();
+			LOGGER.error("Exception while reading stats string!", e);
 		}
 		return map;
 	}
 
-	public static String getStatFileContentString(String username, String sessionID, Map<Stat, Integer> map) {
+	public static String getStatFileContentString(UUID uuid, String sessionID, Map<Stat, Integer> map) {
 		StringBuilder displayString = new StringBuilder();
 		StringBuilder checkSumString = new StringBuilder();
 		boolean flag = true;
 		displayString.append("{\r\n");
-		if (username != null && sessionID != null) {
+		if (uuid != null && sessionID != null) {
 			displayString.append("  \"user\":{\r\n");
-			displayString.append("    \"name\":\"").append(username).append("\",\r\n");
+			displayString.append("    \"uuid\":\"").append(uuid).append("\",\r\n");
 			displayString.append("    \"sessionid\":\"").append(sessionID).append("\"\r\n");
 			displayString.append("  },\r\n");
 		}
diff --git a/src/main/java/net/minecraft/core/achievement/stat/StatsSyncher.java b/src/main/java/net/minecraft/core/achievement/stat/StatsSyncher.java
index fe8535eb8..fee7b6d4c 100644
--- a/src/main/java/net/minecraft/core/achievement/stat/StatsSyncher.java
+++ b/src/main/java/net/minecraft/core/achievement/stat/StatsSyncher.java
@@ -1,13 +1,15 @@
 package net.minecraft.core.achievement.stat;
 
 import com.b100.utils.StringUtils;
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.player.Session;
+import org.slf4j.Logger;
 
 import java.io.*;
 import java.util.Map;
 
 public class StatsSyncher {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     private volatile boolean busy = false;
     private volatile Map<Stat, Integer> queuedLocalStatsChanges;
     private volatile Map<Stat, Integer> queuedSavedStatsChanges;
@@ -20,27 +22,29 @@ public class StatsSyncher {
     private final File statsFileOld;
     private final Session session;
     private int saveTimer;
-    private int fetchChangesTimer; // Im making a sorta longshot guess but I think this is the remnant of an unused timer to retrieve stat changes from the server
+    private int fetchChangesTimer; // I'm making a sorta longshot guess, but I think this is the remnant of an unused timer to retrieve stat changes from the server
 
     public StatsSyncher(Session session, StatsCounter statsCounter, File statsDir) {
         queuedLocalStatsChanges = null;
         queuedSavedStatsChanges = null;
         saveTimer = 0;
         fetchChangesTimer = 0;
-        unsentStatsFile = new File(statsDir, "stats_" + session.username.toLowerCase() + "_unsent.dat");
-        statsFile = new File(statsDir, "stats_" + session.username.toLowerCase() + ".dat");
-        unsentStatsFileOld = new File(statsDir, "stats_" + session.username.toLowerCase() + "_unsent.old");
-        statsFileOld = new File(statsDir, "stats_" + session.username.toLowerCase() + ".old");
-        unsentStatsFileTemp = new File(statsDir, "stats_" + session.username.toLowerCase() + "_unsent.tmp");
-        statsFileTemp = new File(statsDir, "stats_" + session.username.toLowerCase() + ".tmp");
-        if (!session.username.toLowerCase().equals(session.username)) {
-            renameFile(statsDir, "stats_" + session.username + "_unsent.dat", unsentStatsFile);
-            renameFile(statsDir, "stats_" + session.username + ".dat", statsFile);
-            renameFile(statsDir, "stats_" + session.username + "_unsent.old", unsentStatsFileOld);
-            renameFile(statsDir, "stats_" + session.username + ".old", statsFileOld);
-            renameFile(statsDir, "stats_" + session.username + "_unsent.tmp", unsentStatsFileTemp);
-            renameFile(statsDir, "stats_" + session.username + ".tmp", statsFileTemp);
-        }
+
+        statsFile =           (new File(statsDir, "stats_" + session.uuid + ".dat"));
+        statsFileOld =        (new File(statsDir, "stats_" + session.uuid + ".old"));
+        statsFileTemp =       (new File(statsDir, "stats_" + session.uuid + ".tmp"));
+        unsentStatsFile =     (new File(statsDir, "stats_" + session.uuid + "_unsent.dat"));
+        unsentStatsFileOld =  (new File(statsDir, "stats_" + session.uuid + "_unsent.old"));
+        unsentStatsFileTemp = (new File(statsDir, "stats_" + session.uuid + "_unsent.tmp"));
+
+        // Remap pre-UUID stats to new UUID files
+        new File(statsDir, "stats_" + session.username.toLowerCase() + ".dat").renameTo(statsFile);
+        new File(statsDir, "stats_" + session.username.toLowerCase() + ".old").renameTo(statsFileOld);
+        new File(statsDir, "stats_" + session.username.toLowerCase() + ".tmp").renameTo(statsFileTemp);
+        new File(statsDir, "stats_" + session.username.toLowerCase() + "_unsent.dat").renameTo(unsentStatsFile);
+        new File(statsDir, "stats_" + session.username.toLowerCase() + "_unsent.old").renameTo(unsentStatsFileOld);
+        new File(statsDir, "stats_" + session.username.toLowerCase() + "_unsent.tmp").renameTo(unsentStatsFileTemp);
+
         this.statsCounter = statsCounter;
         this.session = session;
         if (unsentStatsFile.exists()) {
@@ -49,10 +53,10 @@ public class StatsSyncher {
         startRetrievalThread();
     }
 
-    private void renameFile(File file, String s, File file1) {
-        File file2 = new File(file, s);
-        if (file2.exists() && !file2.isDirectory() && !file1.exists()) {
-            file2.renameTo(file1);
+    private void renameFile(File parent, String child, File fileToRename) {
+        File destFile = new File(parent, child);
+        if (destFile.exists() && !destFile.isDirectory() && !fileToRename.exists()) {
+            destFile.renameTo(fileToRename);
         }
     }
 
@@ -74,7 +78,7 @@ public class StatsSyncher {
         try {
             return StatsCounter.readStatsFromString(StringUtils.getFileContentAsString(statsFile));
         } catch (Exception e) {
-            e.printStackTrace();
+            LOGGER.warn("Failed to read stats from file '{}'!", statsFile.getPath(), e);
         }
         return null;
     }
@@ -82,7 +86,7 @@ public class StatsSyncher {
     private void saveStats(Map<Stat, Integer> map, File statsFile, File tempStatsFile, File oldStatsFile)
         throws IOException {
         try (PrintWriter writer = new PrintWriter(new FileWriter(tempStatsFile, false))) {
-            writer.print(StatsCounter.getStatFileContentString(session.username, "local", map));
+            writer.print(StatsCounter.getStatFileContentString(session.uuid, "local", map));
         }
         if (oldStatsFile.exists()) {
             oldStatsFile.delete();
@@ -107,7 +111,7 @@ public class StatsSyncher {
                         queuedLocalStatsChanges = readStatsFromFile(statsFile, statsFileTemp, statsFileOld);
                     }
                 } catch (Exception exception) {
-                    exception.printStackTrace();
+                    LOGGER.error("Unexpected exception in retrieval thread!", exception);
                 } finally {
                     busy = false;
                 }
@@ -125,7 +129,7 @@ public class StatsSyncher {
                 try {
                     saveStats(mapToSave, unsentStatsFile, unsentStatsFileTemp, unsentStatsFileOld);
                 } catch (Exception exception) {
-                    exception.printStackTrace();
+                    LOGGER.error("Unexpected exception in saving thread!", exception);
                 } finally {
                     busy = false;
                 }
@@ -139,7 +143,7 @@ public class StatsSyncher {
             try {
                 Thread.sleep(100L);
             } catch (InterruptedException interrupt) {
-                interrupt.printStackTrace();
+                LOGGER.warn("Interrupted!", interrupt);
             }
         }
 
@@ -147,7 +151,7 @@ public class StatsSyncher {
         try {
             saveStats(map, unsentStatsFile, unsentStatsFileTemp, unsentStatsFileOld);
         } catch (Exception exception) {
-            exception.printStackTrace();
+            LOGGER.error("Exception saving stats!", exception);
         } finally {
             busy = false;
         }
diff --git a/src/main/java/net/minecraft/core/block/BaseLeavesBlock.java b/src/main/java/net/minecraft/core/block/BaseLeavesBlock.java
index 2d4bc69bc..eaa111485 100644
--- a/src/main/java/net/minecraft/core/block/BaseLeavesBlock.java
+++ b/src/main/java/net/minecraft/core/block/BaseLeavesBlock.java
@@ -187,7 +187,7 @@ public abstract class BaseLeavesBlock extends Block
     
     private void removeLeaves(World world, int i, int j, int k)
     {
-        dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null);
+        dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null, null);
         world.setBlockWithNotify(i, j, k, 0);
     }
 
diff --git a/src/main/java/net/minecraft/core/block/BlastFurnaceBlock.java b/src/main/java/net/minecraft/core/block/BlastFurnaceBlock.java
index ab6f38d49..2e3f06200 100644
--- a/src/main/java/net/minecraft/core/block/BlastFurnaceBlock.java
+++ b/src/main/java/net/minecraft/core/block/BlastFurnaceBlock.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.block;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.entity.BlastFurnaceBlockEntity;
@@ -8,6 +9,7 @@ import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 import java.util.Random;
 
@@ -19,6 +21,7 @@ import java.util.Random;
 
 public class BlastFurnaceBlock extends FurnaceBlock
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
 
 	public BlastFurnaceBlock(String key, String namespaceId, int id, boolean flag)
     {
@@ -45,7 +48,7 @@ public class BlastFurnaceBlock extends FurnaceBlock
     {
         if (!world.isClientSide) {
             BlastFurnaceBlockEntity tileentityblastfurnace = (BlastFurnaceBlockEntity) world.getBlockEntity(x, y, z);
-            player.displayGUIFurnace(tileentityblastfurnace);
+            player.displayFurnaceScreen(tileentityblastfurnace);
         }
         return true;
     }
@@ -87,14 +90,14 @@ public class BlastFurnaceBlock extends FurnaceBlock
 
 	public static void updateFurnaceBlockState(boolean lit, World world, int x, int y, int z) {
 		int meta = world.getBlockMetadata(x, y, z);
-		BlockEntity tileentity = world.getBlockEntity(x, y, z);
-		if(tileentity == null) {
+		BlockEntity blockEntity = world.getBlockEntity(x, y, z);
+		if(blockEntity == null) {
 			String msg = "Blast Furnace is missing Tile Entity at x: "+x+" y: "+y+" z: "+z+", block will be removed!";
 			if(Global.BUILD_CHANNEL.isUnstableBuild()) {
 				throw new RuntimeException(msg);
 			}
 			world.setBlockWithNotify(x, y, z, 0);
-			System.out.println(msg);
+            LOGGER.warn(msg);
 			return;
 		}
 		keepFurnaceInventory = true;
@@ -105,8 +108,8 @@ public class BlastFurnaceBlock extends FurnaceBlock
 		}
 		keepFurnaceInventory = false;
 		world.setBlockMetadataWithNotify(x, y, z, meta);
-		tileentity.validate();
-		world.setBlockTileEntity(x, y, z, tileentity);
+		blockEntity.validate();
+		world.setBlockTileEntity(x, y, z, blockEntity);
 	}
 
     @Override
diff --git a/src/main/java/net/minecraft/core/block/Block.java b/src/main/java/net/minecraft/core/block/Block.java
index 23e918c3f..068207e88 100644
--- a/src/main/java/net/minecraft/core/block/Block.java
+++ b/src/main/java/net/minecraft/core/block/Block.java
@@ -583,36 +583,36 @@ public class Block
         return false;
     }
 
-    public void harvestBlock(World world, Player entityplayer, int x, int y, int z, int meta, BlockEntity blockEntity)
+    public void harvestBlock(World world, Player player, int x, int y, int z, int meta, BlockEntity blockEntity)
     {
-		entityplayer.addStat(getStat(StatList.STAT_MINED), 1);
+    	player.addStat(getStat(StatList.STAT_MINED), 1);
 
-		ItemStack heldItemStack = entityplayer.inventory.getCurrentItem();
+		ItemStack heldItemStack = player.inventory.getCurrentItem();
 		Item heldItem = heldItemStack != null ? Item.itemsList[heldItemStack.itemID] : null;
 
         if (heldItem != null)
         {
-            if (heldItem.isSilkTouch() && entityplayer.canHarvestBlock(this))
+            if (heldItem.isSilkTouch() && player.canHarvestBlock(this))
             {
-                dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x, y, z, meta, blockEntity);
+                dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x, y, z, meta, blockEntity, player);
                 return;
             }
             else if (heldItem instanceof ToolShearsItem && (this.hasTag(BlockTags.SHEARS_DO_SILK_TOUCH) || this.hasTag(BlockTags.MINEABLE_BY_SHEARS)))
             {
                 ToolShearsItem heldShears = (ToolShearsItem) heldItem;
-                dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x, y, z, meta, blockEntity);
-                heldShears.onBlockSheared(entityplayer, heldItemStack);
+                dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x, y, z, meta, blockEntity, player);
+                heldShears.onBlockSheared(player, heldItemStack);
                 return;
             }
         }
 
-        if (entityplayer.canHarvestBlock(this))
+        if (player.canHarvestBlock(this))
         {
-            dropBlockWithCause(world, EnumDropCause.PROPER_TOOL, x, y, z, meta, blockEntity);
+            dropBlockWithCause(world, EnumDropCause.PROPER_TOOL, x, y, z, meta, blockEntity, player);
         }
         else
         {
-            dropBlockWithCause(world, EnumDropCause.IMPROPER_TOOL, x, y, z, meta, blockEntity);
+            dropBlockWithCause(world, EnumDropCause.IMPROPER_TOOL, x, y, z, meta, blockEntity, player);
         }
 	}
 
@@ -621,37 +621,37 @@ public class Block
         return asItem().getStat(statID);
     }
 
-    public void dropBlockWithCause(World world, EnumDropCause cause, int x, int y, int z, int meta, BlockEntity blockEntity)
-    {
-        if (world.isClientSide) return;
-
-        ItemStack[] drops = getBreakResult(world, cause, x, y, z, meta, blockEntity);
-        if (dropOverride > 0){
-            drops = new ItemStack[]{Item.itemsList[dropOverride].getDefaultStack()};
-        }
-        if (drops != null && drops.length > 0)
-        {
-            for (ItemStack drop : drops)
-            {
-                if (drop != null)
-                {
-                	if(ItemEntity.enableItemClumping)
-                	{
-                		world.dropItem(x, y, z, drop.copy());
-                	}
-                	else
-                	{
-                        for (int i = 0; i < drop.stackSize; i++)
-                        {
-                        	ItemStack drop1 = drop.copy();
-                        	drop1.stackSize = 1;
-                            world.dropItem(x, y, z, drop1);
-                        }
-                	}
-                }
-            }
-        }
-    }
+	public void dropBlockWithCause(World world, EnumDropCause cause, int x, int y, int z, int meta, BlockEntity blockEntity, Player player) {
+		if(world.isClientSide)
+			return;
+
+		ItemStack[] drops = getBreakResult(world, cause, x, y, z, meta, blockEntity);
+		if(dropOverride > 0) {
+			drops = new ItemStack[] { Item.itemsList[dropOverride].getDefaultStack() };
+		}
+		if(drops != null && drops.length > 0) {
+			for(ItemStack drop : drops) {
+				if(drop == null) {
+					continue;
+				}
+				if(hasTag(BlockTags.INSTANT_PICKUP) && player != null) {
+					player.inventory.insertItem(drop, true);
+					if(drop.stackSize <= 0) {
+						continue;
+					}
+				}
+				if(ItemEntity.enableItemClumping) {
+					world.dropItem(x, y, z, drop.copy());
+				}else {
+					for(int i = 0; i < drop.stackSize; i++) {
+						ItemStack drop1 = drop.copy();
+						drop1.stackSize = 1;
+						world.dropItem(x, y, z, drop1);
+					}
+				}
+			}
+		}
+	}
 
     public boolean canBlockStay(World world, int x, int y, int z)
     {
diff --git a/src/main/java/net/minecraft/core/block/Blocks.java b/src/main/java/net/minecraft/core/block/Blocks.java
index 2c7adf37e..000a8528f 100644
--- a/src/main/java/net/minecraft/core/block/Blocks.java
+++ b/src/main/java/net/minecraft/core/block/Blocks.java
@@ -541,8 +541,8 @@ public final class Blocks {
         WOOL = new WoolBlock("wool", "minecraft:block/wool", 110).withSound(BlockSounds.CLOTH).withHardness(0.8F).withDisabledNeighborNotifyOnMetadataChange()
             .setBlockItem((b) -> new PaintedBlockItem(b, false))
             .withTags(BlockTags.MINEABLE_BY_SHEARS);
-        ROPE = new RopeBlock("rope", "minecraft:block/rope", 111).withSound(BlockSounds.CLOTH).withHardness(0.0F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.ROPE)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS, BlockTags.CAN_HANG_OFF);
+        ROPE = new RopeBlock("rope", "minecraft:block/rope", 111).withSound(BlockSounds.CLOTH).withHardness(0.01F).withDisabledNeighborNotifyOnMetadataChange().setStatParent(() -> Items.ROPE)
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.NOT_IN_CREATIVE_MENU, BlockTags.PREVENT_MOB_SPAWNS, BlockTags.CAN_HANG_OFF, BlockTags.INSTANT_PICKUP);
 
         BRICK_CLAY = new Block("brick.clay", "minecraft:block/brick_clay", 120, Material.stone).withSound(BlockSounds.STONE).withHardness(3.0F).withBlastResistance(10F).withOverrideColor(MaterialColor.brick)
             .withTags(BlockTags.MINEABLE_BY_PICKAXE);
@@ -775,9 +775,9 @@ public final class Blocks {
             .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
 
         TALLGRASS = new TallGrassBlock("tallgrass", "minecraft:block/tallgrass", 320).setKilledByWeather().withSound(BlockSounds.GRASS).withHardness(0.0F)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.SHEEPS_FAVOURITE_BLOCK);
         TALLGRASS_FERN = new TallGrassBlock("tallgrass.fern", "minecraft:block/tallgrass_fern", 321).setKilledByWeather().withSound(BlockSounds.GRASS).withHardness(0.0F)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.PLANTABLE_IN_JAR);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
         DEADBUSH = new DeadBushBlock("deadbush", "minecraft:block/deadbush", 322).withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.wood)
             .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH, BlockTags.PLANTABLE_IN_JAR);
         SPINIFEX = new SpinifexBlock("spinifex", "minecraft:block/spinifex", 323).withSound(BlockSounds.GRASS).withHardness(0.0F)
@@ -787,22 +787,22 @@ public final class Blocks {
             .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLACE_OVERWRITES, BlockTags.SHEARS_DO_SILK_TOUCH);
 
         FLOWER_YELLOW = new FlowerBlock("flower.yellow", "minecraft:block/flower_yellow", 330).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedYellow)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
         FLOWER_RED = new FlowerBlock("flower.red", "minecraft:block/flower_red", 331).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedRed)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
         FLOWER_PINK = new FlowerBlock("flower.pink", "minecraft:block/flower_pink", 332).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedPink)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
         FLOWER_PURPLE = new FlowerBlock("flower.purple", "minecraft:block/flower_purple", 333).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedPurple)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
         FLOWER_LIGHT_BLUE = new FlowerBlock("flower.lightblue", "minecraft:block/flower_light_blue", 334).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedLightblue)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
         FLOWER_ORANGE = new FlowerBlock("flower.orange", "minecraft:block/flower_orange", 335).setKilledByWeather().setBonemealable().withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedOrange)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.SHEEPS_FAVOURITE_BLOCK);
 
         MUSHROOM_BROWN = new MushroomBlock("mushroom.brown", "minecraft:block/mushroom_brown", 340).withSound(BlockSounds.GRASS).withHardness(0.0F).withLightEmission(0.125F).withOverrideColor(MaterialColor.paintedBrown)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.PIGS_FAVOURITE_BLOCK);
         MUSHROOM_RED = new MushroomBlock("mushroom.red", "minecraft:block/mushroom_red", 341).withSound(BlockSounds.GRASS).withHardness(0.0F).withOverrideColor(MaterialColor.paintedRed)
-            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR);
+            .withTags(BlockTags.BROKEN_BY_FLUIDS, BlockTags.PLANTABLE_IN_JAR, BlockTags.PIGS_FAVOURITE_BLOCK);
 
 
         ORE_COAL_STONE = new CoalOreBlock("ore.coal.stone", "minecraft:block/ore_coal_stone", 350, STONE.id, Material.stone).withSound(BlockSounds.STONE).withHardness(3F).withBlastResistance(5F)
diff --git a/src/main/java/net/minecraft/core/block/ButtonBlock.java b/src/main/java/net/minecraft/core/block/ButtonBlock.java
index 4f98b6905..df7864c37 100644
--- a/src/main/java/net/minecraft/core/block/ButtonBlock.java
+++ b/src/main/java/net/minecraft/core/block/ButtonBlock.java
@@ -165,7 +165,7 @@ public class ButtonBlock extends Block
             }
             if(flag)
             {
-                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, i1, null);
+                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, i1, null, null);
                 world.setBlockWithNotify(x, y, z, 0);
             }
         }
@@ -175,7 +175,7 @@ public class ButtonBlock extends Block
     {
         if(!canPlaceBlockAt(world, x, y, z))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
             return false;
         }
diff --git a/src/main/java/net/minecraft/core/block/CacaoLeavesBlock.java b/src/main/java/net/minecraft/core/block/CacaoLeavesBlock.java
index 6f0b950e8..852753b7d 100644
--- a/src/main/java/net/minecraft/core/block/CacaoLeavesBlock.java
+++ b/src/main/java/net/minecraft/core/block/CacaoLeavesBlock.java
@@ -64,7 +64,7 @@ public class CacaoLeavesBlock extends BaseLeavesBlock implements IBonemealable {
             world.playSoundAtEntity(player, player, "random.pop", 0.2F, 0.5f);
             if(!world.isClientSide)
             {
-                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null);
+                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null, null);
             }
             world.setBlockMetadataWithNotify(x, y, z, decayData);
             world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CACAO.id, tickDelay());
diff --git a/src/main/java/net/minecraft/core/block/CactusBlock.java b/src/main/java/net/minecraft/core/block/CactusBlock.java
index 2e091d5ea..3734e86a6 100644
--- a/src/main/java/net/minecraft/core/block/CactusBlock.java
+++ b/src/main/java/net/minecraft/core/block/CactusBlock.java
@@ -112,7 +112,7 @@ public class CactusBlock extends Block implements IBonemealable
     {
         if(!canBlockStay(world, x, y, z))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/CandleBlock.java b/src/main/java/net/minecraft/core/block/CandleBlock.java
index 4c5b09147..c748c1c70 100644
--- a/src/main/java/net/minecraft/core/block/CandleBlock.java
+++ b/src/main/java/net/minecraft/core/block/CandleBlock.java
@@ -55,7 +55,7 @@ public class CandleBlock extends Block
         boolean flag = !world.canPlaceOnSurfaceOfBlock(x, y - 1, z);
         if(flag)
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/ChestBlock.java b/src/main/java/net/minecraft/core/block/ChestBlock.java
index cf33e6946..ed88a7ba5 100644
--- a/src/main/java/net/minecraft/core/block/ChestBlock.java
+++ b/src/main/java/net/minecraft/core/block/ChestBlock.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.block;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.entity.ChestBlockEntity;
 import net.minecraft.core.block.material.Material;
@@ -12,9 +13,10 @@ import net.minecraft.core.player.inventory.container.CompoundContainer;
 import net.minecraft.core.util.helper.Direction;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 public class ChestBlock extends EntityBlock {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public ChestBlock(String key, String namespaceId, int id, Material material) {
 		super(key, namespaceId, id, material);
 	}
@@ -192,7 +194,7 @@ public class ChestBlock extends EntityBlock {
 	public static void dropChestContent(World world, int x, int y, int z) {
 		ChestBlockEntity tileEntityChest = (ChestBlockEntity) world.getBlockEntity(x, y, z);
 		if(tileEntityChest == null) {
-			System.out.println("Can't drop chest items because tile entity is null at x: "+x+" y:"+y+" z: "+z);
+            LOGGER.warn("Can't drop chest items because tile entity is null at x:{}, y:{}, z:{}", x, y, z);
 			return;
 		}
 		
@@ -249,7 +251,7 @@ public class ChestBlock extends EntityBlock {
 		if(world.isClientSide) return true;
 		
 		checkIfOtherHalfExists(world, x, y, z);
-		player.displayGUIChest(getInventory(world, x, y, z));
+		player.displayContainerScreen(getInventory(world, x, y, z));
 		
 		return true;
 	}
@@ -333,14 +335,15 @@ public class ChestBlock extends EntityBlock {
 	}
 	
 	public static Direction getDirectionFromMeta(int meta) {
-		meta = meta & 3;
-		
-		if(meta == 0) return Direction.NORTH;
-		if(meta == 1) return Direction.EAST;
-		if(meta == 2) return Direction.SOUTH;
-		if(meta == 3) return Direction.WEST;
-		
-		return Direction.NONE;
+		meta = meta & 0b11;
+
+		switch (meta) {
+			case 0: return Direction.NORTH;
+			case 1: return Direction.EAST;
+			case 2: return Direction.SOUTH;
+			case 3: return Direction.WEST;
+			default: return Direction.NONE;
+		}
 	}
 	
 	public static Type getTypeFromMeta(int meta) {
diff --git a/src/main/java/net/minecraft/core/block/ChestBlockPainted.java b/src/main/java/net/minecraft/core/block/ChestBlockPainted.java
index 04c02daa6..c894114c2 100644
--- a/src/main/java/net/minecraft/core/block/ChestBlockPainted.java
+++ b/src/main/java/net/minecraft/core/block/ChestBlockPainted.java
@@ -2,8 +2,10 @@ package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.material.Material;
+import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
 public class ChestBlockPainted extends ChestBlock {
@@ -11,6 +13,11 @@ public class ChestBlockPainted extends ChestBlock {
 	protected ChestBlockPainted(String key, String namespaceId, int id, Material material) {
 		super(key, namespaceId, id, material);
 	}
+	
+	@Override
+	public int getPlacedBlockMetadata(Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
+		return stack.getMetadata();
+	}
 
 	@Override
 	public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, BlockEntity blockEntity)
diff --git a/src/main/java/net/minecraft/core/block/DispenserBlock.java b/src/main/java/net/minecraft/core/block/DispenserBlock.java
index a6e680913..877949a84 100644
--- a/src/main/java/net/minecraft/core/block/DispenserBlock.java
+++ b/src/main/java/net/minecraft/core/block/DispenserBlock.java
@@ -86,7 +86,7 @@ public class DispenserBlock extends RotatableEntityBlock
         } else
         {
             DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity)world.getBlockEntity(x, y, z);
-            player.displayGUIDispenser(tileentitydispenser);
+            player.displayDispenserScreen(tileentitydispenser);
             return true;
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/DoorBlock.java b/src/main/java/net/minecraft/core/block/DoorBlock.java
index 395f38b30..ad251043e 100644
--- a/src/main/java/net/minecraft/core/block/DoorBlock.java
+++ b/src/main/java/net/minecraft/core/block/DoorBlock.java
@@ -15,8 +15,10 @@ import net.minecraft.core.item.tag.ItemTags;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
 import net.minecraft.core.util.phys.Vec3;
+import net.minecraft.core.world.LevelListener;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.WorldSource;
+import net.minecraft.core.world.save.LevelData;
 import org.jetbrains.annotations.Nullable;
 
 // Referenced classes of package net.minecraft.src:
@@ -143,7 +145,7 @@ public class DoorBlock extends Block
         }
         world.setBlockMetadataWithNotify(x, y, z, l ^ 4);
         world.markBlocksDirty(x, y - 1, z, x, y, z);
-        world.playSoundEffect(player, 1003, x, y, z, 0);
+        world.playSoundEffect(player, LevelListener.EVENT_DOOR_SOUND, x, y, z, 0);
         return true;
     }
 
@@ -202,7 +204,7 @@ public class DoorBlock extends Block
             }
             if(!world.canPlaceOnSurfaceOfBlock(x, y - 1, z))
             {
-                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
                 world.setBlockWithNotify(x, y, z, 0);
                 flag = true;
                 if(otherBlock instanceof DoorBlock)
diff --git a/src/main/java/net/minecraft/core/block/FireflyLanternBlock.java b/src/main/java/net/minecraft/core/block/FireflyLanternBlock.java
index 2e71e6a92..4ff4c1864 100644
--- a/src/main/java/net/minecraft/core/block/FireflyLanternBlock.java
+++ b/src/main/java/net/minecraft/core/block/FireflyLanternBlock.java
@@ -122,7 +122,7 @@ public class FireflyLanternBlock extends Block{
     {
         if(!canBlockStay(world, x, y, z))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/FlagBlock.java b/src/main/java/net/minecraft/core/block/FlagBlock.java
index 42c29847b..d107d6e54 100644
--- a/src/main/java/net/minecraft/core/block/FlagBlock.java
+++ b/src/main/java/net/minecraft/core/block/FlagBlock.java
@@ -57,14 +57,14 @@ public class FlagBlock extends EntityBlock {
 	public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xPlaced, double yPlaced) {
 		if (!world.isClientSide) {
 			FlagBlockEntity flag = (FlagBlockEntity) world.getBlockEntity(x, y, z);
-			if (flag.owner != null && !flag.owner.isEmpty() && !player.username.equals(flag.owner)) {
+			if (flag.owner != null && !player.uuid.equals(flag.owner)) {
 				return false;
 			}
 			int heldItemId = player.getHeldItem() != null ? player.getHeldItem().itemID : 0;
 			if(heldItemId == Items.MAP.id || heldItemId == Items.FLAG.id) {
 				return false;
 			}
-			player.displayGUIEditFlag(flag);
+			player.displayFlagEditorScreen(flag);
 			return true;
 		}
 		return true;
diff --git a/src/main/java/net/minecraft/core/block/FlowerBlock.java b/src/main/java/net/minecraft/core/block/FlowerBlock.java
index c72f1999f..9dd508b68 100644
--- a/src/main/java/net/minecraft/core/block/FlowerBlock.java
+++ b/src/main/java/net/minecraft/core/block/FlowerBlock.java
@@ -81,7 +81,7 @@ public class FlowerBlock extends Block implements IBonemealable
     {
         if(!canBlockStay(world, i, j, k))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null, null);
             world.setBlockWithNotify(i, j, k, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/FloweringCherryLeavesBlock.java b/src/main/java/net/minecraft/core/block/FloweringCherryLeavesBlock.java
index 0eaf1dad1..218ba91ac 100644
--- a/src/main/java/net/minecraft/core/block/FloweringCherryLeavesBlock.java
+++ b/src/main/java/net/minecraft/core/block/FloweringCherryLeavesBlock.java
@@ -49,7 +49,7 @@ public class FloweringCherryLeavesBlock extends CherryLeavesBlock implements IBo
             world.playSoundAtEntity(player, player, "random.pop", 0.2F, 0.5f);
             if(!world.isClientSide)
             {
-                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null);
+                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null, null);
             }
             world.setBlockMetadataWithNotify(x, y, z, decayData);
             world.scheduleBlockUpdate(x, y, z, Blocks.LEAVES_CHERRY_FLOWERING.id, tickDelay());
diff --git a/src/main/java/net/minecraft/core/block/FlowingFluidBlock.java b/src/main/java/net/minecraft/core/block/FlowingFluidBlock.java
index a1b1642c0..282ba2dab 100644
--- a/src/main/java/net/minecraft/core/block/FlowingFluidBlock.java
+++ b/src/main/java/net/minecraft/core/block/FlowingFluidBlock.java
@@ -108,7 +108,7 @@ public class FlowingFluidBlock extends FluidBlock
         	int meta = world.getBlockMetadata(x, y - 1, z);
         	if(id > 0)
             {
-                Block.blocksList[id].dropBlockWithCause(world, EnumDropCause.WORLD, x, y - 1, z, meta, null);
+                Block.blocksList[id].dropBlockWithCause(world, EnumDropCause.WORLD, x, y - 1, z, meta, null, null);
         	}
             if(localFlowDecay >= 8) {
                 world.setBlockAndMetadataWithNotify(x, y - 1, z, this.id, localFlowDecay);
@@ -159,7 +159,7 @@ public class FlowingFluidBlock extends FluidBlock
                     fizz(world, i, j, k);
                 } else
                 {
-                    Block.blocksList[i1].dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null);
+                    Block.blocksList[i1].dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null, null);
                 }
             }
             world.setBlockAndMetadataWithNotify(i, j, k, id, l);
diff --git a/src/main/java/net/minecraft/core/block/FurnaceBlock.java b/src/main/java/net/minecraft/core/block/FurnaceBlock.java
index 41a1327d2..69c2ce2bd 100644
--- a/src/main/java/net/minecraft/core/block/FurnaceBlock.java
+++ b/src/main/java/net/minecraft/core/block/FurnaceBlock.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.block;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.entity.FurnaceBlockEntity;
@@ -10,6 +11,7 @@ import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 import java.util.Random;
 
@@ -21,7 +23,7 @@ import java.util.Random;
 
 public class FurnaceBlock extends RotatableEntityBlock
 {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
 	public FurnaceBlock(String key, String namespaceId, int id, boolean flag)
     {
         super(key, namespaceId, id, Material.stone);
@@ -91,21 +93,21 @@ public class FurnaceBlock extends RotatableEntityBlock
     {
         if (!world.isClientSide) {
             FurnaceBlockEntity tileentityfurnace = (FurnaceBlockEntity) world.getBlockEntity(x, y, z);
-            player.displayGUIFurnace(tileentityfurnace);
+            player.displayFurnaceScreen(tileentityfurnace);
         }
         return true;
     }
 
 	public static void updateFurnaceBlockState(boolean lit, World world, int x, int y, int z) {
 		int meta = world.getBlockMetadata(x, y, z);
-		BlockEntity tileentity = world.getBlockEntity(x, y, z);
-		if(tileentity == null) {
+		BlockEntity blockEntity = world.getBlockEntity(x, y, z);
+		if(blockEntity == null) {
 			String msg = "Furnace is missing Tile Entity at x: "+x+" y: "+y+" z: "+z+", block will be removed!";
 			if(Global.BUILD_CHANNEL.isUnstableBuild()) {
 				throw new RuntimeException(msg);
 			}
 			world.setBlockWithNotify(x, y, z, 0);
-			System.out.println(msg);
+            LOGGER.warn(msg);
 			return;
 		}
 		keepFurnaceInventory = true;
@@ -116,8 +118,8 @@ public class FurnaceBlock extends RotatableEntityBlock
 		}
 		keepFurnaceInventory = false;
 		world.setBlockMetadataWithNotify(x, y, z, meta);
-		tileentity.validate();
-		world.setBlockTileEntity(x, y, z, tileentity);
+		blockEntity.validate();
+		world.setBlockTileEntity(x, y, z, blockEntity);
 	}
 
     @Override
diff --git a/src/main/java/net/minecraft/core/block/LadderBlock.java b/src/main/java/net/minecraft/core/block/LadderBlock.java
index 5ee6eda1f..a9bd3529a 100644
--- a/src/main/java/net/minecraft/core/block/LadderBlock.java
+++ b/src/main/java/net/minecraft/core/block/LadderBlock.java
@@ -48,7 +48,7 @@ public class LadderBlock extends Block {
 	@Override
 	public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) {
 		if(!canExistAt(world, x, y, z, world.getBlockMetadata(x, y, z))) {
-			dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, blockId, null);
+			dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, blockId, null, null);
 			world.setBlockWithNotify(x, y, z, 0);
 		}
 	}
diff --git a/src/main/java/net/minecraft/core/block/LeavesLayerBlock.java b/src/main/java/net/minecraft/core/block/LeavesLayerBlock.java
index 74473f4b3..3bf083560 100644
--- a/src/main/java/net/minecraft/core/block/LeavesLayerBlock.java
+++ b/src/main/java/net/minecraft/core/block/LeavesLayerBlock.java
@@ -76,7 +76,7 @@ public class LeavesLayerBlock extends BaseLayerBlock
     {
         if(!canPlaceBlockAt(world, i, j, k))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null, null);
             world.setBlockWithNotify(i, j, k, 0);
             return false;
         } else
diff --git a/src/main/java/net/minecraft/core/block/LeverBlock.java b/src/main/java/net/minecraft/core/block/LeverBlock.java
index 21af5a45b..7cc1b88b0 100644
--- a/src/main/java/net/minecraft/core/block/LeverBlock.java
+++ b/src/main/java/net/minecraft/core/block/LeverBlock.java
@@ -107,7 +107,7 @@ public class LeverBlock extends Block
         }
 
         if(rotation == -1) {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
         } else {
             world.setBlockMetadataWithNotify(x, y, z, rotation | (isPowered ? MASK_POWERED : 0));
@@ -147,7 +147,7 @@ public class LeverBlock extends Block
             }
             if(shouldBreak)
             {
-                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
                 world.setBlockWithNotify(x, y, z, 0);
             }
         }
@@ -157,7 +157,7 @@ public class LeverBlock extends Block
     {
         if(!canPlaceBlockAt(world, x, y, z))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
             return false;
         } else
diff --git a/src/main/java/net/minecraft/core/block/MobSpawnerBlock.java b/src/main/java/net/minecraft/core/block/MobSpawnerBlock.java
index e2e09f731..139619975 100644
--- a/src/main/java/net/minecraft/core/block/MobSpawnerBlock.java
+++ b/src/main/java/net/minecraft/core/block/MobSpawnerBlock.java
@@ -28,7 +28,7 @@ public class MobSpawnerBlock extends EntityBlock
             return false;
         }
 
-        player.displayGUIMobSpawnerPicker(x, y, z);
+        player.displayMobPickerScreen(x, y, z);
         return true;
     }
 
diff --git a/src/main/java/net/minecraft/core/block/OverlayPebblesBlock.java b/src/main/java/net/minecraft/core/block/OverlayPebblesBlock.java
index d6536bcc1..9f256a320 100644
--- a/src/main/java/net/minecraft/core/block/OverlayPebblesBlock.java
+++ b/src/main/java/net/minecraft/core/block/OverlayPebblesBlock.java
@@ -52,7 +52,7 @@ public class OverlayPebblesBlock extends Block
     {
         if (!canBlockStay(world,x, y, z))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/PaintedFenceBlock.java b/src/main/java/net/minecraft/core/block/PaintedFenceBlock.java
index 2ae7966b8..eb86be43d 100644
--- a/src/main/java/net/minecraft/core/block/PaintedFenceBlock.java
+++ b/src/main/java/net/minecraft/core/block/PaintedFenceBlock.java
@@ -1,8 +1,10 @@
 package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.BlockEntity;
+import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
 public class PaintedFenceBlock extends FenceBlock
@@ -11,6 +13,11 @@ public class PaintedFenceBlock extends FenceBlock
 	{
 		super(key, namespaceId, id);
 	}
+	
+	@Override
+	public int getPlacedBlockMetadata(Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
+		return stack.getMetadata();
+	}
 
 	@Override
 	public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, BlockEntity blockEntity)
diff --git a/src/main/java/net/minecraft/core/block/PaintedFenceGateBlock.java b/src/main/java/net/minecraft/core/block/PaintedFenceGateBlock.java
index 0743413f9..625aca883 100644
--- a/src/main/java/net/minecraft/core/block/PaintedFenceGateBlock.java
+++ b/src/main/java/net/minecraft/core/block/PaintedFenceGateBlock.java
@@ -1,8 +1,10 @@
 package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.BlockEntity;
+import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
 
 public class PaintedFenceGateBlock extends FenceGateBlock
@@ -11,6 +13,11 @@ public class PaintedFenceGateBlock extends FenceGateBlock
 	{
 		super(key, namespaceId, id);
 	}
+	
+	@Override
+	public int getPlacedBlockMetadata(Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
+		return stack.getMetadata();
+	}
 
 	@Override
 	public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, BlockEntity blockEntity)
diff --git a/src/main/java/net/minecraft/core/block/PressurePlateBlock.java b/src/main/java/net/minecraft/core/block/PressurePlateBlock.java
index 69f08f4e4..8331bf503 100644
--- a/src/main/java/net/minecraft/core/block/PressurePlateBlock.java
+++ b/src/main/java/net/minecraft/core/block/PressurePlateBlock.java
@@ -62,7 +62,7 @@ public class PressurePlateBlock extends Block
         boolean flag = !canPlaceBlockAt(world, x, y, z);
         if(flag)
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/RailBlock.java b/src/main/java/net/minecraft/core/block/RailBlock.java
index 8a5495621..a05f43701 100644
--- a/src/main/java/net/minecraft/core/block/RailBlock.java
+++ b/src/main/java/net/minecraft/core/block/RailBlock.java
@@ -94,7 +94,7 @@ public class RailBlock extends Block {
         RailDirection railDirection = getRailDirection(world, x, y, z);
 
         if(!isValidState(world, x, y, z)) {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
             return;
         }
diff --git a/src/main/java/net/minecraft/core/block/RedstoneWireBlock.java b/src/main/java/net/minecraft/core/block/RedstoneWireBlock.java
index 7ea6f59ae..c127c1d9c 100644
--- a/src/main/java/net/minecraft/core/block/RedstoneWireBlock.java
+++ b/src/main/java/net/minecraft/core/block/RedstoneWireBlock.java
@@ -307,7 +307,7 @@ public class RedstoneWireBlock extends Block
         int meta = world.getBlockMetadata(x, y, z);
         boolean flag = canPlaceBlockAt(world, x, y, z);
         if(!flag) {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null, null);
             world.setBlockWithNotify(x, y, z, 0);
         } else {
             updateAndPropagateCurrentStrength(world, x, y, z);
diff --git a/src/main/java/net/minecraft/core/block/RepeaterBlock.java b/src/main/java/net/minecraft/core/block/RepeaterBlock.java
index 00d477bd3..680360b39 100644
--- a/src/main/java/net/minecraft/core/block/RepeaterBlock.java
+++ b/src/main/java/net/minecraft/core/block/RepeaterBlock.java
@@ -101,7 +101,7 @@ public class RepeaterBlock extends Block
     @Override
 	public void onNeighborBlockChange(World world, int x, int y, int z, int blockId) {
         if(!canBlockStay(world, x, y, z)) {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
             return;
         }
diff --git a/src/main/java/net/minecraft/core/block/RopeBlock.java b/src/main/java/net/minecraft/core/block/RopeBlock.java
index abbefe753..0fe24747c 100644
--- a/src/main/java/net/minecraft/core/block/RopeBlock.java
+++ b/src/main/java/net/minecraft/core/block/RopeBlock.java
@@ -3,9 +3,10 @@ package net.minecraft.core.block;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.entity.player.Player;
+import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.enums.EnumDropCause;
-import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ToolShearsItem;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.util.phys.AABB;
@@ -64,11 +65,12 @@ public class RopeBlock
 
         setBlockBounds(minX, minY, minZ, maxX, maxY, maxZ);
     }
+    
     @Override
     public boolean onBlockRightClicked(World world, int x, int y, int z, Player player, Side side, double xPlaced, double yPlaced)
     {
         ItemStack heldItem = player.getHeldItem();
-        if (heldItem != null && heldItem.getItem() instanceof ToolShearsItem){
+        if (heldItem != null && heldItem.getItem() instanceof ToolShearsItem) {
             int meta = world.getBlockMetadata(x, y, z);
             int forceRope = (~meta) & 0b1000_0000;
             world.setBlockMetadataWithNotify(x, y, z, forceRope | (meta & 0b0111_1111));
@@ -78,8 +80,65 @@ public class RopeBlock
             }
             return true;
         }
+        
+        if(heldItem == null) {
+        	pickUpRope(world, x, y, z, player);
+        	return true;
+        }
+        
         return false;
     }
+    
+    public void pickUpRope(World world, int x, int y, int z, Player player) {
+    	if(world.isClientSide || world.getBlock(x, y, z) != this) {
+    		return;
+    	}
+    	
+    	final int highestRope = y;
+    	// Find the position of the lowest rope
+    	while(y > 0) {
+    		Block block = world.getBlock(x, y - 1, z);
+    		if(block != this) {
+    			break;
+    		}
+    		y--;
+    	}
+    	final int lowestRope = y;
+    	
+    	// Determine how many ropes fit into the players inventory
+    	int freeSpace = 0;
+    	for(int i=0; i < player.inventory.mainInventory.length; i++) {
+    		ItemStack stack = player.inventory.mainInventory[i];
+    		if(stack == null) {
+    			freeSpace += Items.ROPE.getItemStackLimit();
+    			continue;
+    		}
+    		if(stack.getItem() == Items.ROPE) {
+    			freeSpace += Items.ROPE.getItemStackLimit() - stack.stackSize;	
+    		}
+    	}
+    	freeSpace = Math.min(freeSpace, 1);
+    	
+    	int ropesCollected = 0;
+    	for(y = lowestRope; y <= highestRope; y++) {
+    		if(ropesCollected >= freeSpace) {
+    			break;
+    		}
+    		world.setBlockWithNotify(x, y, z, 0);
+    		ropesCollected++;
+    	}
+    	
+    	if(player.getGamemode().consumeBlocks()) {
+    		ItemStack stack = new ItemStack(Items.ROPE, ropesCollected);
+    		player.inventory.insertItem(stack, true);
+    		if(stack.stackSize > 0) {
+        		// this shouldnt happen
+        		player.dropPlayerItem(stack);
+        	}	
+    	}
+    	
+    	world.playBlockSoundEffect(player, x + 0.5, highestRope + 0.5, z + 0.5, this, EnumBlockSoundEffectType.PLACE);
+    }
 
     @Override
     public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, BlockEntity blockEntity) {
diff --git a/src/main/java/net/minecraft/core/block/SignBlock.java b/src/main/java/net/minecraft/core/block/SignBlock.java
index 2557be6f6..e3e5ca388 100644
--- a/src/main/java/net/minecraft/core/block/SignBlock.java
+++ b/src/main/java/net/minecraft/core/block/SignBlock.java
@@ -145,7 +145,7 @@ public class SignBlock extends EntityBlock
         }
         if(flag)
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
         }
         super.onNeighborBlockChange(world, x, y, z, blockId);
@@ -169,7 +169,7 @@ public class SignBlock extends EntityBlock
             } else if (player.getHeldItem() != null && player.getHeldItem().itemID == Items.DYE.id) {
                 return false;
             } else if (signEntity.isEditableBy(player)) {
-                player.displayGUIEditSign(signEntity);
+                player.displaySignEditorScreen(signEntity);
                 return true;
             }
         }
diff --git a/src/main/java/net/minecraft/core/block/SnowBlock.java b/src/main/java/net/minecraft/core/block/SnowBlock.java
index 9eaca196e..5ce60b89c 100644
--- a/src/main/java/net/minecraft/core/block/SnowBlock.java
+++ b/src/main/java/net/minecraft/core/block/SnowBlock.java
@@ -33,7 +33,7 @@ public class SnowBlock extends Block
     {
         if(world.getSavedLightValue(LightLayer.Block, x, y, z) > 11)
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/SnowLayerBlock.java b/src/main/java/net/minecraft/core/block/SnowLayerBlock.java
index e03309eb7..02fe4c8cd 100644
--- a/src/main/java/net/minecraft/core/block/SnowLayerBlock.java
+++ b/src/main/java/net/minecraft/core/block/SnowLayerBlock.java
@@ -78,7 +78,7 @@ public class SnowLayerBlock extends BaseLayerBlock
     {
         if(!canPlaceBlockAt(world, i, j, k))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null, null);
             world.setBlockWithNotify(i, j, k, 0);
             return false;
         } else
@@ -109,12 +109,12 @@ public class SnowLayerBlock extends BaseLayerBlock
     {
 		if(world.getSavedLightValue(LightLayer.Block, x, y, z) > 11)
 		{
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
 			world.setBlockWithNotify(x, y, z, 0);
 		}
         if(world.getBlockBiome(x, y, z) != null && !world.getBlockBiome(x, y, z).hasSurfaceSnow() && world.getSeasonManager().getCurrentSeason() != null && world.getSeasonManager().getCurrentSeason().letWeatherCleanUpSnow)
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
             world.setBlockWithNotify(x, y, z, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/SpikesBlock.java b/src/main/java/net/minecraft/core/block/SpikesBlock.java
index b9446e445..9e80c1cfd 100644
--- a/src/main/java/net/minecraft/core/block/SpikesBlock.java
+++ b/src/main/java/net/minecraft/core/block/SpikesBlock.java
@@ -46,7 +46,7 @@ public class SpikesBlock extends CobwebBlock
 		
 		boolean destroy = !world.canPlaceOnSurfaceOfBlock(x, y - 1, z) && world.getBlockId(x, y - 1, z) != Blocks.MESH.id && world.getBlockId(x, y - 1, z) != Blocks.MOBSPAWNER.id;
 		if(destroy) {
-			dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+			dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
 			world.setBlockWithNotify(x, y, z, 0);
 			return;
 		}
diff --git a/src/main/java/net/minecraft/core/block/SugarcaneBlock.java b/src/main/java/net/minecraft/core/block/SugarcaneBlock.java
index bcadba290..c9e8017ed 100644
--- a/src/main/java/net/minecraft/core/block/SugarcaneBlock.java
+++ b/src/main/java/net/minecraft/core/block/SugarcaneBlock.java
@@ -101,7 +101,7 @@ public class SugarcaneBlock extends Block implements IBonemealable
     {
         if(!canBlockStay(world, i, j, k))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null, null);
             world.setBlockWithNotify(i, j, k, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/core/block/TorchBlock.java b/src/main/java/net/minecraft/core/block/TorchBlock.java
index 9a6a29bcf..c0174f91a 100644
--- a/src/main/java/net/minecraft/core/block/TorchBlock.java
+++ b/src/main/java/net/minecraft/core/block/TorchBlock.java
@@ -163,7 +163,7 @@ public class TorchBlock extends Block
             }
             if(flag)
             {
-                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, i1, null);
+                dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, i1, null, null);
                 world.setBlockWithNotify(x, y, z, 0);
             }
         }
@@ -173,7 +173,7 @@ public class TorchBlock extends Block
     {
         if(!canPlaceBlockAt(world, i, j, k))
         {
-            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null);
+            dropBlockWithCause(world, EnumDropCause.WORLD, i, j, k, world.getBlockMetadata(i, j, k), null, null);
             world.setBlockWithNotify(i, j, k, 0);
             return false;
         } else
diff --git a/src/main/java/net/minecraft/core/block/TrommelBlock.java b/src/main/java/net/minecraft/core/block/TrommelBlock.java
index 12887ff9c..2df0d5901 100644
--- a/src/main/java/net/minecraft/core/block/TrommelBlock.java
+++ b/src/main/java/net/minecraft/core/block/TrommelBlock.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.block;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.Global;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.entity.TrommelBlockEntity;
@@ -10,11 +11,13 @@ import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 import java.util.Random;
 
 public class TrommelBlock extends RotatableEntityBlock
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
 	public TrommelBlock(String key, String namespaceId, int id, Material material, boolean isActive)
     {
         super(key, namespaceId, id, material);
@@ -49,7 +52,7 @@ public class TrommelBlock extends RotatableEntityBlock
     {
         if (!world.isClientSide) {
             TrommelBlockEntity tileEntityTrommel = (TrommelBlockEntity) world.getBlockEntity(x, y, z);
-            player.displayGUITrommel(tileEntityTrommel);
+            player.displayTrommelScreen(tileEntityTrommel);
         }
         return true;
     }
@@ -68,14 +71,14 @@ public class TrommelBlock extends RotatableEntityBlock
     public static void updateTrommelBlockState(boolean flag, World world, int i, int j, int k)
     {
         int l = world.getBlockMetadata(i, j, k);
-        BlockEntity tileentity = world.getBlockEntity(i, j, k);
-        if(tileentity == null) {
+        BlockEntity blockEntity = world.getBlockEntity(i, j, k);
+        if(blockEntity == null) {
             String msg = "Trommel is missing Tile Entity at x: " + i + " y: " + j + " z: " + k + ", block will be removed!";
             if(Global.BUILD_CHANNEL.isUnstableBuild()) {
                 throw new RuntimeException(msg);
             }
             world.setBlockWithNotify(i, j, k, 0);
-            System.out.println(msg);
+            LOGGER.warn(msg);
             return;
         }
         keepTrommelInventory = true;
@@ -88,8 +91,8 @@ public class TrommelBlock extends RotatableEntityBlock
         }
         keepTrommelInventory = false;
         world.setBlockMetadataWithNotify(i, j, k, l);
-        tileentity.validate();
-        world.setBlockTileEntity(i, j, k, tileentity);
+        blockEntity.validate();
+        world.setBlockTileEntity(i, j, k, blockEntity);
     }
     
     @Override
@@ -99,11 +102,11 @@ public class TrommelBlock extends RotatableEntityBlock
     	{
     		if(world.getBlockEntity(x, y, z) != null)
     		{
-    			TrommelBlockEntity tileentitytrommel = (TrommelBlockEntity) world.getBlockEntity(x, y, z);
+    			TrommelBlockEntity trommel = (TrommelBlockEntity) world.getBlockEntity(x, y, z);
     			label0:
-				for (int l = 0; l < tileentitytrommel.getContainerSize(); l++)
+				for (int l = 0; l < trommel.getContainerSize(); l++)
 				{
-					ItemStack itemstack = tileentitytrommel.getItem(l);
+					ItemStack itemstack = trommel.getItem(l);
 					if (itemstack == null) {
 						continue;
 					}
@@ -119,12 +122,12 @@ public class TrommelBlock extends RotatableEntityBlock
 							i1 = itemstack.stackSize;
 						}
 						itemstack.stackSize -= i1;
-						ItemEntity entityitem = new ItemEntity(world, (float) x + f, (float) y + f1, (float) z + f2, new ItemStack(itemstack.itemID, i1, itemstack.getMetadata()));
+						ItemEntity item = new ItemEntity(world, (float) x + f, (float) y + f1, (float) z + f2, new ItemStack(itemstack.itemID, i1, itemstack.getMetadata()));
 						float f3 = 0.05F;
-						entityitem.xd = (float) random.nextGaussian() * f3;
-						entityitem.yd = (float) random.nextGaussian() * f3 + 0.2F;
-						entityitem.zd = (float) random.nextGaussian() * f3;
-						world.entityJoinedWorld(entityitem);
+						item.xd = (float) random.nextGaussian() * f3;
+						item.yd = (float) random.nextGaussian() * f3 + 0.2F;
+						item.zd = (float) random.nextGaussian() * f3;
+						world.entityJoinedWorld(item);
 					} while (true);
 				}
     		}
diff --git a/src/main/java/net/minecraft/core/block/WoolBlock.java b/src/main/java/net/minecraft/core/block/WoolBlock.java
index 1cf8852de..315025490 100644
--- a/src/main/java/net/minecraft/core/block/WoolBlock.java
+++ b/src/main/java/net/minecraft/core/block/WoolBlock.java
@@ -2,15 +2,23 @@ package net.minecraft.core.block;
 
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.material.Material;
+import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.util.helper.Side;
 import net.minecraft.core.world.World;
+
 public class WoolBlock extends Block
 {
     public WoolBlock(String key, String namespaceId, int id) {
 
         super(key, namespaceId, id, Material.cloth);
     }
+    
+    @Override
+    public int getPlacedBlockMetadata(Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
+    	return stack.getMetadata() & 0xF;
+    }
 
     @Override
     public ItemStack[] getBreakResult(World world, EnumDropCause dropCause, int x, int y, int z, int meta, BlockEntity blockEntity)
diff --git a/src/main/java/net/minecraft/core/block/WorkbenchBlock.java b/src/main/java/net/minecraft/core/block/WorkbenchBlock.java
index 3ff1605f6..5b300247e 100644
--- a/src/main/java/net/minecraft/core/block/WorkbenchBlock.java
+++ b/src/main/java/net/minecraft/core/block/WorkbenchBlock.java
@@ -21,7 +21,7 @@ public class WorkbenchBlock extends Block
     {
         if (!world.isClientSide)
         {
-            player.displayGUIWorkbench(x, y, z);
+            player.displayWorkbenchScreen(x, y, z);
         }
         return true;
     }
diff --git a/src/main/java/net/minecraft/core/block/entity/BlockEntity.java b/src/main/java/net/minecraft/core/block/entity/BlockEntity.java
index 9a8b24ee1..00c13fa48 100644
--- a/src/main/java/net/minecraft/core/block/entity/BlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/BlockEntity.java
@@ -1,10 +1,13 @@
 package net.minecraft.core.block.entity;
 
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
 import net.minecraft.core.block.Block;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.block.piston.MovingPistonBlockEntity;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -16,21 +19,21 @@ import java.util.Map;
 
 public class BlockEntity
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
 
     public BlockEntity()
     {
     }
 
-    private static void addMapping(Class class1, String s)
+    private static void addMapping(Class<? extends BlockEntity> entityClass, String name)
     {
-        if(classToNameMap.containsKey(s))
+        if(nameToClassMap.containsKey(name))
         {
-            throw new IllegalArgumentException((new StringBuilder()).append("Duplicate id: ").append(s).toString());
+            throw new IllegalArgumentException("Duplicate id: " + name);
         } else
         {
-            nameToClassMap.put(s, class1);
-            classToNameMap.put(class1, s);
-            return;
+            nameToClassMap.put(name, entityClass);
+            classToNameMap.put(entityClass, name);
         }
     }
 
@@ -43,17 +46,16 @@ public class BlockEntity
 
     public void writeToNBT(CompoundTag nbttagcompound)
     {
-        String s = (String)classToNameMap.get(getClass());
-        if(s == null)
+        String name = classToNameMap.get(getClass());
+        if(name == null)
         {
             throw new RuntimeException(getClass() + " is missing a mapping! This is a bug!");
         } else
         {
-            nbttagcompound.putString("id", s);
+            nbttagcompound.putString("id", name);
             nbttagcompound.putInt("x", x);
             nbttagcompound.putInt("y", y);
             nbttagcompound.putInt("z", z);
-            return;
         }
     }
 
@@ -63,32 +65,32 @@ public class BlockEntity
 
     public static BlockEntity createAndLoadEntity(CompoundTag nbttagcompound)
     {
-        BlockEntity tileentity = null;
+        BlockEntity blockEntity = null;
+        Class<? extends BlockEntity> entityClass = nameToClassMap.get(nbttagcompound.getString("id"));
         try
         {
-            Class class1 = (Class)nameToClassMap.get(nbttagcompound.getString("id"));
-            if(class1 != null)
+            if(entityClass != null)
             {
-                tileentity = (BlockEntity)class1.newInstance();
+                blockEntity = entityClass.newInstance();
             }
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Exception when instancing class '{}'!", entityClass.getSimpleName(), exception);
         }
-        if(tileentity != null)
+        if(blockEntity != null)
         {
-            tileentity.readFromNBT(nbttagcompound);
+            blockEntity.readFromNBT(nbttagcompound);
         } else
         {
-            System.out.println("Skipping BlockEntity with id " + nbttagcompound.getString("id"));
+            LOGGER.warn("Skipping BlockEntity with id {}", nbttagcompound.getString("id"));
         }
-        return tileentity;
+        return blockEntity;
     }
 
-    public static Class<?> getClassFromID(String id)
+    public static Class<? extends BlockEntity> getClassFromID(String id)
     {
-        return (Class<?>)nameToClassMap.get(id);
+        return nameToClassMap.get(id);
     }
 
     public int getMovedData()
@@ -137,8 +139,8 @@ public class BlockEntity
         tileEntityInvalid = false;
     }
 
-    private static Map nameToClassMap = new HashMap();
-    private static Map classToNameMap = new HashMap();
+    private static final Map<String, Class<? extends BlockEntity>> nameToClassMap = new HashMap<>();
+    private static final Map<Class<? extends BlockEntity>, String> classToNameMap = new HashMap<>();
     public World worldObj;
     public int x;
     public int y;
diff --git a/src/main/java/net/minecraft/core/block/entity/FlagBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/FlagBlockEntity.java
index aae0feea3..1b90a467a 100644
--- a/src/main/java/net/minecraft/core/block/entity/FlagBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/FlagBlockEntity.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.block.entity;
 
 import java.util.Random;
+import java.util.UUID;
 
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.ListTag;
@@ -11,6 +12,8 @@ import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.BlockEntityDataPacket;
 import net.minecraft.core.player.inventory.container.Container;
+import net.minecraft.core.util.helper.UUIDHelper;
+import org.jetbrains.annotations.Nullable;
 
 public class FlagBlockEntity extends BlockEntity
     implements Container
@@ -20,7 +23,7 @@ public class FlagBlockEntity extends BlockEntity
     public final byte[] flagColors = new byte[CANVAS_WIDTH * CANVAS_HEIGHT];
     
     public ItemStack[] items = new ItemStack[3];
-    public String owner = "";
+    public @Nullable UUID owner;
     
     public int sway = new Random().nextInt(100); // Random start value
     
@@ -68,7 +71,7 @@ public class FlagBlockEntity extends BlockEntity
     {
         byte[] packedColors = packFlagColors(flagColors);
         tag.putByteArray("Colors", packedColors);
-        tag.putString("Owner", owner);
+        UUIDHelper.writeToTag(tag, owner, "OwnerUUID");
 
         ListTag list = new ListTag();
         for (int i = 0; i < items.length; i++)
@@ -97,7 +100,18 @@ public class FlagBlockEntity extends BlockEntity
         if (packedColors == null) packedColors = new byte[(CANVAS_WIDTH * CANVAS_HEIGHT) / 4];
         byte[] unpackedColors = unpackFlagColors(packedColors);
         System.arraycopy(unpackedColors, 0, flagColors, 0, CANVAS_WIDTH * CANVAS_HEIGHT);
-        owner = tag.getStringOrDefault("Owner", "");
+
+        UUID ownerUUID = UUIDHelper.readFromTag(tag, "OwnerUUID");
+        if (ownerUUID == null) {
+            String s = tag.getString("Owner");
+            if (!s.isEmpty()) {
+                UUIDHelper.runConversionAction(s,
+                    (uuid) -> this.owner = uuid,
+                    null);
+            }
+        } else {
+            this.owner = ownerUUID;
+        }
 
         ListTag list = tag.getList("Items");
         items = new ItemStack[getContainerSize()];
@@ -115,9 +129,11 @@ public class FlagBlockEntity extends BlockEntity
     public void copyFlagNBT(CompoundTag tag) {
 
         byte[] packedColors = packFlagColors(flagColors);
-        String copyOwner = tag.getStringOrDefault("Owner", "");
-        if(copyOwner.isEmpty())
-            tag.putString("Owner", owner);
+        UUID copyOwner = UUIDHelper.readFromTag(tag, "OwnerUUID");
+        if(copyOwner != null) {
+            UUIDHelper.writeToTag(tag, owner, "OwnerUUID");
+        }
+
         tag.putByteArray("Colors", packedColors);
     }
 
diff --git a/src/main/java/net/minecraft/core/block/entity/MobSpawnerBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/MobSpawnerBlockEntity.java
index 13826753b..8383010e4 100644
--- a/src/main/java/net/minecraft/core/block/entity/MobSpawnerBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/MobSpawnerBlockEntity.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.block.entity;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.entity.EntityDispatcher;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.enums.MobCategory;
@@ -9,11 +10,13 @@ import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.SetMobSpawnerPacket;
 import net.minecraft.core.entity.SpawnListEntry;
+import org.slf4j.Logger;
 
 import java.util.List;
 
 public class MobSpawnerBlockEntity extends BlockEntity
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public int delay;
     private String mobId;
     public double yaw;
@@ -166,9 +169,9 @@ public class MobSpawnerBlockEntity extends BlockEntity
     	delay = 200 + worldObj.rand.nextInt(600);
     	if(mobId == null) {
     		delay *= 2;
-    		System.out.println("x2");
+            LOGGER.debug("x2");
     		if(nearby > 1) {
-    			System.out.println("x4");
+                LOGGER.debug("x4");
     			delay *= 4;
     		}
     	}
diff --git a/src/main/java/net/minecraft/core/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/SignBlockEntity.java
index fa243d89e..f34335af4 100644
--- a/src/main/java/net/minecraft/core/block/entity/SignBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/SignBlockEntity.java
@@ -6,6 +6,10 @@ import net.minecraft.core.enums.EnumSignPicture;
 import net.minecraft.core.net.command.TextFormatting;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.net.packet.BlockEntityDataPacket;
+import net.minecraft.core.util.helper.UUIDHelper;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
 
 public class SignBlockEntity extends BlockEntity
 {
@@ -13,7 +17,7 @@ public class SignBlockEntity extends BlockEntity
     public int lineBeingEdited;
     private int selectedPicture = 0;
     private int selectedColor = 15;
-    private String owner = "";
+    private @Nullable UUID owner;
     private boolean glowing = false;
 
     public SignBlockEntity()
@@ -32,7 +36,7 @@ public class SignBlockEntity extends BlockEntity
         tag.putInt("Picture", selectedPicture);
         tag.putInt("Color", selectedColor);
         tag.putBoolean("Glowing", glowing);
-        tag.putString("Owner", owner);
+        UUIDHelper.writeToTag(tag, owner, "OwnerUUID");
     }
 
     @Override
@@ -50,16 +54,27 @@ public class SignBlockEntity extends BlockEntity
         selectedPicture = tag.getIntegerOrDefault("Picture", 0);
         selectedColor = tag.getIntegerOrDefault("Color", 15);
         glowing = tag.getBooleanOrDefault("Glowing", false);
-        owner = tag.getString("Owner");
+
+        UUID ownerUUID = UUIDHelper.readFromTag(tag, "OwnerUUID");
+        if (ownerUUID == null) {
+            String s = tag.getString("Owner");
+            if (!s.isEmpty()) {
+                UUIDHelper.runConversionAction(s,
+                    (uuid) -> this.owner = uuid,
+                    null);
+            }
+        } else {
+            this.owner = ownerUUID;
+        }
     }
     
     public boolean isEditableBy(Player player)
     {
-        return player.username.equals(owner);
+        return player.uuid.equals(owner);
     }
 
     public void setOwner(Player player){
-        this.owner = player.username;
+        this.owner = player.uuid;
     }
 
     public EnumSignPicture getPicture()
diff --git a/src/main/java/net/minecraft/core/block/entity/TrommelBlockEntity.java b/src/main/java/net/minecraft/core/block/entity/TrommelBlockEntity.java
index 094d8a83e..afcd2da8d 100644
--- a/src/main/java/net/minecraft/core/block/entity/TrommelBlockEntity.java
+++ b/src/main/java/net/minecraft/core/block/entity/TrommelBlockEntity.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.block.entity;
 
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.ListTag;
 import net.minecraft.core.block.Block;
@@ -8,6 +9,7 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.ChestBlock;
 import net.minecraft.core.block.TrommelBlock;
 import net.minecraft.core.crafting.LookupFuelFurnace;
+import net.minecraft.core.data.DataLoader;
 import net.minecraft.core.data.registry.recipe.entry.RecipeEntryTrommel;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.entity.monster.SlimeMob;
@@ -17,6 +19,8 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.util.helper.MathHelper;
+import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 import java.util.HashMap;
 import java.util.List;
@@ -377,33 +381,68 @@ public class TrommelBlockEntity extends BlockEntity
     }
 
     private void simulateTrommelDrops(int passes, ItemStack blockToTest){
-        Map<Item, Integer> trommelDropMap = new HashMap<>();
+        Map<Object, Integer> trommelDropMap = new HashMap<>();
         System.out.println();
-        System.out.println("Generating simulation of Trommel loot for block: " + blockToTest.getItem().getKey());
+        System.out.println("Generating simulation of Trommel loot for block: " + blockToTest.getItem().namespaceID);
         for(int i = 0; i < passes; i++){
             ItemStack itemStack = this.getItemResult(blockToTest);
             if(itemStack != null){
                 Item item = itemStack.getItem();
-                trommelDropMap.put(item, trommelDropMap.getOrDefault(item, 0) + 1);
+                trommelDropMap.put(item.namespaceID, trommelDropMap.getOrDefault(item.namespaceID, 0) + 1);
+            } else {
+                trommelDropMap.put("NULL", trommelDropMap.getOrDefault("NULL", 0) + 1);
             }
         }
         System.out.println("Trommel loot sampling " + passes + " passes:");
         for (Item item : Item.itemsList)
         {
+            if (item == null) continue;;
+            Integer amount = trommelDropMap.get(item.namespaceID);
             float percentage;
-            if (trommelDropMap.containsKey(item))
+            if (amount != null)
             {
-                percentage = trommelDropMap.get(item) / (float) (passes);
+                percentage = amount / (float) (passes);
                 percentage *= 100;
             } else {
                 percentage = 0.0f;
             }
-            if(trommelDropMap.containsKey(item) && item != null) {
-                System.out.println("        " + item.getKey() + " yield: " + trommelDropMap.get(item)  + " (" + MathHelper.floor_float((float)(trommelDropMap.get(item))/64F) + " stacks) - " + String.format("%.2f", percentage) + "%");
+            if(amount != null) {
+                System.out.println("        " + item.namespaceID + " yield: " + amount  + String.format(" (%.2f stacks) - ", (float)(amount)/64F) + String.format("%.2f", percentage) + "%");
             }
         }
+        if (trommelDropMap.get("NULL") != null) {
+            float percentage = trommelDropMap.get("NULL") / (float) (passes);
+            percentage *= 100;
+            System.out.println("        " + "NULL" + " yield: " + trommelDropMap.get("NULL")  + " (" + MathHelper.floor_float((float)(trommelDropMap.get("NULL"))/64F) + " stacks) - " + String.format("%.2f", percentage) + "%");
+        }
+    }
+
+    public static void main(String[] args) {
+        Blocks.init();
+        Items.init();
+
+        new Registries();
+
+        // Load vanilla recipes
+        DataLoader.loadRecipesFromFile("/recipes/blast_furnace.json");
+        DataLoader.loadRecipesFromFile("/recipes/furnace.json");
+        DataLoader.loadRecipesFromFile("/recipes/trommel.json");
+        DataLoader.loadRecipesFromFile("/recipes/workbench.json");
+
+//        DataLoader.loadDataPacks(this);
+
+        TrommelBlockEntity trommel = new TrommelBlockEntity();
+        trommel.worldObj = new World();
+
+        trommel.simulateTrommelDrops(10000, Blocks.DIRT.getDefaultStack());
+        trommel.simulateTrommelDrops(10000, Blocks.GRAVEL.getDefaultStack());
+        trommel.simulateTrommelDrops(10000, Blocks.SAND.getDefaultStack());
+        trommel.simulateTrommelDrops(10000, Blocks.SOULSAND.getDefaultStack());
+        trommel.simulateTrommelDrops(10000, Blocks.BLOCK_CLAY.getDefaultStack());
+        trommel.simulateTrommelDrops(10000, Blocks.DIRT_SCORCHED_RICH.getDefaultStack());
     }
 
+    private static final Logger LOGGER = LogUtils.getLogger();
     private ItemStack[] itemStacks;
 
     public int burnTime;
diff --git a/src/main/java/net/minecraft/core/block/piston/BasePistonBlock.java b/src/main/java/net/minecraft/core/block/piston/BasePistonBlock.java
index 142107b20..05b2a0555 100644
--- a/src/main/java/net/minecraft/core/block/piston/BasePistonBlock.java
+++ b/src/main/java/net/minecraft/core/block/piston/BasePistonBlock.java
@@ -304,7 +304,7 @@ public class BasePistonBlock extends Block
                     int y2 = y + PistonDirections.yOffset[direction % 6];
                     int z2 = z + PistonDirections.zOffset[direction % 6];
                     world.playSoundEffect(null, 2001, x2, y2, z2, world.getBlockId(x2, y2, z2));
-                    Block.blocksList[world.getBlockId(x2, y2, z2)].dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x2, y2, z2, world.getBlockMetadata(x2, y2, z2), null);
+                    Block.blocksList[world.getBlockId(x2, y2, z2)].dropBlockWithCause(world, EnumDropCause.SILK_TOUCH, x2, y2, z2, world.getBlockMetadata(x2, y2, z2), null, null);
                     world.setBlockWithNotify(x2, y2, z2, 0);
                     break;
                 }
@@ -353,7 +353,7 @@ public class BasePistonBlock extends Block
             }
             if(Block.blocksList[j2].getPistonPushReaction() == 1)
             {
-                Block.blocksList[j2].dropBlockWithCause(world, EnumDropCause.WORLD, i1, j1, k1, world.getBlockMetadata(i1, j1, k1), null);
+                Block.blocksList[j2].dropBlockWithCause(world, EnumDropCause.WORLD, i1, j1, k1, world.getBlockMetadata(i1, j1, k1), null, null);
                 world.setBlockWithNotify(i1, j1, k1, 0);
                 break;
             }
diff --git a/src/main/java/net/minecraft/core/block/piston/MovingPistonBlock.java b/src/main/java/net/minecraft/core/block/piston/MovingPistonBlock.java
index a85ad3f76..ab847f4e2 100644
--- a/src/main/java/net/minecraft/core/block/piston/MovingPistonBlock.java
+++ b/src/main/java/net/minecraft/core/block/piston/MovingPistonBlock.java
@@ -95,7 +95,7 @@ public class MovingPistonBlock extends EntityBlock
     }
 
     @Override
-    public void dropBlockWithCause(World world, EnumDropCause cause, int x, int y, int z, int meta, BlockEntity blockEntity)
+    public void dropBlockWithCause(World world, EnumDropCause cause, int x, int y, int z, int meta, BlockEntity blockEntity, Player player)
     {
         if(world.isClientSide)
         {
@@ -104,7 +104,7 @@ public class MovingPistonBlock extends EntityBlock
         MovingPistonBlockEntity piston = getBlockEntity(world, x, y, z);
         if(piston != null)
         {
-            Block.blocksList[piston.getMovedId()].dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null);
+            Block.blocksList[piston.getMovedId()].dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, meta, null, null);
         }
     }
 
diff --git a/src/main/java/net/minecraft/core/block/piston/PistonHeadBlock.java b/src/main/java/net/minecraft/core/block/piston/PistonHeadBlock.java
index 05064fd5b..027e1d67d 100644
--- a/src/main/java/net/minecraft/core/block/piston/PistonHeadBlock.java
+++ b/src/main/java/net/minecraft/core/block/piston/PistonHeadBlock.java
@@ -41,7 +41,7 @@ public class PistonHeadBlock extends Block
             int i1 = world.getBlockMetadata(x, y, z);
             if(BasePistonBlock.isPowered(i1))
             {
-                Block.blocksList[k1].dropBlockWithCause(world, EnumDropCause.PROPER_TOOL, x, y, z, i1, null);
+                Block.blocksList[k1].dropBlockWithCause(world, EnumDropCause.PROPER_TOOL, x, y, z, i1, null, null);
                 world.setBlockWithNotify(x, y, z, 0);
             }
         }
diff --git a/src/main/java/net/minecraft/core/block/tag/BlockTags.java b/src/main/java/net/minecraft/core/block/tag/BlockTags.java
index b2a4e806b..bbe98ef7c 100644
--- a/src/main/java/net/minecraft/core/block/tag/BlockTags.java
+++ b/src/main/java/net/minecraft/core/block/tag/BlockTags.java
@@ -1,5 +1,7 @@
 package net.minecraft.core.block.tag;
 
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.CactusBlock;
 import net.minecraft.core.block.ChainlinkFenceBlock;
@@ -20,6 +22,7 @@ import net.minecraft.core.item.tool.HoeToolItem;
 import net.minecraft.core.item.tool.PickaxeToolItem;
 import net.minecraft.core.item.tool.ShovelToolItem;
 import net.minecraft.core.item.tool.SwordToolItem;
+import org.slf4j.Logger;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -30,6 +33,7 @@ import java.util.List;
  */
 public abstract class BlockTags
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     /**
      * block can be mined by {@link PickaxeToolItem PickaxeToolItem}.
      */
@@ -108,7 +112,7 @@ public abstract class BlockTags
      */
     public static Tag<Block> SHEARS_DO_SILK_TOUCH = Tag.of("shears_do_silk_touch");
     /**
-     * This block can be skated on using {@link net.minecraft.core.item.Item#ARMOR_BOOTS_ICESKATES ice skates}.
+     * This block can be skated on using {@link net.minecraft.core.item.Items#ARMOR_BOOTS_ICESKATES ice skates}.
      */
     public static Tag<Block> SKATEABLE = Tag.of("skateable");
     /**
@@ -151,6 +155,18 @@ public abstract class BlockTags
      * Block extends the range of a motion sensor's sight.
      */
     public static Tag<Block> EXTENDS_MOTION_SENSOR_RANGE = Tag.of("extends_motion_sensor_range");
+    /**
+     * When broken, items go into the player's inventory immediately instead of being dropped
+     */
+    public static Tag<Block> INSTANT_PICKUP = Tag.of("instant_pickup");
+    /**
+     * Sheep will follow the player if they are holding this block.
+     */
+    public static Tag<Block> SHEEPS_FAVOURITE_BLOCK = Tag.of("sheeps_favourite_block");
+    /**
+     * Pigs will follow the player if they are holding this block.
+     */
+    public static Tag<Block> PIGS_FAVOURITE_BLOCK = Tag.of("pigs_favourite_block");
 
     public static List<Tag<Block>> TAG_LIST;
 
@@ -168,7 +184,7 @@ public abstract class BlockTags
                 }
                 catch (Exception e)
                 {
-                    e.printStackTrace();
+                    LOGGER.error("Failed to add tag '{}'!", field.getName(), e);
                 }
             }
         }
diff --git a/src/main/java/net/minecraft/core/data/DataLoader.java b/src/main/java/net/minecraft/core/data/DataLoader.java
index cc6e57c74..a634f9547 100644
--- a/src/main/java/net/minecraft/core/data/DataLoader.java
+++ b/src/main/java/net/minecraft/core/data/DataLoader.java
@@ -4,6 +4,7 @@ import com.b100.utils.FileUtils;
 import com.b100.utils.StringUtils;
 import com.google.gson.*;
 import com.google.gson.reflect.TypeToken;
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.MinecraftAccessor;
 import net.minecraft.core.WeightedRandomBag;
 import net.minecraft.core.WeightedRandomLootObject;
@@ -14,6 +15,7 @@ import net.minecraft.core.data.registry.recipe.RecipeSymbol;
 import net.minecraft.core.data.registry.recipe.adapter.*;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.net.packet.RecipeSyncPacket;
+import org.slf4j.Logger;
 
 import java.io.*;
 import java.lang.reflect.InvocationTargetException;
@@ -25,7 +27,7 @@ import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 public class DataLoader {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static void loadItemGroupsFromString(String json){
         int i = 0;
         GsonBuilder builder = new GsonBuilder();
@@ -39,7 +41,7 @@ public class DataLoader {
             Registries.ITEM_GROUPS.register(entry.getKey(),stacks);
             i++;
         }
-        System.out.printf("Registered %d item groups%n",i);
+        LOGGER.info("Registered {} item groups",i);
     }
 
     public static void loadItemGroupsFromFile(String path){
@@ -56,7 +58,7 @@ public class DataLoader {
             Registries.ITEM_GROUPS.register(entry.getKey(),stacks);
             i++;
         }
-        System.out.printf("Registered %d item groups from %s%n",i,path);
+        LOGGER.info("Registered {} item groups from {}",i,path);
     }
 
     public static void loadDataPacks(MinecraftAccessor mc){
@@ -73,7 +75,7 @@ public class DataLoader {
                     }
                     try {
                         try (ZipFile zipFile = new ZipFile(file)) {
-                            System.out.printf("Loading data from %s%n",file.getName());
+                            LOGGER.info("Loading data from {}",file.getName());
                             ZipEntry manifestEntry = zipFile.getEntry("manifest.json");
                             if(manifestEntry != null){
                                 try (InputStreamReader reader = new InputStreamReader(zipFile.getInputStream(manifestEntry))) {
@@ -88,7 +90,7 @@ public class DataLoader {
                                             String[] deconstructedKey = Registries.RECIPES.deconstructKey(removedRecipe);
                                             Registries.RECIPES.getGroupFromKey(removedRecipe).unregister(deconstructedKey[2]);
                                         }
-                                        System.out.printf("Removed %d recipes%n",removedRecipes.size());
+                                        LOGGER.info("Removed {} recipes",removedRecipes.size());
                                     }
                                     //let groups load first
                                     if(groupFiles != null && !groupFiles.isEmpty()){
@@ -97,7 +99,7 @@ public class DataLoader {
                                             if(groupFileEntry != null){
                                                 try (InputStream recipeFileInputStream = zipFile.getInputStream(groupFileEntry)) {
                                                     String contents = StringUtils.readInputString(recipeFileInputStream);
-                                                    System.out.printf("Loading item groups from %s/%s%n",file.getName(),groupFile);
+                                                    LOGGER.info("Loading item groups from {}/{}",file.getName(),groupFile);
                                                     loadItemGroupsFromString(contents);
                                                 }
                                             }
@@ -110,7 +112,7 @@ public class DataLoader {
                                             if(recipeFileEntry != null){
                                                 try (InputStream recipeFileInputStream = zipFile.getInputStream(recipeFileEntry)) {
                                                     String contents = StringUtils.readInputString(recipeFileInputStream);
-                                                    System.out.printf("Loading recipes from %s/%s%n",file.getName(),recipeFile);
+                                                    LOGGER.info("Loading recipes from {}/{}",file.getName(),recipeFile);
                                                     loadRecipesFromString(contents);
                                                 }
                                             }
@@ -120,8 +122,7 @@ public class DataLoader {
                             }
                         }
                     } catch (IOException | RuntimeException e){
-                        System.err.println("Failed to load data from "+file.getName());
-                        e.printStackTrace();
+                        LOGGER.error("Failed to load data from {}", file.getName(), e);
                     }
                 }
             }
@@ -163,7 +164,7 @@ public class DataLoader {
             Registries.RECIPES.addCustomRecipe(recipeId,recipe);
             i++;
         }
-        System.out.printf("Registered %d recipes from %s%n",i,path);
+        LOGGER.info("Registered {} recipes from {}",i,path);
     }
 
     public static void loadRecipesFromString(String json){
@@ -200,7 +201,7 @@ public class DataLoader {
             Registries.RECIPES.addCustomRecipe(recipeId,recipe);
             i++;
         }
-        System.out.printf("Registered %d recipes%n",i);
+        LOGGER.info("Registered {} recipes",i);
     }
 
     public static void loadRecipeFromServer(RecipeSyncPacket packet){
@@ -230,7 +231,7 @@ public class DataLoader {
         Gson gson = builder.create();
         RecipeEntryBase<?, ?, ?> recipe = gson.fromJson(recipeJson, recipeEntryClass);
         Registries.RECIPES.addCustomRecipe(recipeId,recipe);
-        //System.out.printf("Received recipe '%s' from server%n",recipeId);
+        //System.out.printf("Received recipe '%s' from server",recipeId);
     }
 
     public static String serializeRecipes(){
diff --git a/src/main/java/net/minecraft/core/data/registry/recipe/adapter/ItemStackJsonAdapter.java b/src/main/java/net/minecraft/core/data/registry/recipe/adapter/ItemStackJsonAdapter.java
index 6424f12d0..ae90a6116 100644
--- a/src/main/java/net/minecraft/core/data/registry/recipe/adapter/ItemStackJsonAdapter.java
+++ b/src/main/java/net/minecraft/core/data/registry/recipe/adapter/ItemStackJsonAdapter.java
@@ -7,17 +7,18 @@ import com.google.gson.JsonObject;
 import com.google.gson.JsonParseException;
 import com.google.gson.JsonSerializationContext;
 import com.google.gson.JsonSerializer;
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
 import net.minecraft.core.item.Item;
-import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.HardIllegalArgumentException;
 import net.minecraft.core.util.collection.NamespaceID;
+import org.slf4j.Logger;
 
 import java.lang.reflect.Type;
 
 public class ItemStackJsonAdapter implements JsonDeserializer<ItemStack>, JsonSerializer<ItemStack> {
+    private static final Logger LOGGER = LogUtils.getLogger();
     @Override
     public ItemStack deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
         JsonObject obj = json.getAsJsonObject();
@@ -34,7 +35,7 @@ public class ItemStackJsonAdapter implements JsonDeserializer<ItemStack>, JsonSe
                     throw new IllegalArgumentException("Item keys must either start with 'tile' or 'item' provided key '" + key + "' does not!");
                 }
             } catch (Exception e){
-                System.out.println("Failed to find item for key '" + key + "'!");
+                LOGGER.warn("Failed to find item for key '{}'!", key);
                 throw new IllegalArgumentException("Failed to find item for key '" + key + "'!\n" + e.getMessage());
             }
         } else {
diff --git a/src/main/java/net/minecraft/core/entity/EntityDispatcher.java b/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
index d33dc2a93..3cf341baf 100644
--- a/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
+++ b/src/main/java/net/minecraft/core/entity/EntityDispatcher.java
@@ -1,5 +1,6 @@
 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.projectile.*;
@@ -7,13 +8,14 @@ import net.minecraft.core.entity.vehicle.BoatEntity;
 import net.minecraft.core.entity.vehicle.MinecartEntity;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 import java.util.HashMap;
 import java.util.Map;
 
 public class EntityDispatcher
 {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     public EntityDispatcher()
     {
     }
@@ -26,12 +28,12 @@ public class EntityDispatcher
         classToIdMap.put(clazz, id);
     }
 
-    public static Entity createEntityInWorld(String s, World world)
+    public static Entity createEntityInWorld(String id, World world)
     {
         Entity entity = null;
         try
         {
-            Class<? extends Entity> clazz = keyToClassMap.get(s);
+            Class<? extends Entity> clazz = keyToClassMap.get(id);
             if(clazz != null)
             {
                 entity = clazz.getConstructor(World.class).newInstance(world);
@@ -39,8 +41,7 @@ public class EntityDispatcher
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
-            System.out.println("Error with id '" + s + "'");
+            LOGGER.error("Failed to instance entity id '{}'!", id, exception);
         }
         return entity;
     }
@@ -58,14 +59,14 @@ public class EntityDispatcher
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Failed to instance entity id '{}'!", compoundTag.getStringOrDefault("id", "UNKNOWN"), exception);
         }
         if(entity != null)
         {
             entity.load(compoundTag);
         } else
         {
-            System.out.println("Skipping Entity with id " + compoundTag.getString("id"));
+            LOGGER.warn("Skipping Entity with id {}", compoundTag.getStringOrDefault("id", "UNKNOWN"));
         }
         return entity;
     }
@@ -82,11 +83,11 @@ public class EntityDispatcher
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Failed to instance entity id '{}'!", id, exception);
         }
         if(entity == null)
         {
-            System.out.println("Skipping Entity with id " + id);
+            LOGGER.warn("Skipping Entity with id {}", id);
         }
         return entity;
     }
diff --git a/src/main/java/net/minecraft/core/entity/animal/Animal.java b/src/main/java/net/minecraft/core/entity/animal/Animal.java
index eabf88600..27a6ef249 100644
--- a/src/main/java/net/minecraft/core/entity/animal/Animal.java
+++ b/src/main/java/net/minecraft/core/entity/animal/Animal.java
@@ -6,7 +6,11 @@ package net.minecraft.core.entity.animal;
 //            MathHelper, AxisAlignedBB, NBTTagCompound
 
 import net.minecraft.core.block.tag.BlockTags;
+import net.minecraft.core.data.tag.Tag;
 import net.minecraft.core.entity.PathfinderMob;
+import net.minecraft.core.entity.player.Player;
+import net.minecraft.core.item.Item;
+import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.util.helper.MathHelper;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.world.World;
@@ -24,6 +28,26 @@ public abstract class Animal extends PathfinderMob
         scoreValue = 10;
     }
 
+    @Override
+    protected void updateAI()
+    {
+        Player closest = world.getClosestPlayer(x, y, z, 10);
+        if(closest != null){
+            if(isFavouriteItem(closest.getHeldItem())){
+                setTarget(closest);
+            } else {
+                setTarget(null);
+            }
+        }
+        super.updateAI();
+        if(entityToAttack != null) {
+            float distanceToEntity = entityToAttack.distanceTo(this);
+            if(distanceToEntity < 3) {
+                moveForward = 0;
+            }
+        }
+    }
+
     @Override
 	public int getMaxSpawnedInChunk()
     {
@@ -77,4 +101,8 @@ public abstract class Animal extends PathfinderMob
     {
         return 120;
     }
+
+    public boolean isFavouriteItem(ItemStack itemStack) {
+        return false;
+    }
 }
diff --git a/src/main/java/net/minecraft/core/entity/animal/ChickenMob.java b/src/main/java/net/minecraft/core/entity/animal/ChickenMob.java
index 1fb5661bb..58338031b 100644
--- a/src/main/java/net/minecraft/core/entity/animal/ChickenMob.java
+++ b/src/main/java/net/minecraft/core/entity/animal/ChickenMob.java
@@ -2,7 +2,9 @@ package net.minecraft.core.entity.animal;
 
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.WeightedRandomLootObject;
+import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.Items;
+import net.minecraft.core.item.tag.ItemTags;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.world.World;
 
@@ -98,4 +100,10 @@ public class ChickenMob extends Animal
     {
         return "mob.chickenhurt";
     }
+
+    @Override
+    public boolean isFavouriteItem(ItemStack itemStack)
+    {
+        return itemStack != null && itemStack.getItem().hasTag(ItemTags.CHICKENS_FAVOURITE_ITEM);
+    }
 }
diff --git a/src/main/java/net/minecraft/core/entity/animal/CowMob.java b/src/main/java/net/minecraft/core/entity/animal/CowMob.java
index 8b4c863ed..361b271f8 100644
--- a/src/main/java/net/minecraft/core/entity/animal/CowMob.java
+++ b/src/main/java/net/minecraft/core/entity/animal/CowMob.java
@@ -11,6 +11,7 @@ import net.minecraft.core.item.Items;
 import net.minecraft.core.item.EmptyBucketItem;
 import net.minecraft.core.item.ItemStack;
 import com.mojang.nbt.CompoundTag;
+import net.minecraft.core.item.tag.ItemTags;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.world.World;
 
@@ -72,4 +73,10 @@ public class CowMob extends Animal
         }
         return super.interact(entityplayer);
     }
+
+    @Override
+    public boolean isFavouriteItem(ItemStack itemStack)
+    {
+        return itemStack != null && itemStack.getItem().hasTag(ItemTags.COWS_FAVOURITE_ITEM);
+    }
 }
diff --git a/src/main/java/net/minecraft/core/entity/animal/PigMob.java b/src/main/java/net/minecraft/core/entity/animal/PigMob.java
index 6dd14e84a..7e0e09b61 100644
--- a/src/main/java/net/minecraft/core/entity/animal/PigMob.java
+++ b/src/main/java/net/minecraft/core/entity/animal/PigMob.java
@@ -8,9 +8,13 @@ package net.minecraft.core.entity.animal;
 
 import net.minecraft.core.WeightedRandomLootObject;
 import net.minecraft.core.achievement.Achievements;
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.LightningEntity;
 import net.minecraft.core.entity.monster.ZombiePigMob;
 import net.minecraft.core.entity.player.Player;
+import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.Items;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.util.collection.NamespaceID;
@@ -139,5 +143,13 @@ public class PigMob extends Animal
             ((Player) passenger).triggerAchievement(Achievements.FLY_PIG);
         }
     }
+    @Override
+    public boolean isFavouriteItem(ItemStack itemStack)
+    {
+        if(itemStack == null || itemStack.itemID >= Block.blocksList.length)
+            return false;
+
+        return Block.blocksList[itemStack.itemID].hasTag(BlockTags.PIGS_FAVOURITE_BLOCK);
+    }
     public List<WeightedRandomLootObject> burningMobDrops = new ArrayList<>();
 }
diff --git a/src/main/java/net/minecraft/core/entity/animal/SheepMob.java b/src/main/java/net/minecraft/core/entity/animal/SheepMob.java
index 4055780ce..b8df24232 100644
--- a/src/main/java/net/minecraft/core/entity/animal/SheepMob.java
+++ b/src/main/java/net/minecraft/core/entity/animal/SheepMob.java
@@ -3,6 +3,7 @@ package net.minecraft.core.entity.animal;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
+import net.minecraft.core.block.tag.BlockTags;
 import net.minecraft.core.entity.ItemEntity;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
@@ -258,6 +259,15 @@ public class SheepMob extends Animal
         {  0.1F,  0.1F,  0.1F  }  // Black
     };
 
+    @Override
+    public boolean isFavouriteItem(ItemStack itemStack)
+    {
+        if(itemStack == null || itemStack.itemID >= Block.blocksList.length)
+            return false;
+
+        return Block.blocksList[itemStack.itemID].hasTag(BlockTags.SHEEPS_FAVOURITE_BLOCK);
+    }
+
     public void setGrowthTimer(int growthTimer){
         this.growthTimer = growthTimer;
     }
diff --git a/src/main/java/net/minecraft/core/entity/animal/WolfMob.java b/src/main/java/net/minecraft/core/entity/animal/WolfMob.java
index ac4f3abc3..6a1305ce7 100644
--- a/src/main/java/net/minecraft/core/entity/animal/WolfMob.java
+++ b/src/main/java/net/minecraft/core/entity/animal/WolfMob.java
@@ -11,6 +11,7 @@ import net.minecraft.core.item.Item;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.item.material.ArmorMaterial;
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.MathHelper;
 import com.mojang.nbt.CompoundTag;
@@ -29,6 +30,7 @@ import java.util.*;
 
 public class WolfMob extends Animal
 {
+    public static final int DATA_OWNER_UUID = 17;
 
     public WolfMob(World world)
     {
@@ -50,9 +52,9 @@ public class WolfMob extends Animal
 	protected void defineSynchedData()
     {
         super.defineSynchedData();
-        entityData.define(15, ItemStack.NO_ITEM);
+        entityData.define(15, ItemStack.class);
         entityData.define(16, (byte) 0);
-        entityData.define(17, "");
+        entityData.define(DATA_OWNER_UUID, UUID.class);
         entityData.define(19, "");
     }
     @Override
@@ -76,7 +78,6 @@ public class WolfMob extends Animal
     public void setArmor(ItemStack stack) {
         ArmorMaterial material = null;
         armor = stack;
-        //noinspection SuspiciousMethodCalls
         if (stack != null && stack.getItem() instanceof IArmorItem && ARMOR_MATERIALS.containsValue(stack.getItem())){
             material = ((IArmorItem) stack.getItem()).getArmorMaterial();
         }
@@ -133,7 +134,7 @@ public class WolfMob extends Animal
         if (entity instanceof Player)
         {
             Player player = (Player) entity;
-            return !player.username.equalsIgnoreCase(getWolfOwner()) || isWolfSitting();
+            return !player.uuid.equals(getWolfOwner()) || isWolfSitting();
         }
 
         return true;
@@ -157,13 +158,7 @@ public class WolfMob extends Animal
             armor.writeToNBT(armorTag);
             tag.putCompound("Armor", armorTag);
         }
-        if(getWolfOwner() == null)
-        {
-            tag.putString("Owner", "");
-        } else
-        {
-            tag.putString("Owner", getWolfOwner());
-        }
+        UUIDHelper.writeToTag(tag, getWolfOwner(), "OwnerUUID");
     }
 
     @Override
@@ -204,10 +199,16 @@ public class WolfMob extends Animal
 
         }
 
-        String s = tag.getString("Owner");
-        if(!s.isEmpty())
-        {
-            setWolfOwner(s);
+        UUID ownerUUID = UUIDHelper.readFromTag(tag, "OwnerUUID");
+        if (ownerUUID == null) {
+            String s = tag.getString("Owner");
+            if (!s.isEmpty()) {
+                UUIDHelper.runConversionAction(s,
+                    (uuid) -> {setWolfOwner(uuid); setWolfTamed(true);},
+                    null);
+            }
+        } else {
+            setWolfOwner(ownerUUID);
             setWolfTamed(true);
         }
     }
@@ -287,7 +288,7 @@ public class WolfMob extends Animal
 
         if(!hasAttacked && !hasPath() && isWolfTamed() && vehicle == null)
         {
-            Player entityplayer = world.getPlayerEntityByName(getWolfOwner());
+            Player entityplayer = world.getPlayerEntityByUUID(getWolfOwner());
             if(entityplayer != null)
             {
                 float f = entityplayer.distanceTo(this);
@@ -296,15 +297,15 @@ public class WolfMob extends Animal
                     getPathOrWalkableBlock(entityplayer, f);
                 }
             } else
-            if(!isInWater())
+            if(isInWater())
             {
-                setWolfSitting(true);
+                setWolfSitting(false);
             }
         } else
         if(entityToAttack == null && !hasPath())
         {
             if(!isWolfTamed() && world.rand.nextInt(100) == 0){
-                List nearbySheep = world.getEntitiesWithinAABB(SheepMob.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
+                List<Entity> nearbySheep = world.getEntitiesWithinAABB(SheepMob.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
                 if (!nearbySheep.isEmpty()) {
                     setTarget((Entity) nearbySheep.get(world.rand.nextInt(nearbySheep.size())));
                 }
@@ -557,15 +558,15 @@ public class WolfMob extends Animal
                 }
                 if(attacker instanceof Mob)
                 {
-                    List list = world.getEntitiesWithinAABB(WolfMob.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
-                    Iterator iterator = list.iterator();
+                    List<Entity> list = world.getEntitiesWithinAABB(WolfMob.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
+                    Iterator<Entity> iterator = list.iterator();
                     do
                     {
                         if(!iterator.hasNext())
                         {
                             break;
                         }
-                        Entity entity1 = (Entity)iterator.next();
+                        Entity entity1 = iterator.next();
                         WolfMob entitywolf = (WolfMob)entity1;
                         if(!entitywolf.isWolfTamed() && entitywolf.entityToAttack == null)
                         {
@@ -580,7 +581,7 @@ public class WolfMob extends Animal
             } else
             if(attacker != this && attacker != null)
             {
-                if(isWolfTamed() && (attacker instanceof Player) && ((Player) attacker).username.equalsIgnoreCase(getWolfOwner()))
+                if(isWolfTamed() && (attacker instanceof Player) && ((Player) attacker).uuid.equals(getWolfOwner()))
                 {
                     return true;
                 }
@@ -674,7 +675,7 @@ public class WolfMob extends Animal
                         setPathToEntity(null);
                         setWolfSitting(true);
                         setHealthRaw(getMaxHealth());
-                        setWolfOwner(entityplayer.username);
+                        setWolfOwner(entityplayer.uuid);
                         showHeartsOrSmokeFX(true);
                         world.sendTrackedEntityStatusUpdatePacket(this, (byte)7);
                     } else
@@ -704,7 +705,7 @@ public class WolfMob extends Animal
                     return true;
                 }
             }
-            if (itemstack != null && itemstack.getItem() instanceof IArmorItem && entityplayer.username.equalsIgnoreCase(getWolfOwner())) {
+            if (itemstack != null && itemstack.getItem() instanceof IArmorItem && entityplayer.uuid.equals(getWolfOwner())) {
                 IArmorItem armorItem = (IArmorItem) itemstack.getItem();
                 if (armorItem.getArmorMaterial() != null && ARMOR_MATERIALS.containsValue(armorItem)) {
                     if (armor != null) {
@@ -721,7 +722,7 @@ public class WolfMob extends Animal
                     return true;
                 }
             }
-            if(entityplayer.username.equalsIgnoreCase(getWolfOwner()))
+            if(entityplayer.uuid.equals(getWolfOwner()))
             {
                 if(!world.isClientSide)
                 {
@@ -789,14 +790,14 @@ public class WolfMob extends Animal
         }
     }
 
-    public String getWolfOwner()
+    public UUID getWolfOwner()
     {
-        return entityData.getString(17);
+        return entityData.getUUID(DATA_OWNER_UUID);
     }
 
-    public void setWolfOwner(String s)
+    public void setWolfOwner(UUID uuid)
     {
-        entityData.set(17, s);
+        entityData.set(DATA_OWNER_UUID, uuid);
     }
 
     public boolean isWolfSitting()
@@ -834,17 +835,10 @@ public class WolfMob extends Animal
     }
 
     public ItemStack getWolfHeldItem(){
-        ItemStack stack = entityData.getItemStack(15);
-        if (stack == ItemStack.NO_ITEM){
-            stack = null;
-        }
-        return stack;
+        return entityData.getItemStack(15);
     }
 
     public void setWolfHeldItem(ItemStack itemStack){
-        if (itemStack == null){
-            itemStack = ItemStack.NO_ITEM;
-        }
         entityData.set(15, itemStack);
     }
 
diff --git a/src/main/java/net/minecraft/core/entity/player/Player.java b/src/main/java/net/minecraft/core/entity/player/Player.java
index 0e28885db..5810f7bed 100644
--- a/src/main/java/net/minecraft/core/entity/player/Player.java
+++ b/src/main/java/net/minecraft/core/entity/player/Player.java
@@ -70,6 +70,7 @@ import net.minecraft.server.entity.player.ServerPlayer;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
+import java.util.UUID;
 
 public abstract class Player extends Mob
 {
@@ -86,6 +87,7 @@ public abstract class Player extends Mob
     public boolean isSwinging;
     public int swingProgressInt;
     public String username;
+    public UUID uuid;
     public int dimension;
     public double xdO;
     public double ydO;
@@ -476,7 +478,7 @@ public abstract class Player extends Mob
         {
             if (((GoldenArrowProjectile) entityKilledBy).owner instanceof ServerPlayer)
             {
-                if (((ServerPlayer) ((GoldenArrowProjectile) entityKilledBy).owner).username.equals(username))
+                if (((ServerPlayer) ((GoldenArrowProjectile) entityKilledBy).owner).uuid.equals(uuid))
                 {
                     return getDisplayName() + deathMsgColor + " got gold in their eye.";
                 }
@@ -496,7 +498,7 @@ public abstract class Player extends Mob
             }
             else if (((ArrowProjectile) entityKilledBy).owner instanceof ServerPlayer)
             {
-                if (((ServerPlayer) ((ArrowProjectile) entityKilledBy).owner).username.equals(username))
+                if (((ServerPlayer) ((ArrowProjectile) entityKilledBy).owner).uuid.equals(uuid))
                 {
                     return getDisplayName() + deathMsgColor + " lost a game of Russian roulette.";
                 }
@@ -512,7 +514,7 @@ public abstract class Player extends Mob
         {
             if (((CannonballProjectile) entityKilledBy).owner instanceof ServerPlayer)
             {
-                if (((ServerPlayer) ((CannonballProjectile) entityKilledBy).owner).username.equals(username))
+                if (((ServerPlayer) ((CannonballProjectile) entityKilledBy).owner).uuid.equals(uuid))
                 {
                     return getDisplayName() + deathMsgColor + " jumped too high.";
                 }
@@ -761,24 +763,27 @@ public abstract class Player extends Mob
         return TextFormatting.get(chatColor) + name;
     }
 
-    public void displayGUIChest(Container iinventory)
+    public void displayContainerScreen(Container container)
     {
     }
 
-    public void displayGUIWorkbench(int i, int j, int k)
+    public void displayWorkbenchScreen(int x, int y, int z)
     {
     }
 
-    public void displayGUIEditLabel(ItemStack itemstack, int slot)
+    public void displayLabelEditorScreen(ItemStack itemStack, int slot)
     {
     }
 
-    public void displayGUIPaintingPicker()
+    public void displayPaintingPickerScreen()
     {
     }
 
-    public void displayGUIMobSpawnerPicker(int x, int y, int z) { }
-    public void displayGUIWandMonsterPicker(ItemStack stack) { }
+    public void displayMobPickerScreen(int x, int y, int z) { }
+
+    public void displayWandMobPickerScreen(ItemStack itemStack) { }
+
+    public void displayGuidebookScreen() { }
 
     public void onItemPickup(Entity entity, ItemStack item)
     {
@@ -879,7 +884,7 @@ public abstract class Player extends Mob
         if(attacker instanceof WolfMob)
         {
             WolfMob wolf = (WolfMob)attacker;
-            if(wolf.isWolfTamed() && username.equals(wolf.getWolfOwner()))
+            if(wolf.isWolfTamed() && uuid.equals(wolf.getWolfOwner()))
             {
                 return;
             }
@@ -891,7 +896,7 @@ public abstract class Player extends Mob
         List<Entity> list = world.getEntitiesWithinAABB(WolfMob.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
         for (Entity entity : list) {
             WolfMob wolf = (WolfMob) entity;
-            if (wolf.isWolfTamed() && wolf.getTarget() == null && username.equals(wolf.getWolfOwner()) && (!flag || !wolf.isWolfSitting())) {
+            if (wolf.isWolfTamed() && wolf.getTarget() == null && uuid.equals(wolf.getWolfOwner()) && (!flag || !wolf.isWolfSitting())) {
                 wolf.setTarget(attacker);
             }
         }
@@ -917,27 +922,23 @@ public abstract class Player extends Mob
         super.damageEntity(newDamage, damageType);
     }
     
-    public void displayGUIFurnace(FurnaceBlockEntity tileentityfurnace)
-    {
-    }
-
-    public void displayGUITrommel(TrommelBlockEntity tileEntityTrommel)
+    public void displayFurnaceScreen(FurnaceBlockEntity blockEntity)
     {
     }
 
-    public void displayGUIDispenser(DispenserBlockEntity tileentitydispenser)
+    public void displayTrommelScreen(TrommelBlockEntity blockEntity)
     {
     }
 
-    public void displayGUIGuidebook(DispenserBlockEntity tileentitydispenser)
+    public void displayDispenserScreen(DispenserBlockEntity blockEntity)
     {
     }
 
-    public void displayGUIEditSign(SignBlockEntity tileentitysign)
+    public void displaySignEditorScreen(SignBlockEntity blockEntity)
     {
     }
 
-    public void displayGUIEditFlag(FlagBlockEntity tileEntityFlag)
+    public void displayFlagEditorScreen(FlagBlockEntity blockEntity)
     {
     }
 
@@ -1029,7 +1030,7 @@ public abstract class Player extends Mob
     {
     }
 
-    public abstract void func_6420_o();
+    public abstract void animate4();
 
     public void onItemStackChanged(ItemStack itemstack)
     {
diff --git a/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java b/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
index 85d4b5a35..bb6b48861 100644
--- a/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
+++ b/src/main/java/net/minecraft/core/entity/vehicle/MinecartEntity.java
@@ -701,7 +701,7 @@ public class MinecartEntity extends Entity implements Container {
                 break;
             case CHEST_CART:
                 if(!world.isClientSide) {
-                    player.displayGUIChest(this);
+                    player.displayContainerScreen(this);
                 }
                 break;
             case FURNACE_CART:
diff --git a/src/main/java/net/minecraft/core/item/BucketItem.java b/src/main/java/net/minecraft/core/item/BucketItem.java
index b457c85eb..e4c1579ec 100644
--- a/src/main/java/net/minecraft/core/item/BucketItem.java
+++ b/src/main/java/net/minecraft/core/item/BucketItem.java
@@ -99,7 +99,7 @@ public class BucketItem extends Item
 				player.swingItem();
 				Block block1 = world.getBlock(x, y, z);
 				if(block1 != null) {
-					block1.dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null);
+					block1.dropBlockWithCause(world, EnumDropCause.WORLD, x, y, z, world.getBlockMetadata(x, y, z), null, null);
 				}
 				world.setBlockAndMetadataWithNotify(x, y, z, idToPlace, 0);
 			}
diff --git a/src/main/java/net/minecraft/core/item/FlagItem.java b/src/main/java/net/minecraft/core/item/FlagItem.java
index b7b6fe05e..4ca93387b 100644
--- a/src/main/java/net/minecraft/core/item/FlagItem.java
+++ b/src/main/java/net/minecraft/core/item/FlagItem.java
@@ -9,6 +9,7 @@ import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.enums.EnumBlockSoundEffectType;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.helper.Side;
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.core.world.World;
 
 public class FlagItem extends Item
@@ -40,7 +41,7 @@ public class FlagItem extends Item
 					return false;
 				}
 				flag.copyFlagNBT(flagData);
-                flagData.putString("Owner", entityplayer.username); // Sets the owner of the copied flag to the current player so they can actually modify the flag once they place it
+                UUIDHelper.writeToTag(flagData, entityplayer.uuid, "OwnerUUID"); // Sets the owner of the copied flag to the current player so they can actually modify the flag once they place it
 				stack.getData().putCompound("FlagData", flagData);
 				entityplayer.sendStatusMessage(I18n.getInstance().translateKey("flag.copied"));
 				return true;
@@ -82,9 +83,9 @@ public class FlagItem extends Item
                 tileentityflag.readFlagNBT(flagData);
             }
 
-            if (!world.isClientSide && tileentityflag.owner.isEmpty())
+            if (!world.isClientSide && tileentityflag.owner == null)
             {
-                entityplayer.displayGUIEditFlag(tileentityflag);
+                entityplayer.displayFlagEditorScreen(tileentityflag);
             }
         }
         return true;
diff --git a/src/main/java/net/minecraft/core/item/ItemStack.java b/src/main/java/net/minecraft/core/item/ItemStack.java
index 291847976..1497bf1fb 100644
--- a/src/main/java/net/minecraft/core/item/ItemStack.java
+++ b/src/main/java/net/minecraft/core/item/ItemStack.java
@@ -18,7 +18,6 @@ import org.jetbrains.annotations.Nullable;
 
 
 public final class ItemStack {
-    public static ItemStack NO_ITEM = new ItemStack();
 
     public int stackSize;
     public int animationsToGo;
diff --git a/src/main/java/net/minecraft/core/item/Items.java b/src/main/java/net/minecraft/core/item/Items.java
index 4ffc579cc..7a9d62652 100644
--- a/src/main/java/net/minecraft/core/item/Items.java
+++ b/src/main/java/net/minecraft/core/item/Items.java
@@ -259,8 +259,8 @@ public final class Items {
         TOOL_HOE_IRON = (new HoeToolItem("tool.hoe.iron", "minecraft:item/tool_hoe_iron", 16420, ToolMaterial.iron));
         TOOL_HOE_DIAMOND = (new HoeToolItem("tool.hoe.diamond", "minecraft:item/tool_hoe_diamond", 16421, ToolMaterial.diamond));
         TOOL_HOE_GOLD = (new HoeToolItem("tool.hoe.gold", "minecraft:item/tool_hoe_gold", 16422, ToolMaterial.gold));
-        SEEDS_WHEAT = (new SeedsItem("seeds.wheat", "minecraft:item/seeds_wheat", 16423, Blocks.CROPS_WHEAT));
-        WHEAT = (new Item("wheat", "minecraft:item/wheat", 16424));
+        SEEDS_WHEAT = (new SeedsItem("seeds.wheat", "minecraft:item/seeds_wheat", 16423, Blocks.CROPS_WHEAT)).withTags(ItemTags.CHICKENS_FAVOURITE_ITEM);
+        WHEAT = (new Item("wheat", "minecraft:item/wheat", 16424)).withTags(ItemTags.COWS_FAVOURITE_ITEM);
         FOOD_BREAD = (new FoodItem("food.bread", "minecraft:item/food_bread", 16425, 5, 12, false, 8));
 
         ARMOR_HELMET_LEATHER = (new ArmorItem("armor.helmet.leather", "minecraft:item/armor_helmet_leather", 16426, ArmorMaterial.LEATHER, IArmorItem.PIECE_HEAD));
@@ -385,7 +385,7 @@ public final class Items {
         ARMOR_BOOTS_ICESKATES = new IceSkatesItem("armor.boots.iceskates", "minecraft:item/armor_boots_iceskates", 16527);
         TOOL_SHEARS_STEEL = (ToolShearsItem)(new ToolShearsItem("tool.shears.steel", "minecraft:item/tool_shears_steel", 16528, ToolMaterial.steel)).setMaxDamage(ToolMaterial.steel.getDurability());
         TOOL_FIRESTRIKER_STEEL = (new FireStrikerItem("tool.firestriker.steel", "minecraft:item/tool_firestriker_steel", 16529)).setMaxDamage(ToolMaterial.steel.getDurability());
-        SEEDS_PUMPKIN = (new SeedsItem("seeds.pumpkin", "minecraft:item/seeds_pumpkin", 16530, Blocks.CROPS_PUMPKIN));
+        SEEDS_PUMPKIN = (new SeedsItem("seeds.pumpkin", "minecraft:item/seeds_pumpkin", 16530, Blocks.CROPS_PUMPKIN)).withTags(ItemTags.CHICKENS_FAVOURITE_ITEM);
         SEAT = new PlaceableItem("seat", "minecraft:item/seat", 16531, Blocks.SEAT).setMaxStackSize(64);
         DOOR_OAK_PAINTED = (new PaintedDoorItem("door.oak.painted", "minecraft:item/door_oak_painted", 16532, Blocks.DOOR_PLANKS_PAINTED_BOTTOM, Blocks.DOOR_PLANKS_PAINTED_TOP));
         DOOR_GLASS = (new DoorItem("door.glass", "minecraft:item/door_glass", 16533, Blocks.DOOR_GLASS_BOTTOM, Blocks.DOOR_GLASS_TOP));
diff --git a/src/main/java/net/minecraft/core/item/LabelItem.java b/src/main/java/net/minecraft/core/item/LabelItem.java
index dbcdd36e5..366a5ee7b 100644
--- a/src/main/java/net/minecraft/core/item/LabelItem.java
+++ b/src/main/java/net/minecraft/core/item/LabelItem.java
@@ -27,7 +27,7 @@ public class LabelItem extends Item
 		}
 
 		if(slot != -1) {
-			player.displayGUIEditLabel(stack, slot);
+			player.displayLabelEditorScreen(stack, slot);
 		}
 		return stack;
 	}
diff --git a/src/main/java/net/minecraft/core/item/PaintingItem.java b/src/main/java/net/minecraft/core/item/PaintingItem.java
index 3f1f78338..87d05b015 100644
--- a/src/main/java/net/minecraft/core/item/PaintingItem.java
+++ b/src/main/java/net/minecraft/core/item/PaintingItem.java
@@ -25,7 +25,7 @@ public class PaintingItem extends Item
     {
         if (!world.isClientSide && !entityplayer.isSneaking())
         {
-            entityplayer.displayGUIPaintingPicker();
+            entityplayer.displayPaintingPickerScreen();
         }
 
         return itemstack;
diff --git a/src/main/java/net/minecraft/core/item/RopeItem.java b/src/main/java/net/minecraft/core/item/RopeItem.java
index afb078b92..955f815e1 100644
--- a/src/main/java/net/minecraft/core/item/RopeItem.java
+++ b/src/main/java/net/minecraft/core/item/RopeItem.java
@@ -25,7 +25,10 @@ public class RopeItem extends PlaceableItem {
                     blockY = _y;
                     break;
                 } else if (world.getBlock(blockX, _y, blockZ) != blockToPlace) {
-                    break;
+                	if(side == Side.TOP) {
+                		break;
+                	}
+                    return true;
                 }
             }
 
diff --git a/src/main/java/net/minecraft/core/item/SignItem.java b/src/main/java/net/minecraft/core/item/SignItem.java
index 7d80dd70c..da58ccc12 100644
--- a/src/main/java/net/minecraft/core/item/SignItem.java
+++ b/src/main/java/net/minecraft/core/item/SignItem.java
@@ -61,7 +61,7 @@ public class SignItem extends Item
         if(tileentitysign != null)
         {
             tileentitysign.setOwner(entityplayer);
-            entityplayer.displayGUIEditSign(tileentitysign);
+            entityplayer.displaySignEditorScreen(tileentitysign);
         }
         return true;
     }
diff --git a/src/main/java/net/minecraft/core/item/SpawnerWandItem.java b/src/main/java/net/minecraft/core/item/SpawnerWandItem.java
index 019446cbd..5f6bde1f5 100644
--- a/src/main/java/net/minecraft/core/item/SpawnerWandItem.java
+++ b/src/main/java/net/minecraft/core/item/SpawnerWandItem.java
@@ -56,7 +56,7 @@ public class SpawnerWandItem
             }
         }
 
-        player.displayGUIWandMonsterPicker(itemstack);
+        player.displayWandMobPickerScreen(itemstack);
 
         return itemstack;
     }
diff --git a/src/main/java/net/minecraft/core/item/tag/ItemTags.java b/src/main/java/net/minecraft/core/item/tag/ItemTags.java
index 66e2e1847..d97e3c029 100644
--- a/src/main/java/net/minecraft/core/item/tag/ItemTags.java
+++ b/src/main/java/net/minecraft/core/item/tag/ItemTags.java
@@ -1,8 +1,9 @@
 package net.minecraft.core.item.tag;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.data.tag.Tag;
 import net.minecraft.core.item.Item;
-import net.minecraft.core.item.Items;
+import org.slf4j.Logger;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -10,7 +11,7 @@ import java.util.List;
 
 public abstract class ItemTags
 {
-    
+    private static final Logger LOGGER = LogUtils.getLogger();
     /**
      * Items with this tag will not destroy blocks in creative mode
      */
@@ -27,6 +28,14 @@ public abstract class ItemTags
      * Blocks like doors and levers should not be interacted with when mining them with an item with this tag
      */
     public static Tag<Item> PREVENT_LEFT_CLICK_INTERACTIONS = Tag.of("prevent_left_click_interactions");
+    /**
+     * Chickens will follow the player if they are holding this item.
+     */
+    public static Tag<Item> CHICKENS_FAVOURITE_ITEM = Tag.of("chickens_favourite_item");
+    /**
+     * Cows will follow the player if they are holding this item.
+     */
+    public static Tag<Item> COWS_FAVOURITE_ITEM = Tag.of("cows_favourite_item");
 
     public static List<Tag<Item>> TAG_LIST;
 
@@ -44,7 +53,7 @@ public abstract class ItemTags
                 }
                 catch (Exception e)
                 {
-                    e.printStackTrace();
+                    LOGGER.error("Failed to add tag '{}'!", field.getName(), e);
                 }
             }
         }
diff --git a/src/main/java/net/minecraft/core/lang/I18n.java b/src/main/java/net/minecraft/core/lang/I18n.java
index 808480f2e..7cbb05b27 100644
--- a/src/main/java/net/minecraft/core/lang/I18n.java
+++ b/src/main/java/net/minecraft/core/lang/I18n.java
@@ -1,5 +1,9 @@
 package net.minecraft.core.lang;
 
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
+import org.slf4j.Logger;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
@@ -11,6 +15,10 @@ import java.util.List;
 import java.util.stream.Stream;
 
 public class I18n {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private static I18n INSTANCE;
+    private Language currentLanguage;
+
     public static void initialize(String languageCode)
     {
         INSTANCE = new I18n(languageCode);
@@ -44,7 +52,7 @@ public class I18n {
             currentLanguage = Language.Default.INSTANCE;
         }
 
-        System.out.println(currentLanguage.keySize() + " Translation Keys");
+        LOGGER.info("{} Translation Keys", currentLanguage.keySize());
     }
 
     public static I18n getInstance()
@@ -66,16 +74,16 @@ public class I18n {
     {
         return translateKey(s + ".name");
     }
-    
+
     public String translateDescKey(String s)
     {
         return translateKey(s + ".desc");
     }
-    
+
     public Language getCurrentLanguage() {
         return currentLanguage;
     }
-	
+
 	public static InputStream getResourceAsStream(String path) {
         return I18n.class.getResourceAsStream(path);
 	}
@@ -123,13 +131,9 @@ public class I18n {
         }
         catch (Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Exception while loading all files in directory '{}' in translator!", directory, e);
         }
 
         return paths.toArray(new String[0]);
     }
-
-
-    private static I18n INSTANCE;
-    private Language currentLanguage;
 }
diff --git a/src/main/java/net/minecraft/core/lang/Language.java b/src/main/java/net/minecraft/core/lang/Language.java
index f07e367ff..e09fc852b 100644
--- a/src/main/java/net/minecraft/core/lang/Language.java
+++ b/src/main/java/net/minecraft/core/lang/Language.java
@@ -1,5 +1,8 @@
 package net.minecraft.core.lang;
 
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
+
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -21,6 +24,7 @@ import java.util.zip.ZipFile;
  * This method accepts a string as the language ID to be searched with and returns a newly constructed {@link Language} instance.
  */
 public class Language {
+    private static final Logger LOGGER = LogUtils.getLogger();
     /**
      * Used to store any missing translation keys so the log isn't spammed.
      */
@@ -78,7 +82,7 @@ public class Language {
                     {
                         entries.load(reader);
                     } catch (IOException e) {
-                        e.printStackTrace();
+                        LOGGER.error("Failed to load lang file '{}' in '{}'", entry, name, e);
                     }
                 }
                 else if (tips == null && entry.getName().equalsIgnoreCase("tips.txt"))
@@ -87,7 +91,7 @@ public class Language {
                     {
                         tips = Arrays.asList(reader.toString().split("\n"));
                     } catch (IOException e) {
-                        e.printStackTrace();
+                        LOGGER.error("Failed to load 'tips.txt' file in '{}'", name, e);
                     }
                 }
                 else if (entry.getName().equalsIgnoreCase("worldnames.txt"))
@@ -96,7 +100,7 @@ public class Language {
                     {
                         worldNameGenerator = new WorldNameGenerator(bufferedReader.lines().collect(Collectors.toList()));
                     } catch (IOException e) {
-                        e.printStackTrace();
+                        LOGGER.error("Failed to load 'worldnames.txt' file in '{}'", name, e);
                     }
                 }
             }
@@ -113,7 +117,7 @@ public class Language {
         String ret = entries.getProperty(key);
         if (ret == null) {
             if (!reportedMissingTranslations.contains(key)) {
-                System.err.println("Missing translation: " + key + "\n at " + Thread.currentThread().getStackTrace()[2]);
+                LOGGER.error("Missing translation: {}\n at {}", key, Thread.currentThread().getStackTrace()[2]);
                 reportedMissingTranslations.add(key);
             }
             // Try to find in default language then
@@ -182,7 +186,7 @@ public class Language {
                     try (InputStream stream = I18n.getResourceAsStream(path); InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
                         entries.load(reader);
                     } catch (IOException e) {
-                        e.printStackTrace();
+                        LOGGER.error("Failed to load lang file '{}' in '{}'", path, getName(), e);
                     }
                 }
                 else if (tips == null && path.endsWith("/tips.txt"))
@@ -195,7 +199,7 @@ public class Language {
                             tips.add(st);
                         }
                     } catch (IOException e) {
-                        e.printStackTrace();
+                        LOGGER.error("Failed to load 'tips.txt' file in '{}'", getName(), e);
                     }
                 }
                 else if (path.endsWith("/worldnames.txt"))
@@ -204,7 +208,7 @@ public class Language {
                     {
                         worldNameGenerator = new WorldNameGenerator(bufferedReader.lines().collect(Collectors.toList()));
                     } catch (IOException e) {
-                        e.printStackTrace();
+                        LOGGER.error("Failed to load 'worldnames.txt' file in '{}'", getName(), e);
                     }
                 }
             }
@@ -217,7 +221,7 @@ public class Language {
             if (ret == null) {
             	if(!reportedMissingTranslations.contains(key)) {
             		reportedMissingTranslations.add(key);
-            		System.err.println("Missing translation in default language: " + key + "\n at " + Thread.currentThread().getStackTrace()[3]);
+                    LOGGER.error("Missing translation in default language: {}\n at {}", key, Thread.currentThread().getStackTrace()[3]);
             	}
                 return key;
             }
diff --git a/src/main/java/net/minecraft/core/lang/LanguageSeeker.java b/src/main/java/net/minecraft/core/lang/LanguageSeeker.java
index 73cf25313..6f5e53f2f 100644
--- a/src/main/java/net/minecraft/core/lang/LanguageSeeker.java
+++ b/src/main/java/net/minecraft/core/lang/LanguageSeeker.java
@@ -4,9 +4,10 @@ import com.b100.json.JsonParser;
 import com.b100.json.element.JsonArray;
 import com.b100.json.element.JsonElement;
 import com.b100.json.element.JsonObject;
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.Global;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
 
 import java.io.*;
 import java.nio.charset.StandardCharsets;
@@ -18,11 +19,11 @@ import java.util.zip.ZipFile;
  * Utility class for handling languages.
  */
 public class LanguageSeeker {
+    private static final Logger LOGGER = LogUtils.getLogger();
     /**
      * The directory to load languages from.
      */
     public static final File LANGUAGE_DIR = Global.accessor.getMinecraftDir().toPath().resolve("languages").toFile();
-
     /**
      * Finds a language with a specific ID. If nothing is found, <tt>null</tt> is returned.
      *
@@ -103,7 +104,7 @@ public class LanguageSeeker {
                             }
                             ret.add(new Language(langId, langName, langRegion, langCredits, zip));
                         } catch (IOException e) {
-                            e.printStackTrace();
+                            LOGGER.error("Exception loading json 'lang_info.json'!", e);
                         }
                     }
                 }
diff --git a/src/main/java/net/minecraft/core/net/ICommandListener.java b/src/main/java/net/minecraft/core/net/ICommandListener.java
index 4afafd945..8dd5f436a 100644
--- a/src/main/java/net/minecraft/core/net/ICommandListener.java
+++ b/src/main/java/net/minecraft/core/net/ICommandListener.java
@@ -4,7 +4,7 @@ package net.minecraft.core.net;
 public interface ICommandListener
 {
 
-    void log(String s);
+    void logInfo(String s);
 
     String getUsername();
 }
diff --git a/src/main/java/net/minecraft/core/net/NetworkManager.java b/src/main/java/net/minecraft/core/net/NetworkManager.java
index 7cf24ffd7..684d1fa97 100644
--- a/src/main/java/net/minecraft/core/net/NetworkManager.java
+++ b/src/main/java/net/minecraft/core/net/NetworkManager.java
@@ -1,18 +1,17 @@
 package net.minecraft.core.net;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.net.handler.PacketHandler;
 import net.minecraft.core.net.packet.Packet;
+import org.slf4j.Logger;
 
 import java.io.*;
 import java.net.*;
 import java.util.*;
 
-// Referenced classes of package net.minecraft.src:
-//            NetworkReaderThread, NetworkWriterThread, Packet, PacketHandler,
-//            NetworkMasterThread, ThreadCloseConnection
-
 public class NetworkManager
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
 	private final boolean silent;
 	public static int PACKET_DELAY = 100;
 
@@ -110,7 +109,7 @@ public class NetworkManager
                         while (sendPacket());
                         try {
                             sleep(PACKET_DELAY);
-                        } catch (InterruptedException e) { }
+                        } catch (InterruptedException ignored) { }
                         try {
                             if (dos != null) {
                                 dos.flush();
@@ -118,8 +117,9 @@ public class NetworkManager
                         } catch (IOException e) {
                             if (!disconnected) {
                                 onNetworkError(e);
+                            } else {
+                                LOGGER.error("IO Exception while flushing Data Output Stream!", e);
                             }
-                            e.printStackTrace();
                         }
                     }
                 }
@@ -232,21 +232,21 @@ public class NetworkManager
 
     private void onNetworkError(Exception exception)
     {
-        if (!silent) exception.printStackTrace();
+        if (!silent) LOGGER.error("Unexpected network error!", exception);
         networkShutdown("disconnect.genericReason", new Object[] {
-            (new StringBuilder()).append("Internal exception: ").append(exception.toString()).toString()
+            "Internal exception: " + exception.toString()
         });
     }
 
-    public void networkShutdown(String s, Object[] aobj)
+    public void networkShutdown(String reason, Object[] reasonObjects)
     {
         if(!running)
         {
             return;
         }
         disconnected = true;
-        disconnectReason = s;
-        disconnectReasonObjects = aobj;
+        disconnectReason = reason;
+        disconnectReasonObjects = reasonObjects;
         new Thread(() -> {
             try
             {
@@ -257,7 +257,7 @@ public class NetworkManager
                     {
                         readThread.stop();
                     }
-                    catch(Throwable throwable) { }
+                    catch(Throwable ignored) { }
                 }
                 if(writeThread.isAlive())
                 {
@@ -265,12 +265,12 @@ public class NetworkManager
                     {
                         writeThread.stop();
                     }
-                    catch(Throwable throwable1) { }
+                    catch(Throwable ignored) { }
                 }
             }
-            catch(InterruptedException interruptedexception)
+            catch(InterruptedException e)
             {
-                interruptedexception.printStackTrace();
+                LOGGER.error("Interrupted while stopping read/write threads!", e);
             }
 
         }).start();
@@ -280,19 +280,19 @@ public class NetworkManager
             dis.close();
             dis = null;
         }
-        catch(Throwable throwable) { }
+        catch(Throwable ignored) { }
         try
         {
             dos.close();
             dos = null;
         }
-        catch(Throwable throwable1) { }
+        catch(Throwable ignored) { }
         try
         {
             socket.close();
             socket = null;
         }
-        catch(Throwable throwable2) { }
+        catch(Throwable ignored) { }
     }
 
     public void processReadPackets()
@@ -346,7 +346,7 @@ public class NetworkManager
             }
             catch(Exception exception)
             {
-                exception.printStackTrace();
+                LOGGER.error("Exception on Server Shutdown!", exception);
             }
         }).start();
     }
diff --git a/src/main/java/net/minecraft/core/net/PlayerProfile.java b/src/main/java/net/minecraft/core/net/PlayerProfile.java
index 102c74bb7..f6eaffd7b 100644
--- a/src/main/java/net/minecraft/core/net/PlayerProfile.java
+++ b/src/main/java/net/minecraft/core/net/PlayerProfile.java
@@ -2,11 +2,14 @@ package net.minecraft.core.net;
 
 import net.minecraft.core.net.command.TextFormatting;
 
+import java.util.UUID;
+
 public class PlayerProfile {
 
-    public PlayerProfile(String name, String nickname, int score, byte chatColour, boolean isOperator)
+    public PlayerProfile(String name, String nickname, UUID uuid, int score, byte chatColour, boolean isOperator)
     {
         playerName = name;
+        this.uuid = uuid;
         this.nickname = nickname;
         scoreTotal = score;
         this.chatColor = chatColour;
@@ -24,6 +27,7 @@ public class PlayerProfile {
     }
 
     public String playerName;
+    public UUID uuid;
     public String nickname;
     public int scoreTotal;
     public byte chatColor;
diff --git a/src/main/java/net/minecraft/core/net/PropertyManager.java b/src/main/java/net/minecraft/core/net/PropertyManager.java
index e2d199fe3..891935365 100644
--- a/src/main/java/net/minecraft/core/net/PropertyManager.java
+++ b/src/main/java/net/minecraft/core/net/PropertyManager.java
@@ -1,6 +1,7 @@
 package net.minecraft.core.net;
 
-import org.apache.log4j.Logger;
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
 
 
 import java.io.*;
@@ -20,16 +21,16 @@ public class PropertyManager
         {
             try
             {
-                serverProperties.load(new FileInputStream(file));
+                serverProperties.load(Files.newInputStream(file.toPath()));
             }
             catch(Exception exception)
             {
-                logger.warn( (new StringBuilder()).append("Failed to load ").append(file).toString(), exception);
+                logger.warn("Failed to load " + file, exception);
                 generateNewProperties();
             }
         } else
         {
-            logger.warn( (new StringBuilder()).append(file).append(" does not exist").toString());
+            logger.warn(file + " does not exist");
             generateNewProperties();
         }
     }
@@ -105,7 +106,7 @@ public class PropertyManager
         serverProperties.setProperty(s1, s2);
     }
 
-    public static Logger logger = Logger.getLogger("Minecraft");
+    public static Logger logger = LogUtils.getLogger();
     private Properties serverProperties;
     private File serverPropertiesFile;
 
diff --git a/src/main/java/net/minecraft/core/net/SavedServerList.java b/src/main/java/net/minecraft/core/net/SavedServerList.java
index d71e5ee94..84fbeeaf3 100644
--- a/src/main/java/net/minecraft/core/net/SavedServerList.java
+++ b/src/main/java/net/minecraft/core/net/SavedServerList.java
@@ -4,6 +4,7 @@ import com.mojang.nbt.Tag;
 import com.mojang.nbt.CompoundTag;
 
 import java.io.*;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -20,7 +21,7 @@ public class SavedServerList
         serverList.serverListFile = file;
         try
         {
-            FileInputStream fileStream = new FileInputStream(file);
+            InputStream fileStream = Files.newInputStream(file.toPath());
             DataInputStream dataStream = new DataInputStream(fileStream);
             CompoundTag tag = new CompoundTag();
             tag.read(dataStream);
@@ -34,6 +35,7 @@ public class SavedServerList
             }
 
             fileStream.close();
+            dataStream.close();
         }
         catch (Exception e)
         {
@@ -47,7 +49,7 @@ public class SavedServerList
     {
         try
         {
-            FileOutputStream fileStream = new FileOutputStream(serverListFile);
+            OutputStream fileStream = Files.newOutputStream(serverListFile.toPath());
             DataOutputStream dataStream = new DataOutputStream(fileStream);
             CompoundTag tag = new CompoundTag();
 
@@ -58,6 +60,7 @@ public class SavedServerList
 
             tag.write(dataStream);
             fileStream.close();
+            dataStream.close();
         }
         catch (Exception ignored)
         {
diff --git a/src/main/java/net/minecraft/core/net/ServerData.java b/src/main/java/net/minecraft/core/net/ServerData.java
index 308fcc8de..9caef981d 100644
--- a/src/main/java/net/minecraft/core/net/ServerData.java
+++ b/src/main/java/net/minecraft/core/net/ServerData.java
@@ -1,10 +1,6 @@
 package net.minecraft.core.net;
 
 import com.mojang.nbt.CompoundTag;
-import org.apache.logging.log4j.core.jmx.Server;
-
-import java.time.LocalDateTime;
-import java.time.ZoneOffset;
 
 public class ServerData
 {
diff --git a/src/main/java/net/minecraft/core/net/command/ClientCommandHandler.java b/src/main/java/net/minecraft/core/net/command/ClientCommandHandler.java
index fd15d7c8b..2025f9f48 100644
--- a/src/main/java/net/minecraft/core/net/command/ClientCommandHandler.java
+++ b/src/main/java/net/minecraft/core/net/command/ClientCommandHandler.java
@@ -16,19 +16,19 @@ public class ClientCommandHandler implements CommandHandler{
 	}
 	
 	@Override
-	public void sendMessageToAdmins(String msg) {
+	public synchronized void sendMessageToAdmins(String msg) {
 		if(minecraft.theWorld.getLevelData().getCheatsEnabled()) {
-			minecraft.ingameGUI.addChatMessage(msg);
+			minecraft.ingameHud.addChatMessage(msg);
 		}
 	}
 
 	@Override
-	public void sendMessageToAllPlayers(String msg) {
-		minecraft.ingameGUI.addChatMessage(msg);
+	public synchronized void sendMessageToAllPlayers(String msg) {
+		minecraft.ingameHud.addChatMessage(msg);
 	}
 
 	@Override
-	public @Nullable Player getPlayer(String name) {
+	public synchronized @Nullable Player getPlayer(String name) {
 		if(minecraft.thePlayer.username.equalsIgnoreCase(name)) {
 			return minecraft.thePlayer;
 		}else {
@@ -37,24 +37,24 @@ public class ClientCommandHandler implements CommandHandler{
 	}
 
 	@Override
-	public void sendMessageToPlayer(Player player, String msg) {
+	public synchronized void sendMessageToPlayer(Player player, String msg) {
 		if(player == minecraft.thePlayer) {
-			minecraft.ingameGUI.addChatMessage(msg);
+			minecraft.ingameHud.addChatMessage(msg);
 		}
 	}
 
 	@Override
-	public boolean playerExists(String name) {
+	public synchronized boolean playerExists(String name) {
 		return name.equalsIgnoreCase(minecraft.thePlayer.username);
 	}
 
 	@Override
-	public void sendCommandFeedback(CommandSender sender, String message) {
+	public synchronized void sendCommandFeedback(CommandSender sender, String message) {
 		sender.sendMessage(message);
 	}
 	
 	@Override
-	public World getWorld(int dimension) {
+	public synchronized World getWorld(int dimension) {
 		return minecraft.theWorld;
 	}
 
diff --git a/src/main/java/net/minecraft/core/net/command/ClientPlayerCommandSender.java b/src/main/java/net/minecraft/core/net/command/ClientPlayerCommandSender.java
index 18846ffa7..404335045 100644
--- a/src/main/java/net/minecraft/core/net/command/ClientPlayerCommandSender.java
+++ b/src/main/java/net/minecraft/core/net/command/ClientPlayerCommandSender.java
@@ -24,7 +24,7 @@ public class ClientPlayerCommandSender extends PlayerCommandSender{
 
 	@Override
 	public void sendMessage(String string) {
-		minecraft.ingameGUI.addChatMessage(string);
+		minecraft.ingameHud.addChatMessage(string);
 	}
 
 	@Override
diff --git a/src/main/java/net/minecraft/core/net/command/ConsoleCommandSender.java b/src/main/java/net/minecraft/core/net/command/ConsoleCommandSender.java
index 3c6d4e34e..16eb8d552 100644
--- a/src/main/java/net/minecraft/core/net/command/ConsoleCommandSender.java
+++ b/src/main/java/net/minecraft/core/net/command/ConsoleCommandSender.java
@@ -1,9 +1,10 @@
 package net.minecraft.core.net.command;
 
-import org.apache.log4j.Logger;
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.util.helper.LoggedPrintStream;
+import org.slf4j.Logger;
 
 import net.minecraft.core.entity.player.Player;
-import net.minecraft.core.util.helper.LogPrintStream;
 import net.minecraft.core.world.World;
 import net.minecraft.server.MinecraftServer;
 
@@ -11,7 +12,7 @@ public class ConsoleCommandSender implements CommandSender{
 	
 	public final MinecraftServer minecraftServer;
 	
-	private static final Logger logger = Logger.getLogger("Minecraft");
+	private static final Logger LOGGER = LogUtils.getLogger();
 	
 	public ConsoleCommandSender(MinecraftServer minecraftServer) {
 		this.minecraftServer = minecraftServer;
@@ -29,7 +30,7 @@ public class ConsoleCommandSender implements CommandSender{
 
 	@Override
 	public void sendMessage(String string) {
-		logger.info(LogPrintStream.removeColorCodes(string));
+		LOGGER.info(LoggedPrintStream.removeColorCodes(string));
 	}
 
 	@Override
diff --git a/src/main/java/net/minecraft/core/net/command/ServerCommand.java b/src/main/java/net/minecraft/core/net/command/ServerCommand.java
index f9cc29a89..7a7f80b14 100644
--- a/src/main/java/net/minecraft/core/net/command/ServerCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/ServerCommand.java
@@ -16,7 +16,7 @@ public abstract class ServerCommand extends Command{
 	{
 		String formattedMessage = name + TextFormatting.LIGHT_GRAY +  ": " + message;
 		server.playerList.sendChatMessageToAllOps(TextFormatting.LIGHT_GRAY + "(" + formattedMessage + ")");
-		MinecraftServer.logger.info(formattedMessage);
+		MinecraftServer.LOGGER.info(formattedMessage);
 	}
 
 }
diff --git a/src/main/java/net/minecraft/core/net/command/ServerCommandHandler.java b/src/main/java/net/minecraft/core/net/command/ServerCommandHandler.java
index c9b8f8800..b147a3fe5 100644
--- a/src/main/java/net/minecraft/core/net/command/ServerCommandHandler.java
+++ b/src/main/java/net/minecraft/core/net/command/ServerCommandHandler.java
@@ -16,49 +16,49 @@ public class ServerCommandHandler implements CommandHandler{
 	}
 	
 	@Override
-	public void sendMessageToAdmins(String msg) {
+	public synchronized void sendMessageToAdmins(String msg) {
 		minecraftServer.playerList.sendChatMessageToAllOps(msg);
 	}
 
 	@Override
-	public @Nullable Player getPlayer(String name) {
+	public synchronized @Nullable Player getPlayer(String name) {
 		return minecraftServer.playerList.getPlayerEntity(name);
 	}
 
 	@Override
-	public void sendMessageToAllPlayers(String msg) {
+	public synchronized void sendMessageToAllPlayers(String msg) {
 		minecraftServer.playerList.sendEncryptedChatToAllPlayers(msg);
 	}
 
 	@Override
-	public void sendMessageToPlayer(Player player, String messsage) {
+	public synchronized void sendMessageToPlayer(Player player, String messsage) {
 		minecraftServer.playerList.sendPacketToPlayer(player.username, new ChatPacket(messsage, AES.keyChain.get(player.username)));
 	}
 
 	@Override
-	public boolean playerExists(String name) {
+	public synchronized boolean playerExists(String name) {
 		return minecraftServer.playerList.getPlayerEntity(name) != null;
 	}
 
 	@Override
-	public void sendCommandFeedback(CommandSender sender, String message) {
+	public synchronized void sendCommandFeedback(CommandSender sender, String message) {
 		sender.sendMessage(message);
 		
 		String message2 = "\2477" + sender.getName() + ": " + message;
 		
 		for(Player p : minecraftServer.playerList.playerEntities) {
-			if(minecraftServer.playerList.isOp(p.username)) {
+			if(minecraftServer.playerList.isOp(p.uuid)) {
 				if(sender.getPlayer() == null || sender.getPlayer() != p) {
 					sendMessageToPlayer(p, message2);
 				}
 			}
 		}
 		
-		minecraftServer.log(message2);
+		minecraftServer.logInfo(message2);
 	}
 
 	@Override
-	public World getWorld(int dimension) {
+	public synchronized World getWorld(int dimension) {
 		return minecraftServer.getDimensionWorld(dimension);
 	}
 
diff --git a/src/main/java/net/minecraft/core/net/command/ServerPlayerCommandSender.java b/src/main/java/net/minecraft/core/net/command/ServerPlayerCommandSender.java
index 88b6cbfb7..623468b23 100644
--- a/src/main/java/net/minecraft/core/net/command/ServerPlayerCommandSender.java
+++ b/src/main/java/net/minecraft/core/net/command/ServerPlayerCommandSender.java
@@ -19,7 +19,7 @@ public class ServerPlayerCommandSender extends PlayerCommandSender{
 
 	@Override
 	public boolean isAdmin() {
-		return server.playerList.isOp(player.username);
+		return server.playerList.isOp(player.uuid);
 	}
 
 	@Override
diff --git a/src/main/java/net/minecraft/core/net/command/commands/GenerateCommand.java b/src/main/java/net/minecraft/core/net/command/commands/GenerateCommand.java
index 77dade245..c7a655604 100644
--- a/src/main/java/net/minecraft/core/net/command/commands/GenerateCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/commands/GenerateCommand.java
@@ -1,6 +1,8 @@
 package net.minecraft.core.net.command.commands;
 
 import com.b100.utils.Utils;
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.net.command.Command;
@@ -12,6 +14,7 @@ import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.util.helper.ReflectionHelper;
 import net.minecraft.core.world.generate.feature.MethodParametersAnnotation;
 import net.minecraft.core.world.generate.feature.WorldFeature;
+import org.slf4j.Logger;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Parameter;
@@ -24,8 +27,8 @@ import java.util.Random;
 import java.util.Set;
 
 public class GenerateCommand extends Command {
-	
-	private static Map<String, Class<? extends WorldFeature>> worldFeatures = new HashMap<>();
+	private static final Logger LOGGER = LogUtils.getLogger();
+	private static final Map<String, Class<? extends WorldFeature>> worldFeatures = new HashMap<>();
 
 	public GenerateCommand() {
 		super("generate", "gen");
@@ -173,7 +176,7 @@ public class GenerateCommand extends Command {
 				}
 			}
 		} catch (Exception e) {
-			e.printStackTrace();
+			LOGGER.error("Reflection hacking WorldFeatures failed!", e);
 		}
 	}
 }
diff --git a/src/main/java/net/minecraft/core/net/command/commands/PlaySoundCommand.java b/src/main/java/net/minecraft/core/net/command/commands/PlaySoundCommand.java
index 4f0997f3d..eb0586d4f 100644
--- a/src/main/java/net/minecraft/core/net/command/commands/PlaySoundCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/commands/PlaySoundCommand.java
@@ -10,6 +10,8 @@ import net.minecraft.core.net.packet.PlaySoundEffectDirectPacket;
 import net.minecraft.core.sound.SoundTypes;
 import net.minecraft.core.sound.SoundCategory;
 
+import java.util.Locale;
+
 public class PlaySoundCommand extends Command {
     public PlaySoundCommand() {
         super("playsound", "play");
@@ -33,7 +35,7 @@ public class PlaySoundCommand extends Command {
         float pitch = 1f;
         if (args.length >= 2){
             soundPath = args[0];
-            soundType = SoundCategory.valueOf(args[1]);
+            soundType = SoundCategory.valueOf(args[1].toUpperCase(Locale.ROOT));
             if (args.length >= 5){
                 x = Float.parseFloat(args[2]);
                 y = Float.parseFloat(args[3]);
@@ -45,11 +47,11 @@ public class PlaySoundCommand extends Command {
             }
         }
         if (soundPath != null && x != null){
-        	int soundId = SoundTypes.getSoundId(soundPath);
-        	if(soundId < 0) {
-        		throw new CommandError("Invalid Sound: '" + soundPath + "'!");
-        	}
             if (handler instanceof ServerCommandHandler){
+                int soundId = SoundTypes.getSoundId(soundPath);
+                if(soundId < 0) {
+                    throw new CommandError("Invalid Sound: '" + soundPath + "'!");
+                }
                 ((ServerCommandHandler) handler).minecraftServer.playerList.sendPacketToPlayersAroundPoint(x, y,z, 128f, dimension, new PlaySoundEffectDirectPacket(soundId, soundType, x, y, z, volume, pitch));
             } else if (handler instanceof ClientCommandHandler){
                 ((ClientCommandHandler) handler).minecraft.sndManager.playSoundAt(soundPath, soundType, x, y, z, volume, pitch);
diff --git a/src/main/java/net/minecraft/core/net/command/commands/SummonCommand.java b/src/main/java/net/minecraft/core/net/command/commands/SummonCommand.java
index a931a08ee..05aadab7b 100644
--- a/src/main/java/net/minecraft/core/net/command/commands/SummonCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/commands/SummonCommand.java
@@ -2,6 +2,7 @@ package net.minecraft.core.net.command.commands;
 
 import java.util.Set;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityDispatcher;
 import net.minecraft.core.world.World;
@@ -12,9 +13,11 @@ import net.minecraft.core.net.command.CommandHandler;
 import net.minecraft.core.net.command.CommandSender;
 import net.minecraft.core.net.command.LocationTarget;
 import net.minecraft.core.net.command.PlayerCommandSender;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
 
 public class SummonCommand extends Command{
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public SummonCommand() {
 		super("summon");
 	}
@@ -94,11 +97,11 @@ public class SummonCommand extends Command{
 		}
 	}
 	
-	public static Entity createEntity(Class<? extends Entity> entityClass, World world) {
+	public static Entity createEntity(@NotNull Class<? extends Entity> entityClass, World world) {
 		try {
 			return entityClass.getConstructor(World.class).newInstance(world);
 		}catch (Exception e) {
-			e.printStackTrace();
+            LOGGER.warn("Could not create Entity for class '{}'!", entityClass.getSimpleName());
 			throw new CommandError("Could not create Entity!");
 		}
 	}
diff --git a/src/main/java/net/minecraft/core/net/command/commands/TeleportCommand.java b/src/main/java/net/minecraft/core/net/command/commands/TeleportCommand.java
index f60a7f9dd..5f6db4c01 100644
--- a/src/main/java/net/minecraft/core/net/command/commands/TeleportCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/commands/TeleportCommand.java
@@ -1,5 +1,7 @@
 package net.minecraft.core.net.command.commands;
 
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.server.entity.player.ServerPlayer;
@@ -10,18 +12,19 @@ import net.minecraft.core.net.command.CommandHandler;
 import net.minecraft.core.net.command.CommandSender;
 import net.minecraft.core.net.command.PlayerCommandSender;
 import net.minecraft.core.net.command.ServerCommandHandler;
+import org.slf4j.Logger;
 
 public class TeleportCommand extends Command{
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public TeleportCommand() {
 		super("tp");
 	}
 
 	@Override
 	public boolean execute(CommandHandler handler, CommandSender sender, String[] args) {
-		System.out.println("TP Command");
-		System.out.println("handler: "+handler);
-		System.out.println("sender: "+sender);
+		LOGGER.info("TP Command");
+        LOGGER.info("handler: {}", handler);
+        LOGGER.info("sender: {}", sender);
 		
 		boolean sentByPlayer = sender instanceof PlayerCommandSender;
 		
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/BanCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/BanCommand.java
index d4c04e74a..da7a5e8bf 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/BanCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/BanCommand.java
@@ -1,9 +1,9 @@
 package net.minecraft.core.net.command.servercommands;
 
-import net.minecraft.client.entity.player.RemotePlayer;
 import net.minecraft.core.net.command.CommandHandler;
 import net.minecraft.core.net.command.CommandSender;
 import net.minecraft.core.net.command.ServerCommand;
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.server.MinecraftServer;
 import net.minecraft.server.entity.player.ServerPlayer;
 
@@ -19,14 +19,21 @@ public class BanCommand extends ServerCommand {
 
         String nameToBan = args[0];
 
-        server.playerList.banPlayer(nameToBan);
-        sendNoticeToOps(senderName, "Banning " + nameToBan);
+
         ServerPlayer player = server.playerList.getPlayerEntity(nameToBan);
-        if(player != null)
-        {
+        if(player != null) {
+            server.playerList.banPlayer(player.uuid);
+            sendNoticeToOps(senderName, "Banning " + nameToBan);
             player.playerNetServerHandler.kickPlayer("Banned by admin");
+        } else {
+            UUIDHelper.runConversionAction(nameToBan, (uuid) -> {
+                server.playerList.banPlayer(uuid);
+                sendNoticeToOps(senderName, "Banning " + nameToBan);
+            }, (username) -> handler.sendCommandFeedback(sender,"Could not retrieve UUID of player '" + username + "'"));
         }
 
+
+
         return true;
     }
 
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/ColorCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/ColorCommand.java
index 5c11a6ea7..8fd585dbd 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/ColorCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/ColorCommand.java
@@ -57,7 +57,7 @@ public class ColorCommand extends ServerCommand {
 		newColor = (byte) color.id;
 		player.chatColor = newColor;
 		player.hadNicknameSet = true;
-		player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.score, newColor, true, player.isOperator()));
+		player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, newColor, true, player.isOperator()));
 		sender.sendMessage(TextFormatting.LIGHT_GRAY + "You changed your color to " + color + color.getNames()[0]);
 		return true;
 	}
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/DeopCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/DeopCommand.java
index 282120958..e37bc3777 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/DeopCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/DeopCommand.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.net.command.servercommands;
 
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.server.MinecraftServer;
 import net.minecraft.server.entity.player.ServerPlayer;
 import net.minecraft.core.net.packet.UpdatePlayerProfilePacket;
@@ -19,18 +20,25 @@ public class DeopCommand extends ServerCommand{
 		if(args.length == 0) return false;
 		String name = args[0];
 
-		boolean playerWasOp = server.playerList.isOp(name);
-
-		server.playerList.deopPlayer(name);
-
-		if (playerWasOp) {
-			handler.sendCommandFeedback(sender, "De-opping "+name);
-		}
-
 		ServerPlayer player = (ServerPlayer) handler.getPlayer(name);
-		if(player != null && playerWasOp) {
-			handler.sendMessageToPlayer(player, TextFormatting.YELLOW + "You are no longer op!");
-			player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.score, player.chatColor, true, player.isOperator()));
+		if(player != null) {
+			boolean wasOp = player.isOperator();
+
+			server.playerList.deopPlayer(player.uuid);
+			if (wasOp) {
+				handler.sendCommandFeedback(sender, "De-opping " + name);
+				handler.sendMessageToPlayer(player, TextFormatting.YELLOW + "You are no longer op!");
+				player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, player.chatColor, true, player.isOperator()));
+			}
+		} else {
+			UUIDHelper.runConversionAction(name, (uuid) -> {
+				if (server.playerList.isOp(uuid)) {
+					server.playerList.deopPlayer(uuid);
+					handler.sendCommandFeedback(sender, "De-opping " + name);
+				} else {
+					handler.sendCommandFeedback(sender, name + " was not an operator");
+				}
+			}, (username) -> handler.sendCommandFeedback(sender,"Could not retrieve UUID of player '" + username + "'"));
 		}
 		
 		return true;
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/KickCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/KickCommand.java
index 7613689a8..361692a6c 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/KickCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/KickCommand.java
@@ -33,7 +33,7 @@ public class KickCommand extends ServerCommand {
             sendNoticeToOps(senderName, "Kicking " + playerToKick.getDisplayName());
         } else
         {
-            server.log("Can't find user " + nameToKick + ". No kick attempted.");
+            server.logInfo("Can't find user " + nameToKick + ". No kick attempted.");
         }
         return true;
     }
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/NicknameCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/NicknameCommand.java
index e95b3881e..fa3577ee9 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/NicknameCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/NicknameCommand.java
@@ -34,7 +34,7 @@ public class NicknameCommand extends ServerCommand
 
             player.nickname = enteredNickname;
             player.hadNicknameSet = true;
-            player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.score, player.chatColor, true, player.isOperator()));
+            player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, player.chatColor, true, player.isOperator()));
             sender.sendMessage("You set your nickname to " + player.getDisplayName());
             return true;
         }
@@ -51,7 +51,7 @@ public class NicknameCommand extends ServerCommand
             if (args.length != 1) return false;
             player.nickname = "";
             player.hadNicknameSet = true;
-            player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.score, player.chatColor, true, player.isOperator()));
+            player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, player.chatColor, true, player.isOperator()));
             sender.sendMessage("You cleared your nickname.");
             return true;
         }
@@ -74,7 +74,7 @@ public class NicknameCommand extends ServerCommand
 
                 player.nickname = enteredNickname;
                 player.hadNicknameSet = true;
-                player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.score, player.chatColor, true, player.isOperator()));
+                player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, player.chatColor, true, player.isOperator()));
                 sender.sendMessage("Set " + player.username + "'s nickname to " + player.getDisplayName());
                 handler.sendMessageToPlayer(player, "Your nickname was set to " + player.getDisplayName());
                 return true;
@@ -90,7 +90,7 @@ public class NicknameCommand extends ServerCommand
                 if (args.length != 2) return false;
                 player.nickname = "";
                 player.hadNicknameSet = true;
-                player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.score, player.chatColor, true, player.isOperator()));
+                player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, player.chatColor, true, player.isOperator()));
                 sender.sendMessage("Cleared " + player.username + "'s nickname.");
                 handler.sendMessageToPlayer(player, "Your nickname was cleared.");
                 return true;
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/OpCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/OpCommand.java
index 026b6c8f8..731c07846 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/OpCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/OpCommand.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.net.command.servercommands;
 
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.server.MinecraftServer;
 import net.minecraft.server.entity.player.ServerPlayer;
 import net.minecraft.core.net.packet.UpdatePlayerProfilePacket;
@@ -18,16 +19,22 @@ public class OpCommand extends ServerCommand{
 	public boolean execute(CommandHandler handler, CommandSender sender, String[] args) {
 		if(args.length == 0) return false;
 		String name = args[0];
-		
-		server.playerList.opPlayer(name);
-		handler.sendCommandFeedback(sender, "Opping "+name);
-		
+
 		ServerPlayer player = (ServerPlayer) handler.getPlayer(name);
 		if(player != null) {
+			server.playerList.opPlayer(player.uuid);
+			handler.sendCommandFeedback(sender, "Opping "+name);
+
 			handler.sendMessageToPlayer(player, TextFormatting.YELLOW + "You are now op!");
-			player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.score, player.chatColor, true, player.isOperator()));
+			player.mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, player.chatColor, true, player.isOperator()));
+		} else {
+			UUIDHelper.runConversionAction(name, (uuid) -> {
+				server.playerList.opPlayer(uuid);
+				handler.sendCommandFeedback(sender, "Opping "+name);
+			}, (username) -> handler.sendCommandFeedback(sender,"Could not retrieve UUID of player '" + username + "'"));
 		}
 
+
 		return true;
 	}
 
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/PardonCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/PardonCommand.java
index b15372123..39a15a414 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/PardonCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/PardonCommand.java
@@ -3,7 +3,9 @@ package net.minecraft.core.net.command.servercommands;
 import net.minecraft.core.net.command.CommandHandler;
 import net.minecraft.core.net.command.CommandSender;
 import net.minecraft.core.net.command.ServerCommand;
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.entity.player.ServerPlayer;
 
 public class PardonCommand extends ServerCommand {
     public PardonCommand(MinecraftServer server) {
@@ -17,8 +19,16 @@ public class PardonCommand extends ServerCommand {
 
         String nameToPardon = args[0];
 
-        server.playerList.pardonPlayer(nameToPardon);
-        sendNoticeToOps(senderName, "Pardoning " + nameToPardon);
+        ServerPlayer player = server.playerList.getPlayerEntity(nameToPardon);
+        if(player != null) {
+            server.playerList.pardonPlayer(player.uuid);
+            sendNoticeToOps(senderName, "Pardoning " + nameToPardon);
+        } else {
+            UUIDHelper.runConversionAction(nameToPardon, (uuid) -> {
+                server.playerList.pardonPlayer(uuid);
+                sendNoticeToOps(senderName, "Pardoning " + nameToPardon);
+            }, (username) -> handler.sendCommandFeedback(sender,"Could not retrieve UUID of player '" + username + "'"));
+        }
 
         return true;
     }
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/SayCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/SayCommand.java
index 92ad1a49b..413ab441a 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/SayCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/SayCommand.java
@@ -24,7 +24,7 @@ public class SayCommand extends ServerCommand {
         }
         String message = messageBuilder.toString().trim();
 
-        MinecraftServer.logger.info("[" + senderName + "] " + message);
+        MinecraftServer.LOGGER.info("[" + senderName + "] " + message);
         server.playerList.sendPacketToAllPlayers(new ChatPacket(TextFormatting.PINK + "[Server] " + message));
 
         return true;
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/ScoreCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/ScoreCommand.java
index 29f7c88a4..af1d06567 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/ScoreCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/ScoreCommand.java
@@ -29,7 +29,7 @@ public class ScoreCommand extends ServerCommand
             int newScore = Integer.parseInt(args[2]);
 
             player.score = newScore;
-            server.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.score, player.chatColor, true, player.isOperator()));
+            server.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, player.chatColor, true, player.isOperator()));
             sender.sendMessage("Set " + player.getDisplayName() + TextFormatting.WHITE + "'s score to " + player.score);
             handler.sendMessageToPlayer(player, "Your score was set to " + player.score);
             return true;
@@ -42,7 +42,7 @@ public class ScoreCommand extends ServerCommand
         if (args[1].equalsIgnoreCase("reset"))
         {
             player.score = 0;
-            server.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.score, player.chatColor, true, player.isOperator()));
+            server.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, player.chatColor, true, player.isOperator()));
             sender.sendMessage("Set " + player.getDisplayName() + TextFormatting.WHITE + "'s score to " + player.score);
             handler.sendMessageToPlayer(player, "Your score was set to " + player.score);
             return true;
diff --git a/src/main/java/net/minecraft/core/net/command/servercommands/WhitelistCommand.java b/src/main/java/net/minecraft/core/net/command/servercommands/WhitelistCommand.java
index 004979ab6..560e608a2 100644
--- a/src/main/java/net/minecraft/core/net/command/servercommands/WhitelistCommand.java
+++ b/src/main/java/net/minecraft/core/net/command/servercommands/WhitelistCommand.java
@@ -3,9 +3,12 @@ package net.minecraft.core.net.command.servercommands;
 import net.minecraft.core.net.command.CommandHandler;
 import net.minecraft.core.net.command.CommandSender;
 import net.minecraft.core.net.command.ServerCommand;
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.entity.player.ServerPlayer;
 
 import java.util.Set;
+import java.util.UUID;
 
 public class WhitelistCommand extends ServerCommand {
     public WhitelistCommand(MinecraftServer server) {
@@ -31,10 +34,10 @@ public class WhitelistCommand extends ServerCommand {
                 server.propertyManager.setProperty("white-list", false);
                 return true;
             case "list":
-                Set<String> set = server.playerList.getWhitelist();
+                Set<UUID> set = server.playerList.getWhitelist();
                 StringBuilder builder = new StringBuilder();
-                for (String s6 : set) {
-                    builder.append("\"").append(s6).append("\"").append(", ");
+                for (UUID uuid : set) {
+                    builder.append("\"").append(uuid).append("\"").append(", ");
                 }
 
                 String message = builder.toString();
@@ -44,18 +47,38 @@ public class WhitelistCommand extends ServerCommand {
 
                 sender.sendMessage("White-listed players: " + message);
                 return true;
-            case "add":
+            case "add":{
                 if (args.length != 2) return false;
                 String nameToAdd = args[1].toLowerCase();
-                server.playerList.addToWhiteList(nameToAdd);
-                sendNoticeToOps(senderName, "Added " + nameToAdd + " to white-list");
+
+                ServerPlayer player = server.playerList.getPlayerEntity(nameToAdd);
+                if(player != null) {
+                    server.playerList.addToWhiteList(player.uuid);
+                    sendNoticeToOps(senderName, "Added " + nameToAdd + " to white-list");
+                } else {
+                    UUIDHelper.runConversionAction(nameToAdd, (uuid) -> {
+                        server.playerList.addToWhiteList(uuid);
+                        sendNoticeToOps(senderName, "Added " + nameToAdd + " to white-list");
+                    }, (username) -> handler.sendCommandFeedback(sender,"Could not retrieve UUID of player '" + username + "'"));
+                }
                 return true;
-            case "remove":
+            }
+            case "remove": {
                 if (args.length != 2) return false;
                 String nameToRemove = args[1].toLowerCase();
-                server.playerList.removeFromWhiteList(nameToRemove);
-                sendNoticeToOps(senderName, "Removed " + nameToRemove + " from white-list");
+
+                ServerPlayer player = server.playerList.getPlayerEntity(nameToRemove);
+                if(player != null) {
+                    server.playerList.removeFromWhiteList(player.uuid);
+                    sendNoticeToOps(senderName, "Removed " + nameToRemove + " from white-list");
+                } else {
+                    UUIDHelper.runConversionAction(nameToRemove, (uuid) -> {
+                        server.playerList.removeFromWhiteList(uuid);
+                        sendNoticeToOps(senderName, "Removed " + nameToRemove + " from white-list");
+                    }, (username) -> handler.sendCommandFeedback(sender,"Could not retrieve UUID of player '" + username + "'"));
+                }
                 return true;
+            }
             case "reload":
                 server.playerList.reloadWhiteList();
                 sendNoticeToOps(senderName, "Reloaded white-list from file");
diff --git a/src/main/java/net/minecraft/core/net/packet/AddPlayerPacket.java b/src/main/java/net/minecraft/core/net/packet/AddPlayerPacket.java
index fcbcfce32..0e875ab74 100644
--- a/src/main/java/net/minecraft/core/net/packet/AddPlayerPacket.java
+++ b/src/main/java/net/minecraft/core/net/packet/AddPlayerPacket.java
@@ -6,6 +6,7 @@ import net.minecraft.core.net.handler.PacketHandler;
 import net.minecraft.core.util.helper.MathHelper;
 
 import java.io.*;
+import java.util.UUID;
 
 // Referenced classes of package net.minecraft.src:
 //            Packet, Player, MathHelper, InventoryPlayer,
@@ -22,6 +23,7 @@ public class AddPlayerPacket extends Packet
     {
         entityId = entityplayer.id;
         name = entityplayer.username;
+        uuid = entityplayer.uuid;
         xPosition = MathHelper.floor(entityplayer.x * 32D);
         yPosition = MathHelper.floor(entityplayer.y * 32D);
         zPosition = MathHelper.floor(entityplayer.z * 32D);
@@ -39,6 +41,7 @@ public class AddPlayerPacket extends Packet
     {
         entityId = dis.readInt();
         name = readString(dis, 16);
+        uuid = readUUID(dis);
         xPosition = dis.readInt();
         yPosition = dis.readInt();
         zPosition = dis.readInt();
@@ -55,6 +58,7 @@ public class AddPlayerPacket extends Packet
     {
         dos.writeInt(entityId);
         writeString(name, dos);
+        writeUUID(uuid, dos);
         dos.writeInt(xPosition);
         dos.writeInt(yPosition);
         dos.writeInt(zPosition);
@@ -79,6 +83,7 @@ public class AddPlayerPacket extends Packet
 
     public int entityId;
     public String name;
+    public UUID uuid;
     public int xPosition;
     public int yPosition;
     public int zPosition;
diff --git a/src/main/java/net/minecraft/core/net/packet/ContainerAckPacket.java b/src/main/java/net/minecraft/core/net/packet/ContainerAckPacket.java
index 4b29d83ce..499911949 100644
--- a/src/main/java/net/minecraft/core/net/packet/ContainerAckPacket.java
+++ b/src/main/java/net/minecraft/core/net/packet/ContainerAckPacket.java
@@ -14,11 +14,11 @@ public class ContainerAckPacket extends Packet
     {
     }
 
-    public ContainerAckPacket(int i, short word0, boolean flag)
+    public ContainerAckPacket(int windowId, short shortWindowId, boolean accepted)
     {
-        windowId = i;
-        shortWindowId = word0;
-        accepted = flag;
+        this.windowId = windowId;
+        this.shortWindowId = shortWindowId;
+        this.accepted = accepted;
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/core/net/packet/LoginPacket.java b/src/main/java/net/minecraft/core/net/packet/LoginPacket.java
index 70005a373..e0004ee50 100644
--- a/src/main/java/net/minecraft/core/net/packet/LoginPacket.java
+++ b/src/main/java/net/minecraft/core/net/packet/LoginPacket.java
@@ -3,6 +3,7 @@ package net.minecraft.core.net.packet;
 import net.minecraft.core.net.handler.PacketHandler;
 
 import java.io.*;
+import java.util.UUID;
 
 // Referenced classes of package net.minecraft.src:
 //            Packet, PacketHandler
@@ -11,6 +12,7 @@ public class LoginPacket extends Packet
 {
     public int playerEntityIdAndProtocolVersion;
     public String username;
+    public UUID uuid;
     public long worldSeed;
     public byte dimensionId;
     public byte worldTypeId;
@@ -21,9 +23,10 @@ public class LoginPacket extends Packet
     {
     }
 
-    public LoginPacket(String username, int playerEntityIdOrProtocolVersion, long worldSeed, byte dimensionId, byte worldTypeId, int packetDelay, String publicKey)
+    public LoginPacket(String username, UUID uuid, int playerEntityIdOrProtocolVersion, long worldSeed, byte dimensionId, byte worldTypeId, int packetDelay, String publicKey)
     {
         this.username = username;
+        this.uuid = uuid;
         this.playerEntityIdAndProtocolVersion = playerEntityIdOrProtocolVersion;
         this.worldSeed = worldSeed;
         this.dimensionId = dimensionId;
@@ -32,11 +35,12 @@ public class LoginPacket extends Packet
         this.publicKey = publicKey;
     }
 
-    public LoginPacket(String s, int i, String p)
+    public LoginPacket(String username, UUID uuid, int i, String publicKey)
     {
-        username = s;
-        playerEntityIdAndProtocolVersion = i;
-        publicKey = p;
+        this.username = username;
+        this.uuid = uuid;
+        this.playerEntityIdAndProtocolVersion = i;
+        this.publicKey = publicKey;
     }
 
     @Override
@@ -45,6 +49,7 @@ public class LoginPacket extends Packet
     {
         playerEntityIdAndProtocolVersion = dis.readInt();
         username = readString(dis, 16);
+        uuid = readUUID(dis);
         publicKey = readString(dis, 392);
         worldSeed = dis.readLong();
         dimensionId = dis.readByte();
@@ -58,6 +63,7 @@ public class LoginPacket extends Packet
     {
         dos.writeInt(playerEntityIdAndProtocolVersion);
         writeString(username, dos);
+        writeUUID(uuid, dos);
         writeString(publicKey, dos);
         dos.writeLong(worldSeed);
         dos.writeByte(dimensionId);
diff --git a/src/main/java/net/minecraft/core/net/packet/Packet.java b/src/main/java/net/minecraft/core/net/packet/Packet.java
index bca82d732..f11ea80bd 100644
--- a/src/main/java/net/minecraft/core/net/packet/Packet.java
+++ b/src/main/java/net/minecraft/core/net/packet/Packet.java
@@ -1,9 +1,12 @@
 package net.minecraft.core.net.packet;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.Global;
 import net.minecraft.core.net.handler.PacketHandler;
+import org.slf4j.Logger;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -19,9 +22,11 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
 public abstract class Packet
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private static final List<Integer> INTERESTING_PACKETS = Arrays.asList(50, 51, 52);
     private static final Map<Integer, Class<? extends Packet>> packetIdToClassMap = new HashMap<>();
     private static final Map<Class<? extends Packet>, Integer> packetClassToIdMap = new HashMap<>();
@@ -53,8 +58,8 @@ public abstract class Packet
     }
 
     public static Packet getNewPacket(int id) {
+        Class<? extends Packet> packetClass = packetIdToClassMap.get(id);
         try {
-            Class<? extends Packet> packetClass = packetIdToClassMap.get(id);
             if (packetClass == null) {
                 return null;
             }
@@ -63,9 +68,9 @@ public abstract class Packet
             }
         }
         catch (Exception exception) {
-            exception.printStackTrace();
+            LOGGER.error("Exception instancing packet class '{}'!", packetClass.getSimpleName(), exception);
         }
-        System.out.println("Skipping packet with id " + id);
+        LOGGER.warn("Skipping packet with id {}", id);
         return null;
     }
 
@@ -95,14 +100,14 @@ public abstract class Packet
             if (Global.NET_DEBUG) {
                 long sendTime = dis.readLong();
                 if (INTERESTING_PACKETS.contains(id)) {
-                    System.out.println("Packet " + id + " took " + (System.currentTimeMillis() - sendTime) + "ms to arrive");
+                    LOGGER.debug("Packet {} took {}ms to arrive", id, System.currentTimeMillis() - sendTime);
                 }
             }
             packet.read(dis);
         }
         catch (EOFException eofexception)
         {
-            System.out.println("Reached end of stream");
+            LOGGER.warn("Reached end of stream");
             return null;
         }
         return packet;
@@ -210,6 +215,17 @@ public abstract class Packet
         return NbtIo.readCompressed(new ByteArrayInputStream(data));
     }
 
+    public static void writeUUID(@NotNull UUID uuid, DataOutputStream dos) throws IOException {
+        dos.writeLong(uuid.getMostSignificantBits());
+        dos.writeLong(uuid.getLeastSignificantBits());
+    }
+
+    public static UUID readUUID(DataInputStream dis) throws IOException {
+        long msb = dis.readLong();
+        long lsb = dis.readLong();
+        return new UUID(msb, lsb);
+    }
+
     public static Map<Class<? extends Packet>, Integer> getPacketClassToIdMap() {
         return Collections.unmodifiableMap(packetClassToIdMap);
     }
diff --git a/src/main/java/net/minecraft/core/net/packet/UpdatePlayerProfilePacket.java b/src/main/java/net/minecraft/core/net/packet/UpdatePlayerProfilePacket.java
index 6d50b13b8..69be2e80f 100644
--- a/src/main/java/net/minecraft/core/net/packet/UpdatePlayerProfilePacket.java
+++ b/src/main/java/net/minecraft/core/net/packet/UpdatePlayerProfilePacket.java
@@ -6,6 +6,7 @@ import net.minecraft.server.util.helper.PlayerList;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.util.UUID;
 
 // Referenced classes of package net.minecraft.src:
 //            Packet, PacketHandler
@@ -17,10 +18,11 @@ public class UpdatePlayerProfilePacket extends Packet
     {
     }
 
-    public UpdatePlayerProfilePacket(String username, String nickname, int score, byte chatColor, boolean isOnline, boolean isOperator)
+    public UpdatePlayerProfilePacket(String username, String nickname, UUID uuid, int score, byte chatColor, boolean isOnline, boolean isOperator)
     {
         this.username = username;
         this.nickname = nickname;
+        this.uuid = uuid;
         this.score = score;
         this.chatColor = chatColor;
         this.isOnline = isOnline;
@@ -34,6 +36,7 @@ public class UpdatePlayerProfilePacket extends Packet
     {
         username = readString(dis, 16);
         nickname = readString(dis, 32);
+        uuid = readUUID(dis);
         score = dis.readInt();
         chatColor = dis.readByte();
         isOnline = dis.readBoolean();
@@ -46,6 +49,7 @@ public class UpdatePlayerProfilePacket extends Packet
     {
         writeString(username, dos);
         writeString(nickname, dos);
+        writeUUID(uuid, dos);
         dos.writeInt(score);
         dos.writeByte(chatColor);
         dos.writeBoolean(isOnline);
@@ -66,6 +70,7 @@ public class UpdatePlayerProfilePacket extends Packet
 
     public String username;
     public String nickname;
+    public UUID uuid;
     public int score;
     public byte chatColor;
     public boolean isOnline;
diff --git a/src/main/java/net/minecraft/core/player/Session.java b/src/main/java/net/minecraft/core/player/Session.java
index faca8af03..e5ff6ca58 100644
--- a/src/main/java/net/minecraft/core/player/Session.java
+++ b/src/main/java/net/minecraft/core/player/Session.java
@@ -1,13 +1,20 @@
 package net.minecraft.core.player;
 
+import net.minecraft.core.util.helper.UUIDHelper;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.UUID;
+
 public class Session
 {
 
-    public String username;
-    public String sessionId;
-    public Session(String username, String sessionId)
+    public @NotNull String username;
+    public @NotNull UUID uuid;
+    public @NotNull String sessionId;
+    public Session(@NotNull String username, @NotNull String uuid, @NotNull String sessionId)
     {
         this.username = username;
+        this.uuid = UUID.fromString(UUIDHelper.untrimUUID(uuid));
         this.sessionId = sessionId;
     }
 
diff --git a/src/main/java/net/minecraft/core/player/inventory/menu/AbstractContainerMenu.java b/src/main/java/net/minecraft/core/player/inventory/menu/AbstractContainerMenu.java
index dcc408947..9501fb09a 100644
--- a/src/main/java/net/minecraft/core/player/inventory/menu/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/core/player/inventory/menu/AbstractContainerMenu.java
@@ -2,6 +2,7 @@ package net.minecraft.core.player.inventory.menu;
 
 import java.util.*;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.InventoryAction;
 import net.minecraft.core.Global;
 import net.minecraft.core.crafting.ContainerListener;
@@ -14,10 +15,11 @@ import net.minecraft.core.player.inventory.container.Inventory;
 import net.minecraft.core.player.inventory.slot.Slot;
 import net.minecraft.core.player.inventory.slot.ResultSlot;
 import net.minecraft.core.util.helper.MathHelper;
+import org.slf4j.Logger;
 
 public abstract class AbstractContainerMenu
 {
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public List<ItemStack> lastSlots;
 	public List<Slot> slots;
 	public int containerId;
@@ -117,7 +119,7 @@ public abstract class AbstractContainerMenu
 	public ItemStack clicked(InventoryAction action, int[] args, Player player) {
 		if(action.requireCreative()) {
 			if(player.getGamemode().consumeBlocks()) {
-				System.out.println("Player "+player.username+" used a creative inventory action but is not in creative mode!");
+                LOGGER.warn("Player {} used a creative inventory action but is not in creative mode!", player.username);
 				return null;
 			}
 		}
diff --git a/src/main/java/net/minecraft/core/sound/SoundTypes.java b/src/main/java/net/minecraft/core/sound/SoundTypes.java
index 5d0b32222..3cbd2bef3 100644
--- a/src/main/java/net/minecraft/core/sound/SoundTypes.java
+++ b/src/main/java/net/minecraft/core/sound/SoundTypes.java
@@ -1,5 +1,12 @@
 package net.minecraft.core.sound;
 
+import com.b100.utils.StringUtils;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+
+import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -17,73 +24,27 @@ public class SoundTypes {
 	 * Required for any sound that is supposed to be played by the server
 	 */
 	public static void registerSounds() {
-		register("ambient.cave.cave");
-		register("ambient.weather.thunder");
-		register("ambient.weather.rain");
-
-		register("mob.skeleton");
-		register("mob.skeletonhurt");
-		register("mob.spider");
-		register("mob.spiderdeath");
-		register("mob.slime");
-		register("mob.slimeattack");
-		register("mob.ghast.charge");
-		register("mob.ghast.death");
-		register("mob.ghast.fireball");
-		register("mob.ghast.moan");
-		register("mob.ghast.scream");
-		register("mob.zombiepig.zpig");
-		register("mob.zombiepig.zpighurt");
-		register("mob.zombiepig.zpigdeath");
-		register("mob.zombie");
-		register("mob.zombiehurt");
-		register("mob.zombiedeath");
-
-		register("mob.chicken");
-		register("mob.chickenhurt");
-		register("mob.chickendeath");
-		register("mob.chickenplop");
-		register("mob.creeper");
-		register("mob.creeperdeath");
-		register("mob.pig");
-		register("mob.pigdeath");
-		register("mob.sheep");
-		register("mob.slime");
-		register("mob.cow");
-		register("mob.cowhurt");
-		register("mob.wolf");
-		register("mob.wolf.bark");
-		register("mob.wolf.hurt");
-		register("mob.wolf.shake");
-		register("mob.wolf.panting");
-		register("mob.wolf.death");
-		register("mob.wolf.whine");
-		register("mob.wolf.growl");
+		loadSoundsJson("/assets/minecraft/sounds/sounds.json");
+	}
 
-		register("random.bow");
-		register("random.breath");
-		register("random.click");
-		register("random.drr");
-		register("random.door_open");
-		register("random.door_close");
-		register("random.explode");
-		register("random.fizz");
-		register("random.fuse");
-		register("random.hurt");
-		register("random.pop");
-		register("random.splash");
+	public static void loadSoundsJson(String path) {
+		JsonObject o;
+		try {
+			o = loadStreamAsElement(SoundTypes.class.getResourceAsStream(path)).getAsJsonObject();
+		} catch (Exception e) {
+			System.err.println("Failed to load '" + path + "' as a json!");
+			e.printStackTrace();
+			return;
+		}
+		for (String s : o.asMap().keySet()) {
+			register(s);
+		}
+	}
 
-		register("step.cloth");
-		register("step.grass");
-		register("step.gravel");
-		register("step.stone");
-		register("step.sand");
-		register("step.wood");
-		
-		register("tile.piston.in");
-		register("tile.piston.out");
+	private static JsonElement loadStreamAsElement(InputStream stream) throws JsonParseException {
+		return JsonParser.parseString(StringUtils.readInputString(stream));
 	}
-	
+
 	public static boolean register(String soundPath) {
 		if(soundPath.length() > MAX_SOUND_NAME_LENGTH) {
 			throw new RuntimeException("Sound Path is too long: '" + soundPath + "'!");
diff --git a/src/main/java/net/minecraft/core/util/helper/BlockParticleHelper.java b/src/main/java/net/minecraft/core/util/helper/BlockParticleHelper.java
index c6e247265..3e5f86a2f 100644
--- a/src/main/java/net/minecraft/core/util/helper/BlockParticleHelper.java
+++ b/src/main/java/net/minecraft/core/util/helper/BlockParticleHelper.java
@@ -1,16 +1,19 @@
 package net.minecraft.core.util.helper;
 
 public class BlockParticleHelper {
-    public static int encodeBlockData(int blockId, int meta, Side side){
+    public static int encodeBlockData(int blockId, int meta, Side side) {
         return blockId & 0x3FFF | (meta & 0xFF) << 14 | (side.getId() << 22);
     }
-    public static int decodeBlockID(int data){
+
+    public static int decodeBlockID(int data) {
         return data & 0x3FFF;
     }
-    public static int decodeBlockMeta(int data){
+
+    public static int decodeBlockMeta(int data) {
         return data >> 14 & 0xFF;
     }
-    public static int decodeBlockSide(int data){
-        return data >> 22 & 0xF;
+
+    public static Side decodeBlockSide(int data) {
+        return Side.getSideById(data >> 22 & 0xF);
     }
 }
diff --git a/src/main/java/net/minecraft/core/util/helper/GetMonsterSkinUrlThread.java b/src/main/java/net/minecraft/core/util/helper/GetMonsterSkinUrlThread.java
index 65158d110..2ba9d9fba 100644
--- a/src/main/java/net/minecraft/core/util/helper/GetMonsterSkinUrlThread.java
+++ b/src/main/java/net/minecraft/core/util/helper/GetMonsterSkinUrlThread.java
@@ -4,12 +4,15 @@ import com.b100.json.JsonParser;
 import com.b100.json.element.JsonArray;
 import com.b100.json.element.JsonObject;
 import com.b100.utils.StringUtils;
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.entity.monster.HumanMob;
+import org.slf4j.Logger;
 
 import java.util.Base64;
+import java.util.UUID;
 
 public class GetMonsterSkinUrlThread extends Thread{
-
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static int counter = 0;
 
 	private static final String urlUUID = "https://api.mojang.com/users/profiles/minecraft/";
@@ -18,7 +21,7 @@ public class GetMonsterSkinUrlThread extends Thread{
 	private static final JsonParser jsonParser = new JsonParser();
 
 	private HumanMob monster;
-	private String uuid;
+	private UUID uuid;
 
 	public GetMonsterSkinUrlThread(HumanMob monster) {
 		this.monster = monster;
@@ -32,7 +35,7 @@ public class GetMonsterSkinUrlThread extends Thread{
 	@Override
 	public void run() {
 		String name = monster.nickname;
-		if(name == null || name.length() == 0) return;
+		if(name == null || name.isEmpty()) return;
 
 		//  Attempt to get the skin 3 times before failing
 		String string = null;
@@ -59,8 +62,8 @@ public class GetMonsterSkinUrlThread extends Thread{
 				}
 			}
 		}
-		
-		System.out.println("Skin URL: "+ monster.skinUrl);
+
+        LOGGER.info("Skin URL: {}", monster.skinUrl);
 	}
 	
 	public static String decodeBase64(String string) {
@@ -68,31 +71,14 @@ public class GetMonsterSkinUrlThread extends Thread{
 	}
 	private String getSkinObject(String name){
 		String string;
-		try{
-			string = StringUtils.getWebsiteContentAsString(urlUUID + name);
-		}catch (Exception e) {
-			System.err.println("Can't connect to Mojang API.");
-			e.printStackTrace();
-			return null;
-		}
-		if(string.length() == 0) {
-			System.err.println("Player "+name+" doesn't exist!");
-			return null;
-		}
-		try {
-			JsonObject contentParsed = jsonParser.parse(string);
-			this.uuid = contentParsed.getString("id");
-		}catch (Exception e) {
-			e.printStackTrace();
-			return null;
-		}
-		if(uuid == null) return null;
+		this.uuid = UUIDHelper.getUUIDFromName(name);
+    if(uuid == null) return null;
 
-		System.out.println("Loading Skin for Player "+name+"...");
+        LOGGER.info("Loading Skin for Player {}...", name);
 		try {
 			string = StringUtils.getWebsiteContentAsString(urlSkin + uuid);
 		}catch (Exception e) {
-			System.err.println("Invalid UUID "+uuid+", or can't connect to the Mojang API.");
+            LOGGER.warn("Invalid UUID {}, or can't connect to the Mojang API.", uuid);
 			return null;
 		}
 		return string;
diff --git a/src/main/java/net/minecraft/core/util/helper/GetSkinUrlThread.java b/src/main/java/net/minecraft/core/util/helper/GetSkinUrlThread.java
index 02dfb01af..195f2af64 100644
--- a/src/main/java/net/minecraft/core/util/helper/GetSkinUrlThread.java
+++ b/src/main/java/net/minecraft/core/util/helper/GetSkinUrlThread.java
@@ -1,25 +1,28 @@
 package net.minecraft.core.util.helper;
 
 import java.util.Base64;
+import java.util.UUID;
 
 import com.b100.json.JsonParser;
 import com.b100.json.element.JsonArray;
 import com.b100.json.element.JsonObject;
 import com.b100.utils.StringUtils;
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.entity.player.Player;
+import org.slf4j.Logger;
 
 public class GetSkinUrlThread extends Thread{
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	private static int counter = 0;
 
 	private static final String urlUUID = "https://api.mojang.com/users/profiles/minecraft/";
 	private static final String urlSkin = "https://sessionserver.mojang.com/session/minecraft/profile/";
 	
 	private static final JsonParser jsonParser = new JsonParser();
-	
+
 	private Player player;
-	private String uuid;
-	
+	private UUID uuid;
+
 	public GetSkinUrlThread(Player player) {
 		this.player = player;
 		
@@ -32,6 +35,7 @@ public class GetSkinUrlThread extends Thread{
 	@Override
 	public void run() {
 		String name = player.username;
+		this.uuid = player.uuid;
 		if(name == null || name.length() == 0) return;
 
 		//  Attempt to get the skin 3 times before failing
@@ -62,9 +66,9 @@ public class GetSkinUrlThread extends Thread{
 		if(texturesObject.has("CAPE")) {
 			player.capeURL = texturesObject.getObject("CAPE").getString("url");
 		}
-		
-		System.out.println("Skin URL: "+player.skinURL);
-		System.out.println("Cape URL: "+player.capeURL);
+
+        LOGGER.info("Skin URL: {}", player.skinURL);
+        LOGGER.info("Cape URL: {}", player.capeURL);
 	}
 	
 	public static String decodeBase64(String string) {
@@ -72,31 +76,16 @@ public class GetSkinUrlThread extends Thread{
 	}
 	private String getSkinObject(String name){
 		String string;
-		try{
-			string = StringUtils.getWebsiteContentAsString(urlUUID + name);
-		}catch (Exception e) {
-			System.err.println("Can't connect to Mojang API.");
-			e.printStackTrace();
-			return null;
-		}
-		if(string.length() == 0) {
-			System.err.println("Player "+name+" doesn't exist!");
-			return null;
-		}
-		try {
-			JsonObject contentParsed = jsonParser.parse(string);
-			this.uuid = contentParsed.getString("id");
-		}catch (Exception e) {
-			e.printStackTrace();
-			return null;
+		if (uuid == null) {
+			uuid = UUIDHelper.getUUIDFromName(name);
+			if(uuid == null) return null;
 		}
-		if(uuid == null) return null;
 
-		System.out.println("Loading Skin for Player "+name+"...");
+        LOGGER.info("Loading Skin for Player {}...", name);
 		try {
 			string = StringUtils.getWebsiteContentAsString(urlSkin + uuid);
 		}catch (Exception e) {
-			System.err.println("Invalid UUID "+uuid+", or can't connect to the Mojang API.");
+            LOGGER.warn("Invalid UUID {}, or can't connect to the Mojang API.", uuid);
 			return null;
 		}
 		return string;
diff --git a/src/main/java/net/minecraft/core/util/helper/LogPrintStream.java b/src/main/java/net/minecraft/core/util/helper/LogPrintStream.java
deleted file mode 100644
index 3972438b9..000000000
--- a/src/main/java/net/minecraft/core/util/helper/LogPrintStream.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package net.minecraft.core.util.helper;
-
-import java.io.PrintStream;
-import java.time.LocalTime;
-
-public class LogPrintStream extends PrintStream{
-	
-	public static boolean stackTrace = false;
-	public static boolean time = true;
-	public static boolean thread = true;
-	
-	public static void setup() {
-		System.setOut(new LogPrintStream(System.out));
-		System.setErr(new LogPrintStream(System.err));
-	}
-	
-	private PrintStream old;
-	
-	public LogPrintStream(PrintStream printStream) {
-		super(printStream);
-		
-		this.old = printStream;
-	}
-	
-	@Override
-	public void println(boolean x) {
-		formatPrintLine(Boolean.valueOf(x).toString());
-	}
-	
-	@Override
-	public void println(int x) {
-		formatPrintLine(Integer.valueOf(x).toString());
-	}
-	
-	@Override
-	public void println(long x) {
-		formatPrintLine(Long.valueOf(x).toString());
-	}
-	
-	@Override
-	public void println(float x) {
-		formatPrintLine(Float.valueOf(x).toString());
-	}
-	
-	@Override
-	public void println(double x) {
-		formatPrintLine(Double.valueOf(x).toString());
-	}
-	
-	@Override
-	public void println(char x) {
-		formatPrintLine(Character.valueOf(x).toString());
-	}
-	
-	@Override
-	public void println(String a) {
-		formatPrintLine(a);
-	}
-	
-	@Override
-	public void println(Object x) {
-		if(x != null) {
-			formatPrintLine(x.toString());
-		}else {
-			formatPrintLine(null);
-		}
-	}
-	
-	@Override
-	public void println(char[] x) {
-		formatPrintLine(new String(x));
-	}
-	
-	public void formatPrintLine(String s) {
-		formatPrint(s + "\n", 1);
-	}
-	
-	private void formatPrint(String string, int stackTraceOffset) {
-		string = removeColorCodes(string);
-
-		if(stackTrace) {
-			string = Thread.currentThread().getStackTrace()[3 + stackTraceOffset] + " " + string; 
-		}
-		if(thread) {
-		    string = "[" + Thread.currentThread().getName() + "] " + string;
-		}
-		if(time) {
-			LocalTime localTime = LocalTime.now();
-			StringBuilder timeString = new StringBuilder();
-			
-			if(localTime.getHour() < 10) timeString.append("0");
-			timeString.append(localTime.getHour());
-			timeString.append(":");
-			if(localTime.getMinute() < 10) timeString.append("0");
-			timeString.append(localTime.getMinute());
-			timeString.append(":");
-			if(localTime.getSecond() < 10) timeString.append("0");
-			timeString.append(localTime.getSecond());
-			
-			string = "[" + timeString.toString() + "] " + string;
-		}
-		
-		old.print(string);
-	}
-	
-	public static String removeColorCodes(String string) {
-		StringBuilder builder = new StringBuilder();
-		
-		boolean a = false;
-		for(int i=0; i < string.length(); i++) {
-			char c = string.charAt(i);
-			if(c == '§') {
-				a = true;
-			}else if(a) {
-				a = false;
-			}else {
-				builder.append(c);
-			}
-		}
-		return builder.toString();
-	}
-	
-}
diff --git a/src/main/java/net/minecraft/core/util/helper/LoggedPrintStream.java b/src/main/java/net/minecraft/core/util/helper/LoggedPrintStream.java
new file mode 100644
index 000000000..5d3d8efe9
--- /dev/null
+++ b/src/main/java/net/minecraft/core/util/helper/LoggedPrintStream.java
@@ -0,0 +1,55 @@
+package net.minecraft.core.util.helper;
+
+import com.mojang.logging.LogUtils;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+public class LoggedPrintStream extends PrintStream
+{
+	private static final Logger LOGGER = LogUtils.getLogger();
+	protected final String name;
+
+	public LoggedPrintStream(final String name, final OutputStream sourceStream) {
+		super(sourceStream);
+		this.name = name;
+	}
+	public static void wrapStreams() {
+		System.setErr(new LoggedPrintStream("STDERR", System.err));
+		System.setOut(new LoggedPrintStream("STDOUT", System.out));
+	}
+
+	@Override
+	public void println(@Nullable final String message) {
+		this.logLine(message);
+	}
+
+	@Override
+	public void println(final Object object) {
+		this.logLine(String.valueOf(object));
+	}
+
+	protected void logLine(@Nullable final String $$0) {
+		LoggedPrintStream.LOGGER.info("[{}]: {}", this.name, $$0);
+	}
+
+    public static String removeColorCodes(String string) {
+		StringBuilder builder = new StringBuilder();
+		
+		boolean a = false;
+		for(int i=0; i < string.length(); i++) {
+			char c = string.charAt(i);
+			if(c == '§') {
+				a = true;
+			}else if(a) {
+				a = false;
+			}else {
+				builder.append(c);
+			}
+		}
+		return builder.toString();
+	}
+	
+}
diff --git a/src/main/java/net/minecraft/core/util/helper/ReflectionHelper.java b/src/main/java/net/minecraft/core/util/helper/ReflectionHelper.java
index 758210d56..48468b9a0 100644
--- a/src/main/java/net/minecraft/core/util/helper/ReflectionHelper.java
+++ b/src/main/java/net/minecraft/core/util/helper/ReflectionHelper.java
@@ -9,9 +9,11 @@ import java.util.zip.ZipFile;
 
 import com.b100.utils.FileUtils;
 import com.b100.utils.interfaces.Condition;
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
 
 public abstract class ReflectionHelper {
-	
+	private static final Logger LOGGER = LogUtils.getLogger();
 	public static List<Class<?>> getAllClasses(Condition<String> classNameCondition) {
 		ClassLoader classLoader = ClassLoader.getSystemClassLoader();
 		List<Class<?>> classes = new ArrayList<Class<?>>();
@@ -43,7 +45,7 @@ public abstract class ReflectionHelper {
 					}
 					zip.close();
 				} catch (IOException e) {
-					e.printStackTrace();
+                    LOGGER.error("Exception loading class entries from file '{}'!", file.getPath(), e);
 				}
 				
 			}
diff --git a/src/main/java/net/minecraft/core/util/helper/ScreenShot.java b/src/main/java/net/minecraft/core/util/helper/ScreenShot.java
index 843f079b3..0227155db 100644
--- a/src/main/java/net/minecraft/core/util/helper/ScreenShot.java
+++ b/src/main/java/net/minecraft/core/util/helper/ScreenShot.java
@@ -9,14 +9,16 @@ import java.util.Date;
 
 import javax.imageio.ImageIO;
 
+import com.mojang.logging.LogUtils;
 import org.lwjgl.BufferUtils;
 import org.lwjgl.opengl.GL11;
 
 import com.b100.utils.ImageUtils;
+import org.slf4j.Logger;
 
 public class ScreenShot
 {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static String saveScreenshot(File mcDir, int width, int height)
     {
         try
@@ -37,9 +39,9 @@ public class ScreenShot
             buffer.clear();
             GL11.glReadPixels(0, 0, width, height, 6407 /*GL_RGB*/, 5121 /*GL_UNSIGNED_BYTE*/, buffer);
             buffer.clear();
-            String s = "" + dateFormat.format(new Date());
-            File file2;
-            for(int k = 1; (file2 = new File(screenshotsDir, s + (k != 1 ? "_" + k : "") + ".png")).exists(); k++) { }
+            String dateString = dateFormat.format(new Date());
+            File destFile;
+            for(int k = 1; (destFile = new File(screenshotsDir, dateString + (k != 1 ? "_" + k : "") + ".png")).exists(); k++) { }
             buffer.get(pixelData);
             for(int l = 0; l < width; l++)
             {
@@ -57,24 +59,24 @@ public class ScreenShot
 
             BufferedImage bufferedimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
             bufferedimage.setRGB(0, 0, width, height, imageData, 0, width);
-            ImageIO.write(bufferedimage, "png", file2);
+            ImageIO.write(bufferedimage, "png", destFile);
             try {
             	ImageUtils.copyImageToClipboard(bufferedimage);
             }catch (Exception e) {
-            	e.printStackTrace();
+                LOGGER.error("Exception copying image to clipboard!", e);
 			}
-            return "Saved screenshot as " + file2.getName();
+            return "Saved screenshot as " + destFile.getName();
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Failed to save screenshot!", exception);
             return "Failed to save: " + exception;
         }
     }
 
     private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss");
     private static ByteBuffer buffer;
-    private static byte pixelData[];
-    private static int imageData[];
+    private static byte[] pixelData;
+    private static int[] imageData;
 
 }
diff --git a/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java b/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java
new file mode 100644
index 000000000..9c763bb47
--- /dev/null
+++ b/src/main/java/net/minecraft/core/util/helper/UUIDHelper.java
@@ -0,0 +1,118 @@
+package net.minecraft.core.util.helper;
+
+import com.b100.json.JsonParser;
+import com.b100.json.element.JsonObject;
+import com.b100.utils.StringUtils;
+import com.mojang.nbt.CompoundTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class UUIDHelper {
+    private static final String urlUUID = "https://api.mojang.com/users/profiles/minecraft/";
+
+    private static final JsonParser jsonParser = new JsonParser();
+    private static final Map<String, UUID> nameToUUIDMap = new HashMap<>();
+
+    public static boolean isUUID(String usernameOrUUID) {
+        return usernameOrUUID.length() == 36 || usernameOrUUID.length() == 32;
+    }
+
+    public static void runConversionAction(String username, @Nullable UUIDFunction successAction, @Nullable StringFunction failAction) {
+        if (nameToUUIDMap.containsKey(username)) {
+            UUID uuid = nameToUUIDMap.get(username);
+            if (uuid != null) {
+                if (successAction != null) {
+                    successAction.run(uuid);
+                }
+            } else {
+                if (failAction != null) {
+                    failAction.run(username);
+                }
+            }
+            return;
+        }
+        new Thread(() -> {
+            try {
+                UUID uuid = getUUIDFromName(username);
+                if (uuid != null) {
+                    if (successAction != null) {
+                        successAction.run(uuid);
+                    }
+                    nameToUUIDMap.put(username, uuid);
+                } else {
+                    if (failAction != null) {
+                        failAction.run(username);
+                    }
+                    nameToUUIDMap.put(username, null);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                if (failAction != null) {
+                    failAction.run(username);
+                }
+            }
+        }).start();
+    }
+    public static @Nullable UUID getUUIDFromName(String username){
+        String string;
+        try{
+            string = StringUtils.getWebsiteContentAsString(urlUUID + username);
+        }catch (Exception e) {
+            System.err.println("Can't connect to Mojang API.");
+            e.printStackTrace();
+            return null;
+        }
+        if(string.isEmpty()) {
+            System.err.println("Player "+username+" doesn't exist!");
+            return null;
+        }
+        String uuid;
+        try {
+            JsonObject contentParsed = jsonParser.parse(string);
+            uuid = contentParsed.getString("id");
+        }catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+        if (uuid == null) return null;
+        uuid = untrimUUID(uuid);
+        return UUID.fromString(uuid);
+    }
+
+    public static String untrimUUID(String uuid) {
+        if (uuid.length() == 32) { // Untrim trimmed UUID
+            String s1 = uuid.substring(0, 8);
+            String s2 = uuid.substring(8, 12);
+            String s3 = uuid.substring(12, 16);
+            String s4 = uuid.substring(16, 20);
+            String s5 = uuid.substring(20, 32);
+            return s1 + "-" + s2 + "-" + s3 + "-" + s4 + "-" + s5;
+        }
+        return uuid;
+    }
+
+    public static @Nullable UUID readFromTag(@NotNull CompoundTag tag, @NotNull String keyBase) {
+        if (!tag.containsKey(keyBase + "_msb") || !tag.containsKey(keyBase + "_lsb")) return null;
+        long msb = tag.getLong(keyBase + "_msb");
+        long lsb = tag.getLong(keyBase + "_lsb");
+        return new UUID(msb, lsb);
+    }
+
+    public static void writeToTag(@NotNull CompoundTag tag, @Nullable UUID uuid, @NotNull String keyBase) {
+        if (uuid != null) {
+            tag.putLong(keyBase + "_msb", uuid.getMostSignificantBits());
+            tag.putLong(keyBase + "_lsb", uuid.getLeastSignificantBits());
+        }
+    }
+
+    public interface StringFunction {
+        void run(String s);
+    }
+    public interface UUIDFunction {
+        void run(UUID s);
+    }
+}
diff --git a/src/main/java/net/minecraft/core/util/helper/Utils.java b/src/main/java/net/minecraft/core/util/helper/Utils.java
index ff0163137..5a3df5ad6 100644
--- a/src/main/java/net/minecraft/core/util/helper/Utils.java
+++ b/src/main/java/net/minecraft/core/util/helper/Utils.java
@@ -1,9 +1,13 @@
 package net.minecraft.core.util.helper;
 
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
+
 import java.awt.Desktop;
 import java.io.File;
 
 public abstract class Utils {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	
 	public static final String hexString = "0123456789ABCDEF";
 	
@@ -39,18 +43,17 @@ public abstract class Utils {
 	
 	public static void openDirectory(File file) {
 		if(!file.exists()) {
-			System.out.println("Can't open directory '"+file.getAbsolutePath()+"' because it doesnt exist!");
+            LOGGER.warn("Can't open directory '{}' because it doesnt exist!", file.getAbsolutePath());
 			return;
 		}
 		if(!file.isDirectory()) {
-			System.out.println("Not a directory: '"+file.getAbsolutePath()+"'!");
+            LOGGER.warn("Not a directory: '{}'!", file.getAbsolutePath());
 			return;
 		}
 		try {
 			Desktop.getDesktop().open(file);
 		}catch (Exception e) {
-			System.err.println("Error opening directory '"+file.getAbsolutePath()+"'!");
-			e.printStackTrace();
+            LOGGER.error("Error opening directory '{}'!", file.getAbsolutePath(), e);
 		}
 	}
 	
diff --git a/src/main/java/net/minecraft/core/world/Explosion.java b/src/main/java/net/minecraft/core/world/Explosion.java
index af1baca0a..1e3435b56 100644
--- a/src/main/java/net/minecraft/core/world/Explosion.java
+++ b/src/main/java/net/minecraft/core/world/Explosion.java
@@ -88,7 +88,7 @@ public class Explosion {
             }
             if(id > 0)
             {
-                Block.blocksList[id].dropBlockWithCause(worldObj, EnumDropCause.EXPLOSION, x, y, z, worldObj.getBlockMetadata(x, y, z), blockEntity);
+                Block.blocksList[id].dropBlockWithCause(worldObj, EnumDropCause.EXPLOSION, x, y, z, worldObj.getBlockMetadata(x, y, z), blockEntity, null);
                 worldObj.setBlockWithNotify(x, y, z, 0);
                 Block.blocksList[id].onBlockDestroyedByExplosion(worldObj, x, y, z);
             }
diff --git a/src/main/java/net/minecraft/core/world/ExplosionCannonball.java b/src/main/java/net/minecraft/core/world/ExplosionCannonball.java
index 3c4baa9fa..0ffb886b1 100644
--- a/src/main/java/net/minecraft/core/world/ExplosionCannonball.java
+++ b/src/main/java/net/minecraft/core/world/ExplosionCannonball.java
@@ -172,7 +172,7 @@ public class ExplosionCannonball extends Explosion{
                     ||  Block.blocksList[i1].blockMaterial == Material.decoration
                     ||  Block.blocksList[i1].blockMaterial == Material.ice))
             {
-                Block.blocksList[i1].dropBlockWithCause(worldObj, EnumDropCause.EXPLOSION, x, y, z, worldObj.getBlockMetadata(x, y, z), blockEntity);
+                Block.blocksList[i1].dropBlockWithCause(worldObj, EnumDropCause.EXPLOSION, x, y, z, worldObj.getBlockMetadata(x, y, z), blockEntity, null);
                 worldObj.setBlockWithNotify(x, y, z, 0);
                 Block.blocksList[i1].onBlockDestroyedByExplosion(worldObj, x, y, z);
             }
diff --git a/src/main/java/net/minecraft/core/world/SpawnerMobs.java b/src/main/java/net/minecraft/core/world/SpawnerMobs.java
index e76a443a7..8e2d7aa8a 100644
--- a/src/main/java/net/minecraft/core/world/SpawnerMobs.java
+++ b/src/main/java/net/minecraft/core/world/SpawnerMobs.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.world;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.BedBlock;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.data.gamerule.GameRules;
@@ -22,6 +23,7 @@ import net.minecraft.core.world.chunk.ChunkPosition;
 import net.minecraft.core.world.pathfinder.Node;
 import net.minecraft.core.world.pathfinder.Path;
 import net.minecraft.core.world.pathfinder.PathFinder;
+import org.slf4j.Logger;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -32,6 +34,7 @@ import java.util.Map;
 import java.util.Set;
 public final class SpawnerMobs
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private static final Set<ChunkCoordinate> eligibleChunksForSpawning = new HashSet<>();
     private static final Class<?>[] nightSpawnEntities;
 
@@ -166,7 +169,7 @@ public final class SpawnerMobs
                         try {
                             mobToSpawn = (Mob) spawnListEntry.entityClass.getConstructor(new Class[]{World.class}).newInstance(new Object[]{world});
                         } catch (Exception e) {
-                            new RuntimeException("Error spawning entity class '" + spawnListEntry.entityClass.getSimpleName() + "' class missing default constructor for World! Skipping spawn attempt!", e).printStackTrace();
+                            LOGGER.error("Error spawning entity class '{}' class missing default constructor for World! Skipping spawn attempt!", spawnListEntry.entityClass.getSimpleName(), e);
                             return totalSpawned;
                         }
 
@@ -189,9 +192,9 @@ public final class SpawnerMobs
         return totalSpawned;
     }
 
-    private static boolean canCreatureTypeSpawnAtLocation(MobCategory enumcreaturetype, World world, int x, int y, int z)
+    private static boolean canCreatureTypeSpawnAtLocation(MobCategory mobCategory, World world, int x, int y, int z)
     {
-        if(enumcreaturetype.getSpawnMaterial() == Material.water)
+        if(mobCategory.getSpawnMaterial() == Material.water)
         {
             return world.getBlockMaterial(x, y, z).isLiquid() && !world.isBlockNormalCube(x, y + 1, z);
         } else
@@ -266,13 +269,14 @@ public final class SpawnerMobs
 						float entityZ = z + 0.5f;
 						
 						Mob entity;
+                        Class<?> eClass= entityClasses[world.rand.nextInt(entityClasses.length)];
 						try
                         {
-							entity = (Mob) entityClasses[world.rand.nextInt(entityClasses.length)].getConstructor(World.class).newInstance(world);
+							entity = (Mob) eClass.getConstructor(World.class).newInstance(world);
 						}
                         catch (Exception e)
                         {
-							e.printStackTrace();
+                            LOGGER.error("Exception instancing class '{}'!", eClass.getSimpleName(), e);
 							return spawnedEntity;
 						}
 						
diff --git a/src/main/java/net/minecraft/core/world/World.java b/src/main/java/net/minecraft/core/world/World.java
index 5d9430b20..a0c38fa64 100644
--- a/src/main/java/net/minecraft/core/world/World.java
+++ b/src/main/java/net/minecraft/core/world/World.java
@@ -11,7 +11,9 @@ import java.util.List;
 import java.util.Random;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.UUID;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 
 import net.minecraft.client.option.enums.Difficulty;
@@ -70,9 +72,10 @@ import net.minecraft.core.world.weather.Weather;
 import net.minecraft.core.world.weather.WeatherManager;
 import net.minecraft.core.world.weather.Weathers;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
 
 public class World implements WorldSource {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static boolean AUTOSAVE = true;
 
     public static final int HEIGHT_BLOCKS = 256;
@@ -97,6 +100,9 @@ public class World implements WorldSource {
     public int skyDarken = 0;
     protected int updateLCG = new Random().nextInt();
     public int lightningFlicker = 0;
+    public int rainbowTicks = 0;
+    public int startingRainbowTicks = 0;
+    public boolean dayCanHaveRainbow = true;
     public boolean editingBlocks = false;
     private long lockTimestamp = System.currentTimeMillis();
     //protected int autosavePeriod = 40;
@@ -359,7 +365,7 @@ public class World implements WorldSource {
         }
         catch(Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Failed to spawn player with loaded chunks!", e);
         }
     }
 
@@ -1389,6 +1395,10 @@ public class World implements WorldSource {
         return true;
     }
 
+    public void addRainbow(int rainbowTicks){
+        this.rainbowTicks = startingRainbowTicks = rainbowTicks;
+    }
+
     public boolean entityJoinedWorld(Entity entity)
     {
         int i = MathHelper.floor(entity.x / Chunk.CHUNK_SIZE_X);
@@ -2521,6 +2531,10 @@ public class World implements WorldSource {
 		updateBlocksAndPlayCaveSounds();
         Debug.change("season&light");
 		updateSeasonAndLight();
+        if(rainbowTicks > 0)
+        {
+            rainbowTicks--;
+        }
         Debug.pop();
 	}
 	
@@ -2531,6 +2545,11 @@ public class World implements WorldSource {
 		int currentDayCount = ((int) (levelData.getWorldTime() / Global.DAY_LENGTH_TICKS));
 		if(currentDayCount != dayCountLastTick) {
 			dayCountLastTick = currentDayCount;
+            if (!isClientSide){
+                dayCanHaveRainbow = rand.nextInt(3) == 0;
+            } else {
+                dayCanHaveRainbow = true;
+            }
 			seasonChanged = true;
 		}
 
@@ -2911,6 +2930,17 @@ public class World implements WorldSource {
         return null;
     }
 
+    public Player getPlayerEntityByUUID(UUID uuid)
+    {
+        for (Player player : players) {
+            if (uuid.equals(player.uuid)) {
+                return player;
+            }
+        }
+
+        return null;
+    }
+
     public void setChunkData(int x, int y, int z, int width, int height, int length, byte[] data)
     {
         int minChunkX = Math.floorDiv(x, Chunk.CHUNK_SIZE_X);
diff --git a/src/main/java/net/minecraft/core/world/biome/data/BiomeRangeMap.java b/src/main/java/net/minecraft/core/world/biome/data/BiomeRangeMap.java
index 3744485b5..2205a37e8 100644
--- a/src/main/java/net/minecraft/core/world/biome/data/BiomeRangeMap.java
+++ b/src/main/java/net/minecraft/core/world/biome/data/BiomeRangeMap.java
@@ -1,19 +1,19 @@
 package net.minecraft.core.world.biome.data;
 
 import com.b100.utils.ImageUtils;
-import net.minecraft.core.Global;
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.core.world.biome.Biome;
+import org.slf4j.Logger;
 
-import javax.imageio.ImageIO;
 import java.awt.*;
 import java.awt.image.BufferedImage;
-import java.io.File;
 import java.util.*;
 
 public final class BiomeRangeMap
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private final Map<Biome, Set<BiomeRange>> ranges = new LinkedHashMap<>();
     private BiomeRangeLookup lookup = null;
 
@@ -55,7 +55,7 @@ public final class BiomeRangeMap
                         Biome biome = lookupBiome(temperature, humidity, altitude, variety);
 
                         if (biome == null) {
-                            System.out.println("Gap found in biome map at:\nTemperature: " + temperature + "\nHumidity: " + humidity + "\nAltitude: " + altitude);
+                            LOGGER.warn("Gap found in biome map at:\nTemperature: {}\nHumidity: {}\nAltitude: {}", temperature, humidity, altitude);
                             return true;
                         }
                     }
@@ -97,7 +97,7 @@ public final class BiomeRangeMap
 
         if (last == null)
         {
-            System.out.println("Warning: found NULL biome for T: " + temperature + " H: " + humidity + " A: " + altitude + " V: " + variety);
+            LOGGER.warn("Warning: found NULL biome for T: {} H: {} A: {} V: {}", temperature, humidity, altitude, variety);
         }
         return last;
     }
@@ -152,7 +152,7 @@ public final class BiomeRangeMap
         }
         catch (Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Failed to save BiomeLookup image!", e);
         }
     }
 
diff --git a/src/main/java/net/minecraft/core/world/chunk/Chunk.java b/src/main/java/net/minecraft/core/world/chunk/Chunk.java
index 29ef04308..d894a238d 100644
--- a/src/main/java/net/minecraft/core/world/chunk/Chunk.java
+++ b/src/main/java/net/minecraft/core/world/chunk/Chunk.java
@@ -1,5 +1,7 @@
 package net.minecraft.core.world.chunk;
 
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.util.helper.MathHelper;
@@ -9,11 +11,13 @@ import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.world.biome.Biome;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.EntityBlock;
+import org.slf4j.Logger;
 
 import java.util.*;
 
 public class Chunk
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static final int CHUNK_SIZE_X = 16;
     public static final int CHUNK_SIZE_Z = 16;
     public static final int CHUNK_SECTIONS = 16;
@@ -440,7 +444,7 @@ public class Chunk
         int z = MathHelper.floor(entity.z / CHUNK_SIZE_Z);
         if(x != xPosition || z != zPosition)
         {
-            System.out.println("Wrong location! " + entity);
+            LOGGER.warn("Wrong location! {}", entity);
             Thread.dumpStack();
         }
         int section = MathHelper.clamp(MathHelper.floor(entity.y / 16D), 0, CHUNK_SECTIONS - 1);
@@ -514,7 +518,7 @@ public class Chunk
         blockEntity.z = zPosition * CHUNK_SIZE_Z + z;
         if (getBlockID(x, y, z) == 0 || !(Block.blocksList[getBlockID(x, y, z)] instanceof EntityBlock))
         {
-            System.out.println("Attempted to place a tile entity where there was no entity tile!");
+            LOGGER.warn("Attempted to place a tile entity where there was no entity tile!");
         }
         else
         {
diff --git a/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java b/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java
index d2b82cd93..41b6334c4 100644
--- a/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java
+++ b/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.world.chunk;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.Global;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.EntityDispatcher;
@@ -17,14 +18,16 @@ import net.minecraft.core.world.data.ChunkUnsignedByteArray;
 import net.minecraft.core.world.World;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.world.save.LevelData;
+import org.slf4j.Logger;
 
 import java.io.*;
+import java.nio.file.Files;
 import java.util.*;
 
 public class ChunkLoaderLegacy
     implements IChunkLoader
 {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     public ChunkLoaderLegacy(File worldDir, boolean createIfNecessary)
     {
         this.worldDir = worldDir;
@@ -86,22 +89,22 @@ public class ChunkLoaderLegacy
         {
             try
             {
-                FileInputStream fileStream = new FileInputStream(file);
+                InputStream fileStream = Files.newInputStream(file.toPath());
                 CompoundTag tag = NbtIo.readCompressed(fileStream);
                 if(!tag.containsKey("Level"))
                 {
-                    System.out.println("Chunk file at " + x + "," + z + " is missing level data, skipping");
+                    LOGGER.warn("Chunk file at {},{} is missing level data, skipping", x, z);
                     return null;
                 }
                 if(!tag.getCompound("Level").containsKey("Blocks"))
                 {
-                    System.out.println("Chunk file at " + x + "," + z + " is missing block data, skipping");
+                    LOGGER.warn("Chunk file at {},{} is missing block data, skipping", x, z);
                     return null;
                 }
                 Chunk chunk = loadChunkIntoWorldFromCompound(world, tag.getCompound("Level"));
                 if(!chunk.isAtLocation(x, z))
                 {
-                    System.out.println("Chunk file at " + x + "," + z + " is in the wrong location; relocating. (Expected " + x + ", " + z + ", got " + chunk.xPosition + ", " + chunk.zPosition + ")");
+                    LOGGER.warn("Chunk file at {},{} is in the wrong location; relocating. (Expected {}, {}, got {}, {})", x, z, x, z, chunk.xPosition, chunk.zPosition);
                     tag.putInt("xPos", x);
                     tag.putInt("zPos", z);
                     chunk = loadChunkIntoWorldFromCompound(world, tag.getCompound("Level"));
@@ -111,7 +114,7 @@ public class ChunkLoaderLegacy
             }
             catch(Exception exception)
             {
-                exception.printStackTrace();
+                LOGGER.error("Exception while attempting to load chunk at X:{}, Z:{}", x, z, exception);
             }
         }
         return null;
@@ -131,7 +134,7 @@ public class ChunkLoaderLegacy
         try
         {
             File tmpChunkFile = new File(worldDir, "tmp_chunk.dat");
-            FileOutputStream fileStream = new FileOutputStream(tmpChunkFile);
+            OutputStream fileStream = Files.newOutputStream(tmpChunkFile.toPath());
             CompoundTag levelTag = new CompoundTag();
             CompoundTag chunkDataTag = new CompoundTag();
             levelTag.put("Level", chunkDataTag);
@@ -148,7 +151,7 @@ public class ChunkLoaderLegacy
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Exception while attempting to save chunk at X:{}, Z:{}", chunk.xPosition, chunk.zPosition, exception);
         }
     }
 
diff --git a/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java b/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java
index 0e4f16d97..025affe31 100644
--- a/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java
+++ b/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java
@@ -1,16 +1,19 @@
 package net.minecraft.core.world.chunk;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.world.World;
 import net.minecraft.core.world.save.LevelData;
 import net.minecraft.core.world.save.mcregion.RegionFileCache;
 import com.mojang.nbt.NbtIo;
+import org.slf4j.Logger;
 
 import java.io.*;
 
 public class ChunkLoaderRegion
     implements IChunkLoader
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private final File worldDir;
 
     public ChunkLoaderRegion(File worldDir)
@@ -34,13 +37,13 @@ public class ChunkLoaderRegion
         }
         if(!tag.containsKey("Level"))
         {
-            System.out.println("Chunk file at " + x + "," + z + " is missing level data, skipping");
+            LOGGER.warn("Chunk file at {},{} is missing level data, skipping", x, z);
             return null;
         }
         Chunk chunk = ChunkLoaderLegacy.loadChunkIntoWorldFromCompound(world, tag.getCompound("Level"));
         if(!chunk.isAtLocation(x, z))
         {
-            System.out.println("Chunk file at " + x + "," + z + " is in the wrong location; relocating. (Expected " + x + ", " + z + ", got " + chunk.xPosition + ", " + chunk.zPosition + ")");
+            LOGGER.warn("Chunk file at {},{} is in the wrong location; relocating. (Expected {}, {}, got {}, {})", x, z, x, z, chunk.xPosition, chunk.zPosition);
             tag.putInt("xPos", x);
             tag.putInt("zPos", z);
             chunk = ChunkLoaderLegacy.loadChunkIntoWorldFromCompound(world, tag.getCompound("Level"));
@@ -68,7 +71,7 @@ public class ChunkLoaderRegion
         }
         catch (Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Exception while attempting to save chunk at X:{}, Z:{}", chunk.xPosition, chunk.zPosition, exception);
         }
     }
 
diff --git a/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegionAsync.java b/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegionAsync.java
index a3654058e..c4d6edc21 100644
--- a/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegionAsync.java
+++ b/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegionAsync.java
@@ -1,6 +1,8 @@
 package net.minecraft.core.world.chunk;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 import java.io.File;
 import java.io.IOException;
@@ -13,6 +15,7 @@ import java.util.concurrent.locks.ReentrantLock;
 public class ChunkLoaderRegionAsync
     implements IChunkLoader
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private static final Queue<Chunk> chunksToSave = new LinkedList<>();
     private static final Queue<World> worldsToSave = new LinkedList<>();
     private static final Queue<ChunkLoaderRegion> chunkLoaders = new LinkedList<>();
@@ -86,7 +89,7 @@ public class ChunkLoaderRegionAsync
                         notEmpty.await();
                     }
                 } catch (IOException | InterruptedException e) {
-                    e.printStackTrace();
+                    LOGGER.error("Exception while attempting to save chunks in async loader", e);
                 } finally {
                     lockChunksToSave.unlock();
                 }
diff --git a/src/main/java/net/minecraft/core/world/chunk/LightUpdate.java b/src/main/java/net/minecraft/core/world/chunk/LightUpdate.java
index 46403e045..771747964 100644
--- a/src/main/java/net/minecraft/core/world/chunk/LightUpdate.java
+++ b/src/main/java/net/minecraft/core/world/chunk/LightUpdate.java
@@ -3,13 +3,23 @@ package net.minecraft.core.world.chunk;
 // Referenced classes of package net.minecraft.src:
 //            World, Chunk, Block, EnumSkyBlock
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
 import net.minecraft.core.enums.LightLayer;
 import net.minecraft.core.world.World;
+import org.slf4j.Logger;
 
 public class LightUpdate
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    public final LightLayer layer;
+    public int minX;
+    public int minY;
+    public int minZ;
+    public int maxX;
+    public int maxY;
+    public int maxZ;
+
 
     public LightUpdate(LightLayer layer, int minX, int minY, int minZ, int maxX, int maxY, int maxZ)
     {
@@ -31,7 +41,7 @@ public class LightUpdate
         int area = sizeX * sizeY * sizeZ;
         if(area > Chunk.CHUNK_SIZE_X * Chunk.CHUNK_SIZE_Z * world.getHeightBlocks())
         {
-            System.out.println("Light too large, skipping!");
+            LOGGER.warn("Light too large, skipping!");
             return;
         }
 
@@ -230,12 +240,4 @@ public class LightUpdate
         }
         return false;
     }
-
-    public final LightLayer layer;
-    public int minX;
-    public int minY;
-    public int minZ;
-    public int maxX;
-    public int maxY;
-    public int maxZ;
 }
diff --git a/src/main/java/net/minecraft/core/world/chunk/MissingBlockFixer.java b/src/main/java/net/minecraft/core/world/chunk/MissingBlockFixer.java
index c45e05b97..ec93f9182 100644
--- a/src/main/java/net/minecraft/core/world/chunk/MissingBlockFixer.java
+++ b/src/main/java/net/minecraft/core/world/chunk/MissingBlockFixer.java
@@ -4,11 +4,14 @@ package net.minecraft.core.world.chunk;
 // Referenced classes of package net.minecraft.src:
 //            Block
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.Block;
-import net.minecraft.core.block.Blocks;
+import org.slf4j.Logger;
 
 public class MissingBlockFixer
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private static final short[] blocksArray;
 
     public MissingBlockFixer()
     {
@@ -22,8 +25,6 @@ public class MissingBlockFixer
         }
     }
 
-    private static final short[] blocksArray;
-
     static 
     {
         blocksArray = new short[Block.blocksList.length];
@@ -41,7 +42,7 @@ public class MissingBlockFixer
         }
         catch (Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Exception initializing blocksArray!", exception);
         }
     }
 }
diff --git a/src/main/java/net/minecraft/core/world/data/SynchedEntityData.java b/src/main/java/net/minecraft/core/world/data/SynchedEntityData.java
index f143486cb..85fe76d42 100644
--- a/src/main/java/net/minecraft/core/world/data/SynchedEntityData.java
+++ b/src/main/java/net/minecraft/core/world/data/SynchedEntityData.java
@@ -3,6 +3,8 @@ package net.minecraft.core.world.data;
 import net.minecraft.core.item.ItemStack;
 import net.minecraft.core.net.packet.Packet;
 import net.minecraft.core.world.chunk.ChunkCoordinates;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.io.*;
 import java.util.*;
@@ -21,14 +23,18 @@ public class SynchedEntityData
     public static final int TYPE_STRING = 4;
     public static final int TYPE_ITEMSTACK = 5;
     public static final int TYPE_CHUNK_COORDINATE = 6;
+    public static final int TYPE_UUID = 7;
 
     // Format Constants
     public static final int MAX_DATA_VALUE = 31;
     public static final int TYPE_MASK = 0b1110_0000;
     public static final int TYPE_SHIFT = 5;
+
+    public static final int META_NULL = 0b0000_0001;
+
     public static final int END_MARKER = 127;
     private static final HashMap<Class<?>, Integer> DATA_TYPES = new HashMap<>();
-    private final Map<Integer, DataItem<?>> itemsById = new HashMap<>();
+    private final Map<Integer, @NotNull DataItem<?>> itemsById = new HashMap<>();
     private boolean isDirty;
 
     /**
@@ -61,6 +67,36 @@ public class SynchedEntityData
         }
     }
 
+    /**
+     * Attempts to define a new piece of synchronized data.
+     * @param id The ID of the data item.
+     * @param valueClass The class to define for the data item, which will default the initial value to null.
+     * @param <T> The type of the data item.
+     */
+    public <T> void define(int id, Class<T> valueClass)
+    {
+        Integer integer = DATA_TYPES.get(valueClass);
+        if(integer == null)
+        {
+            throw new IllegalArgumentException("Unknown data type: " + valueClass);
+        }
+
+        if(id > MAX_DATA_VALUE)
+        {
+            throw new IllegalArgumentException("Data value id is too big with " + id + "! (Max is " + MAX_DATA_VALUE + ")");
+        }
+
+        if(itemsById.containsKey(id))
+        {
+            throw new IllegalArgumentException("Duplicate id value for " + id + "!");
+        }
+        else
+        {
+            DataItem<T> item = new DataItem<>(integer, id, null);
+            itemsById.put(id, item);
+        }
+    }
+
     /**
      * Fetches the value for a specific item as a byte.
      * @param id The item ID.
@@ -106,16 +142,29 @@ public class SynchedEntityData
         return (ItemStack) itemsById.get(id).getValue();
     }
 
+    /**
+     * Fetches the value for a specific item as a UUID.
+     * @param id The item ID.
+     */
+    public UUID getUUID(int id) {
+        return (UUID) itemsById.get(id).getValue();
+    }
     /**
      * Sets the value for a defined item.
      * @param id The item ID.
      * @param value The value to assign to the item.
      * @param <T> The type of the data item.
      */
-    public <T> void set(int id, T value)
+    public <T> void set(int id, @Nullable T value)
     {
         DataItem<T> item = (DataItem<T>)itemsById.get(id);
-        if(!value.equals(item.getValue()))
+        if (value == null && item.getValue() != null) {
+            item.setValue(null);
+            item.setDirty(true);
+            isDirty = true;
+            return;
+        }
+        if(value != null && !value.equals(item.getValue()))
         {
             item.setValue(value);
             item.setDirty(true);
@@ -204,39 +253,56 @@ public class SynchedEntityData
         int typeValueByte = (di.getType() << TYPE_SHIFT | di.getId() & ~TYPE_MASK) & 0xFF;
         dos.writeByte(typeValueByte);
 
+        byte metadata = 0;
+        T value = di.getValue();
+        if (value == null) {
+            metadata |= META_NULL;
+            dos.writeByte(metadata);
+            return;
+        }
+
         switch(di.getType()) {
             case TYPE_BYTE:
-                dos.writeByte((Byte) di.getValue());
+                dos.write(metadata);
+                dos.writeByte((Byte) value);
                 break;
             case TYPE_SHORT:
-                dos.writeShort((Short) di.getValue());
+                dos.write(metadata);
+                dos.writeShort((Short) value);
                 break;
             case TYPE_INT:
-                dos.writeInt((Integer) di.getValue());
+                dos.write(metadata);
+                dos.writeInt((Integer) value);
                 break;
             case TYPE_FLOAT:
-                dos.writeFloat((Float) di.getValue());
+                dos.write(metadata);
+                dos.writeFloat((Float) value);
                 break;
             case TYPE_STRING:
-                Packet.writeString((String)di.getValue(), dos);
+                String s = (String)value;
+                dos.write(metadata);
+                Packet.writeString(s, dos);
                 break;
             case TYPE_ITEMSTACK:
-                ItemStack itemStack = (ItemStack)di.getValue();
-                if (itemStack == ItemStack.NO_ITEM){
-                    dos.writeShort(-1);
-                    dos.writeByte(-1);
-                    dos.writeShort(-1);
-                } else {
-                    dos.writeShort(itemStack.getItem().id);
-                    dos.writeByte(itemStack.stackSize);
-                    dos.writeShort(itemStack.getMetadata());
-                }
+                ItemStack itemStack = (ItemStack)value;
+                dos.write(metadata);
+                dos.writeShort(itemStack.getItem().id);
+                dos.writeByte(itemStack.stackSize);
+                dos.writeShort(itemStack.getMetadata());
                 break;
             case TYPE_CHUNK_COORDINATE:
-                ChunkCoordinates chunkcoordinates = (ChunkCoordinates)di.getValue();
+                ChunkCoordinates chunkcoordinates = (ChunkCoordinates)value;
+                dos.write(metadata);
                 dos.writeInt(chunkcoordinates.x);
                 dos.writeInt(chunkcoordinates.y);
                 dos.writeInt(chunkcoordinates.z);
+
+                break;
+            case TYPE_UUID:
+                UUID uuid = (UUID) value;
+                dos.write(metadata);
+                dos.writeLong(uuid.getMostSignificantBits());
+                dos.writeLong(uuid.getLeastSignificantBits());
                 break;
         }
     }
@@ -260,40 +326,45 @@ public class SynchedEntityData
             }
             int type = (data & TYPE_MASK) >> TYPE_SHIFT;
             int id = data & ~TYPE_MASK;
-            DataItem<?> di = null;
-            switch(type)
-            {
-                case TYPE_BYTE:
-                    di = new DataItem<>(type, id, dis.readByte());
-                    break;
-                case TYPE_SHORT:
-                    di = new DataItem<>(type, id, dis.readShort());
-                    break;
-                case TYPE_INT:
-                    di = new DataItem<>(type, id, dis.readInt());
-                    break;
-                case TYPE_FLOAT:
-                    di = new DataItem<>(type, id, dis.readFloat());
-                    break;
-                case TYPE_STRING:
-                    di = new DataItem<>(type, id, Packet.readString(dis, 64));
-                    break;
-                case TYPE_ITEMSTACK:
-                    short itemId = dis.readShort();
-                    byte itemCount = dis.readByte();
-                    short itemData = dis.readShort();
-                    if (itemId == -1){
-                        di = new DataItem<>(type, id, ItemStack.NO_ITEM);
-                    } else {
+            byte metadata = dis.readByte();
+
+            DataItem<?> di = new DataItem<>(type, id, null);
+            if ((metadata & META_NULL) == 0) { // if not marked as null
+                switch(type)
+                {
+                    case TYPE_BYTE:
+                        di = new DataItem<>(type, id, dis.readByte());
+                        break;
+                    case TYPE_SHORT:
+                        di = new DataItem<>(type, id, dis.readShort());
+                        break;
+                    case TYPE_INT:
+                        di = new DataItem<>(type, id, dis.readInt());
+                        break;
+                    case TYPE_FLOAT:
+                        di = new DataItem<>(type, id, dis.readFloat());
+                        break;
+                    case TYPE_STRING:
+                        di = new DataItem<>(type, id, Packet.readString(dis, 64));
+                        break;
+                    case TYPE_ITEMSTACK:
+                        short itemId = dis.readShort();
+                        byte itemCount = dis.readByte();
+                        short itemData = dis.readShort();
                         di = new DataItem<>(type, id, new ItemStack(itemId, itemCount, itemData));
-                    }
-                    break;
-                case TYPE_CHUNK_COORDINATE:
-                    int x = dis.readInt();
-                    int y = dis.readInt();
-                    int z = dis.readInt();
-                    di = new DataItem<>(type, id, new ChunkCoordinates(x, y, z));
-                    break;
+                        break;
+                    case TYPE_CHUNK_COORDINATE:
+                        int x = dis.readInt();
+                        int y = dis.readInt();
+                        int z = dis.readInt();
+                        di = new DataItem<>(type, id, new ChunkCoordinates(x, y, z));
+                        break;
+                    case TYPE_UUID:
+                        long msb = dis.readLong();
+                        long lsb = dis.readLong();
+                        di = new DataItem<>(type, id, new UUID(msb, lsb));
+                        break;
+                }
             }
             out.add(di);
             data = dis.readByte();
@@ -328,6 +399,7 @@ public class SynchedEntityData
         DATA_TYPES.put(String.class, TYPE_STRING);
         DATA_TYPES.put(ItemStack.class, TYPE_ITEMSTACK);
         DATA_TYPES.put(ChunkCoordinates.class, TYPE_CHUNK_COORDINATE);
+        DATA_TYPES.put(UUID.class, TYPE_UUID);
     }
 
     /**
@@ -338,7 +410,7 @@ public class SynchedEntityData
     {
         private final int type;
         private final int id;
-        private T value;
+        private @Nullable T value;
         private boolean dirty;
 
         /**
@@ -347,7 +419,7 @@ public class SynchedEntityData
          * @param id The ID of the data item.
          * @param value The initial value of the data item.
          */
-        public DataItem(int type, int id, T value)
+        public DataItem(int type, int id, @Nullable T value)
         {
             this.id = id;
             this.value = value;
@@ -367,7 +439,7 @@ public class SynchedEntityData
          * Sets the value of the data item.
          * @param value The value to set.
          */
-        public void setValue(T value)
+        public void setValue(@Nullable T value)
         {
             this.value = value;
         }
@@ -375,7 +447,7 @@ public class SynchedEntityData
         /**
          * Fetches the value of the data item.
          */
-        public T getValue()
+        public @Nullable T getValue()
         {
             return this.value;
         }
diff --git a/src/main/java/net/minecraft/core/world/save/LevelData.java b/src/main/java/net/minecraft/core/world/save/LevelData.java
index d4f38340b..49f65145d 100644
--- a/src/main/java/net/minecraft/core/world/save/LevelData.java
+++ b/src/main/java/net/minecraft/core/world/save/LevelData.java
@@ -1,23 +1,39 @@
 package net.minecraft.core.world.save;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.client.option.enums.Difficulty;
 import net.minecraft.core.data.gamerule.GameRuleCollection;
 import net.minecraft.core.entity.player.Player;
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.NbtIo;
-import net.minecraft.core.world.Dimension;
 import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
 
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.util.List;
 
-// Referenced classes of package net.minecraft.src:
-//            NBTTagCompound, Player
-
 public class LevelData
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private long randomSeed;
+    private int spawnX;
+    private int spawnY;
+    private int spawnZ;
+    private long worldTime;
+    private long lastTimePlayed;
+    private long sizeOnDisk;
+    private CompoundTag playerTag;
+    private int dimension;
+    private int gamemode;
+    private @NotNull String levelName = "DEFAULT NAME";
+    private int saveVersion;
+    private boolean cheatsEnabled;
+    private @NotNull Difficulty difficulty = Difficulty.NORMAL;
+    private boolean difficultyLocked;
+    private GameRuleCollection gameRules;
+
 
     public LevelData(CompoundTag tag)
     {
@@ -110,7 +126,7 @@ public class LevelData
         CompoundTag nbttagcompound = new CompoundTag();
         Player entityplayer = null;
         CompoundTag nbttagcompound1 = null;
-        if(list.size() > 0)
+        if(!list.isEmpty())
         {
             entityplayer = list.get(0);
         }
@@ -279,12 +295,12 @@ public class LevelData
     {
         return lastTimePlayed;
     }
-    
+
     public int getGamemode()
     {
     	return gamemode;
     }
-    
+
     public void setGamemode(int gamemode)
     {
     	this.gamemode = gamemode;
@@ -299,7 +315,7 @@ public class LevelData
     {
     	return cheatsEnabled;
     }
-    
+
     public void setCheatsEnabled(boolean enabled)
     {
     	this.cheatsEnabled = enabled;
@@ -312,8 +328,14 @@ public class LevelData
 
     public void setDifficulty(int difficulty, boolean overrideLock) {
         if (!overrideLock && difficultyLocked) return;
-        if (difficulty < 0) new RuntimeException("Attempted to set difficulty to '" + difficulty + "' which is less then 0!").printStackTrace();
-        if (difficulty >= Difficulty.values().length) new RuntimeException("Attempted to set difficulty to '" + difficulty + "' which is more then the '" + Difficulty.values().length + "' difficulties!").printStackTrace();
+        if (difficulty < 0) {
+            LOGGER.warn("Attempted to set difficulty to '{}' which is less then 0!", difficulty);
+            difficulty = 0;
+        }
+        if (difficulty >= Difficulty.values().length) {
+            LOGGER.error("Attempted to set difficulty to '{}' which is more then the '{}' difficulties!", difficulty, Difficulty.values().length);
+            difficulty = Difficulty.values().length - 1;
+        }
         setDifficulty(Difficulty.values()[difficulty], overrideLock);
     }
 
@@ -328,21 +350,4 @@ public class LevelData
     public boolean getDifficultyLocked() {
         return difficultyLocked;
     }
-
-    private long randomSeed;
-    private int spawnX;
-    private int spawnY;
-    private int spawnZ;
-    private long worldTime;
-    private long lastTimePlayed;
-    private long sizeOnDisk;
-    private CompoundTag playerTag;
-    private int dimension;
-    private int gamemode;
-    private @NotNull String levelName = "DEFAULT NAME";
-    private int saveVersion;
-    private boolean cheatsEnabled;
-    private @NotNull Difficulty difficulty = Difficulty.NORMAL;
-    private boolean difficultyLocked;
-    private GameRuleCollection gameRules;
 }
diff --git a/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java b/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java
index f8475dbd3..bad31a653 100644
--- a/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java
+++ b/src/main/java/net/minecraft/core/world/save/SaveFormatBase.java
@@ -1,14 +1,14 @@
 package net.minecraft.core.world.save;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.helper.MathHelper;
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.Dimension;
+import org.slf4j.Logger;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.List;
@@ -16,6 +16,7 @@ import java.util.List;
 public abstract class SaveFormatBase
     implements ISaveFormat
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     protected final File savesDir;
 
     public SaveFormatBase(File savesDir)
@@ -54,7 +55,7 @@ public abstract class SaveFormatBase
             }
             catch(Exception ex)
             {
-                ex.printStackTrace();
+                LOGGER.error("Exception loading level dat for world '{}'!", worldDirName, ex);
             }
         }
         worldLevelDat = new File(worldDir, "level.dat_old");
@@ -68,7 +69,7 @@ public abstract class SaveFormatBase
             }
             catch(Exception ex)
             {
-                ex.printStackTrace();
+                LOGGER.error("Exception loading level dat old for world '{}'!", worldDirName, ex);
             }
         }
         return null;
@@ -103,7 +104,7 @@ public abstract class SaveFormatBase
             }
             catch (Exception ex)
             {
-                ex.printStackTrace();
+                LOGGER.error("Exception loading dimension dat '{}' for world '{}'!", dimensionId, worldDirName, ex);
             }
         }
         dimensionDat = new File(dimensionDir, "dimension.dat_old");
@@ -117,7 +118,7 @@ public abstract class SaveFormatBase
             }
             catch (Exception ex)
             {
-                ex.printStackTrace();
+                LOGGER.error("Exception loading dimension dat old '{}' for world '{}'!", dimensionId, worldDirName, ex);
             }
         }
 
@@ -186,14 +187,14 @@ public abstract class SaveFormatBase
         {
             try
             {
-                CompoundTag nbtRoot = NbtIo.readCompressed(new FileInputStream(worldLevelDat));
+                CompoundTag nbtRoot = NbtIo.readCompressed(Files.newInputStream(worldLevelDat.toPath()));
                 CompoundTag nbtRootData = nbtRoot.getCompound("Data");
                 nbtRootData.putString("LevelName", newName);
-                NbtIo.writeCompressed(nbtRoot, new FileOutputStream(worldLevelDat));
+                NbtIo.writeCompressed(nbtRoot, Files.newOutputStream(worldLevelDat.toPath()));
             }
             catch(Exception exception)
             {
-                exception.printStackTrace();
+                LOGGER.error("Failed to rename world '{}' to '{}'!", worldDirName, newName, exception);
             }
         }
     }
diff --git a/src/main/java/net/minecraft/core/world/save/SaveFormats.java b/src/main/java/net/minecraft/core/world/save/SaveFormats.java
index 6389a52b6..2c51aa4a9 100644
--- a/src/main/java/net/minecraft/core/world/save/SaveFormats.java
+++ b/src/main/java/net/minecraft/core/world/save/SaveFormats.java
@@ -1,9 +1,12 @@
 package net.minecraft.core.world.save;
 
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
 import net.minecraft.core.world.save.legacy.SaveFormatLegacy;
 import net.minecraft.core.world.save.mcregion.SaveFormat19132;
 import net.minecraft.core.world.save.mcregion.SaveFormat19133;
 import net.minecraft.core.world.save.mcregion.SaveFormat19134;
+import org.slf4j.Logger;
 
 import java.io.File;
 import java.util.HashMap;
@@ -11,6 +14,7 @@ import java.util.Map;
 
 public class SaveFormats
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     public static Map<Integer, Class<? extends ISaveFormat>> saveFormats;
 
     public static ISaveFormat createSaveFormat(int version, File savesDir)
@@ -23,7 +27,7 @@ public class SaveFormats
         }
         catch (Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Exception instancing ISaveFormat from '{}'!", version, e);
             return null;
         }
     }
diff --git a/src/main/java/net/minecraft/core/world/save/SaveHandlerBase.java b/src/main/java/net/minecraft/core/world/save/SaveHandlerBase.java
index cfb4e6793..3f8b1fb82 100644
--- a/src/main/java/net/minecraft/core/world/save/SaveHandlerBase.java
+++ b/src/main/java/net/minecraft/core/world/save/SaveHandlerBase.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.world.save;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.MinecraftException;
 import net.minecraft.core.entity.player.Player;
 import com.mojang.nbt.CompoundTag;
@@ -7,18 +8,18 @@ import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.chunk.ChunkLoaderLegacy;
 import net.minecraft.core.world.chunk.IChunkLoader;
+import org.slf4j.Logger;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.util.List;
 
 public abstract class SaveHandlerBase implements LevelStorage
 {
+	private static final Logger LOGGER = LogUtils.getLogger();
 	final String worldDirName;
 	final File saveDirectory;
 	final File playersDirectory;
@@ -46,12 +47,12 @@ public abstract class SaveHandlerBase implements LevelStorage
 	{
 		try {
 			File file = new File(saveDirectory, "session.lock");
-			try (DataOutputStream stream = new DataOutputStream(new FileOutputStream(file)))
+			try (DataOutputStream stream = new DataOutputStream(Files.newOutputStream(file.toPath())))
 			{
 				stream.writeLong(now);
 			}
 		} catch (IOException ioexception) {
-			ioexception.printStackTrace();
+			LOGGER.error("Failed to check session lock!", ioexception);
 			throw new RuntimeException("Failed to check session lock, aborting");
 		}
 	}
@@ -67,7 +68,7 @@ public abstract class SaveHandlerBase implements LevelStorage
 		try
 		{
 			File file = new File(saveDirectory, "session.lock");
-			try (DataInputStream datainputstream = new DataInputStream(new FileInputStream(file)))
+			try (DataInputStream datainputstream = new DataInputStream(Files.newInputStream(file.toPath())))
 			{
 				if (datainputstream.readLong() != now)
 				{
@@ -117,15 +118,15 @@ public abstract class SaveHandlerBase implements LevelStorage
 	@Override
 	public void saveLevelDataAndPlayerData(LevelData levelData, List<Player> playerList)
 	{
-		CompoundTag nbttagcompound = levelData.getNBTTagCompoundWithPlayer(playerList);
-		CompoundTag nbttagcompound1 = new CompoundTag();
-		nbttagcompound1.put("Data", nbttagcompound);
+		CompoundTag dataTag = levelData.getNBTTagCompoundWithPlayer(playerList);
+		CompoundTag savedTag = new CompoundTag();
+		savedTag.put("Data", dataTag);
 		try
 		{
 			File file = new File(saveDirectory, "level.dat_new");
 			File file1 = new File(saveDirectory, "level.dat_old");
 			File file2 = new File(saveDirectory, "level.dat");
-			NbtIo.writeCompressed(nbttagcompound1, new FileOutputStream(file));
+			NbtIo.writeCompressed(savedTag, Files.newOutputStream(file.toPath()));
 			if (file1.exists())
 			{
 				file1.delete();
@@ -143,7 +144,7 @@ public abstract class SaveHandlerBase implements LevelStorage
 		}
 		catch (Exception exception)
 		{
-			exception.printStackTrace();
+			LOGGER.error("Failed to save level data to disk!", exception);
 		}
 	}
 
@@ -182,7 +183,7 @@ public abstract class SaveHandlerBase implements LevelStorage
 		}
 		catch (Exception exception)
 		{
-			exception.printStackTrace();
+			LOGGER.error("Failed to save level data to disk!", exception);
 		}
 
 	}
@@ -226,7 +227,7 @@ public abstract class SaveHandlerBase implements LevelStorage
 		}
 		catch (Exception exception)
 		{
-			exception.printStackTrace();
+            LOGGER.error("Failed to save dimension {} data to disk!", dimensionId, exception);
 		}
 	}
 
diff --git a/src/main/java/net/minecraft/core/world/save/SaveHandlerServer.java b/src/main/java/net/minecraft/core/world/save/SaveHandlerServer.java
index e0e4995a5..d6c68b811 100644
--- a/src/main/java/net/minecraft/core/world/save/SaveHandlerServer.java
+++ b/src/main/java/net/minecraft/core/world/save/SaveHandlerServer.java
@@ -1,25 +1,27 @@
 package net.minecraft.core.world.save;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.entity.player.Player;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.world.chunk.IChunkLoader;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.chunk.ChunkLoaderRegion;
-import org.apache.log4j.Logger;
+import org.slf4j.Logger;
 
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.nio.file.Files;
 import java.util.List;
+import java.util.UUID;
 
 
 public class SaveHandlerServer
         extends SaveHandlerBase
         implements PlayerIO
 {
-    private static final Logger logger = Logger.getLogger("Minecraft");
+    private static final Logger LOGGER = LogUtils.getLogger();
 
     public SaveHandlerServer(ISaveFormat saveFormat, File savesDir, String worldDirName, boolean isMultiplayer)
     {
@@ -49,25 +51,26 @@ public class SaveHandlerServer
         {
             CompoundTag nbttagcompound = new CompoundTag();
             player.saveWithoutId(nbttagcompound);
-            File file = new File(playersDirectory, "_tmp_.dat");
-            File file1 = new File(playersDirectory, player.username + ".dat");
-            NbtIo.writeCompressed(nbttagcompound, new FileOutputStream(file));
-            if(file1.exists())
+            nbttagcompound.putInt("Format", 1);
+            File temp = new File(playersDirectory, "_tmp_.dat");
+            File save = new File(playersDirectory, player.uuid + ".dat");
+            NbtIo.writeCompressed(nbttagcompound, new FileOutputStream(temp));
+            if(save.exists())
             {
-                file1.delete();
+                save.delete();
             }
-            file.renameTo(file1);
+            temp.renameTo(save);
         }
         catch(Exception exception)
         {
-            logger.warn("Failed to save player data for " + player.username);
+            LOGGER.warn("Failed to save player data for " + player.username);
         }
     }
 
     @Override
     public void load(Player player)
     {
-        CompoundTag nbttagcompound = getPlayerData(player.username);
+        CompoundTag nbttagcompound = getPlayerData(player.username, player.uuid);
         if(nbttagcompound != null)
         {
             player.load(nbttagcompound);
@@ -80,19 +83,26 @@ public class SaveHandlerServer
         return this;
     }
 
-    private CompoundTag getPlayerData(String s)
+    private CompoundTag getPlayerData(String username, UUID uuid)
     {
         try
         {
-            File file = new File(playersDirectory, s + ".dat");
-            if(file.exists())
+            File uuidFile = new File(playersDirectory, uuid + ".dat");
+            if(uuidFile.exists())
             {
-                return NbtIo.readCompressed(new FileInputStream(file));
+                return NbtIo.readCompressed(Files.newInputStream(uuidFile.toPath()));
+            } else { // If the uuid file doesn't exist attempt to load the old username file
+                File nameFile = new File(playersDirectory, username + ".dat");
+                if (nameFile.exists()) {
+                    CompoundTag tag = NbtIo.readCompressed(Files.newInputStream(nameFile.toPath()));
+                    nameFile.renameTo(uuidFile);
+                    return tag;
+                }
             }
         }
         catch(Exception exception)
         {
-            logger.warn("Failed to load player data for " + s);
+            LOGGER.warn("Failed to load player data for " + username);
         }
         return null;
     }
diff --git a/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19132To19133.java b/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19132To19133.java
index eeb2b6182..0674d27fe 100644
--- a/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19132To19133.java
+++ b/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19132To19133.java
@@ -1,11 +1,13 @@
 package net.minecraft.core.world.save.conversion;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.NbtIo;
 import net.minecraft.core.world.Dimension;
 import net.minecraft.core.world.ProgressListener;
 import net.minecraft.core.world.save.mcregion.RegionFile;
 import net.minecraft.core.world.save.mcregion.RegionFileCache;
+import org.slf4j.Logger;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -17,6 +19,7 @@ import java.util.Collections;
 public class SaveConverter19132To19133
     extends SaveConverterMCRegionBase
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     @Override
     public int fromVersion()
     {
@@ -125,7 +128,7 @@ public class SaveConverter19132To19133
                     }
                     catch(IOException e)
                     {
-                        e.printStackTrace();
+                        LOGGER.error("Failed to convert chunk X:{}, Z:{}, in region {}!", x, z, region.toPath(), e);
                     }
 
                 }
diff --git a/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19133To19134.java b/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19133To19134.java
index 1790bc671..4f278edf6 100644
--- a/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19133To19134.java
+++ b/src/main/java/net/minecraft/core/world/save/conversion/SaveConverter19133To19134.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.world.save.conversion;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.data.legacy.LegacyWorldTypes;
 import net.minecraft.core.world.Dimension;
@@ -7,6 +8,7 @@ import net.minecraft.core.world.ProgressListener;
 import net.minecraft.core.world.save.DimensionData;
 import net.minecraft.core.world.save.ISaveFormat;
 import net.minecraft.core.world.save.SaveFormats;
+import org.slf4j.Logger;
 
 
 import java.io.*;
@@ -19,6 +21,7 @@ import java.util.Map;
 public class SaveConverter19133To19134
     extends SaveConverterMCRegionBase
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     @Override
     public int fromVersion()
     {
@@ -82,7 +85,7 @@ public class SaveConverter19133To19134
         List<File> dimensionDirs = new ArrayList<>();
         Map<File, ArrayList<File>> dimensionRegionFiles = new HashMap<>();
 
-        System.out.println("Scanning folders...");
+        LOGGER.info("Scanning folders...");
 
         // Add directory files for each present dimension
         for (Dimension dim : Dimension.getDimensionList().values())
@@ -102,7 +105,7 @@ public class SaveConverter19133To19134
         {
             totalConversions += dimensionRegionFiles.get(dimensionDir).size();
         }
-        System.out.println("Total conversion count is " + totalConversions);
+        LOGGER.info("Total conversion count is {}", totalConversions);
 
         // Convert regions for each dimension
         progress.progressStagePercentage(0);
@@ -144,7 +147,7 @@ public class SaveConverter19133To19134
                     }
                     catch (IOException e)
                     {
-                        e.printStackTrace();
+                        LOGGER.error("Failed to copy file {} to {}!", file.toPath(), new File(destDir, file.getName()).toPath(), e);
                     }
                 }
             }
diff --git a/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterLegacyTo19132.java b/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterLegacyTo19132.java
index bb3f826d1..b3df2469a 100644
--- a/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterLegacyTo19132.java
+++ b/src/main/java/net/minecraft/core/world/save/conversion/SaveConverterLegacyTo19132.java
@@ -1,5 +1,6 @@
 package net.minecraft.core.world.save.conversion;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.data.legacy.LegacyWorldTypes;
 import net.minecraft.core.world.ProgressListener;
@@ -11,16 +12,20 @@ import net.minecraft.core.world.save.legacy.ChunkFilePattern;
 import net.minecraft.core.world.save.legacy.ChunkFolderPattern;
 import net.minecraft.core.world.save.mcregion.RegionFile;
 import net.minecraft.core.world.save.mcregion.RegionFileCache;
+import org.slf4j.Logger;
 
 import java.io.*;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.zip.GZIPInputStream;
 
 public class SaveConverterLegacyTo19132
     implements ISaveConverter
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     @Override
     public int fromVersion()
     {
@@ -107,16 +112,16 @@ public class SaveConverterLegacyTo19132
         for(Iterator<ChunkFile> iterator = chunkFileList.iterator(); iterator.hasNext(); progress.progressStagePercentage(numConversions))
         {
             ChunkFile chunkfile = iterator.next();
-            int k = chunkfile.getX();
-            int l = chunkfile.getZ();
-            RegionFile regionfile = RegionFileCache.loadRegionFileFromCoords(file, k, l);
-            if(!regionfile.chunkExists(k & 0x1f, l & 0x1f))
+            int x = chunkfile.getX();
+            int z = chunkfile.getZ();
+            RegionFile regionfile = RegionFileCache.loadRegionFileFromCoords(file, x, z);
+            if(!regionfile.chunkExists(x & 0x1f, z & 0x1f))
             {
                 try
                 {
-                    DataInputStream datainputstream = new DataInputStream(new GZIPInputStream(new FileInputStream(chunkfile.getChunkFile())));
-                    DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(k & 0x1f, l & 0x1f);
-                    for(int j1 = 0; (j1 = datainputstream.read(fileBuffer)) != -1;)
+                    DataInputStream datainputstream = new DataInputStream(new GZIPInputStream(Files.newInputStream(chunkfile.getChunkFile().toPath())));
+                    DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(x & 0x1f, z & 0x1f);
+                    for(int j1; (j1 = datainputstream.read(fileBuffer)) != -1;)
                     {
                         dataoutputstream.write(fileBuffer, 0, j1);
                     }
@@ -126,7 +131,7 @@ public class SaveConverterLegacyTo19132
                 }
                 catch(IOException ioexception)
                 {
-                    ioexception.printStackTrace();
+                    LOGGER.error("Failed to convert chunk X:{}, Z:{}, in region {}!", x, z, regionfile);
                 }
             }
             conversionsPerformed++;
@@ -136,17 +141,17 @@ public class SaveConverterLegacyTo19132
         RegionFileCache.flushCache();
     }
 
-    private void deleteOldWorldData(ArrayList arraylist, int i, int j, ProgressListener iprogressupdate)
+    private void deleteOldWorldData(List<File> files, int conversionsPerformed, int totalConversions, ProgressListener progressListener)
     {
         int k;
-        for(Iterator iterator = arraylist.iterator(); iterator.hasNext(); iprogressupdate.progressStagePercentage(k))
+        for(Iterator<File> iterator = files.iterator(); iterator.hasNext(); progressListener.progressStagePercentage(k))
         {
-            File file = (File)iterator.next();
-            File afile[] = file.listFiles();
+            File file = iterator.next();
+            File[] afile = file.listFiles();
             deleteFilesRecursively(afile);
             file.delete();
-            i++;
-            k = (int)Math.round((100D * (double)i) / (double)j);
+            conversionsPerformed++;
+            k = (int)Math.round((100D * (double)conversionsPerformed) / (double)totalConversions);
         }
 
     }
diff --git a/src/main/java/net/minecraft/core/world/save/mcregion/RegionFile.java b/src/main/java/net/minecraft/core/world/save/mcregion/RegionFile.java
index 7b86cd0b7..5a6285166 100644
--- a/src/main/java/net/minecraft/core/world/save/mcregion/RegionFile.java
+++ b/src/main/java/net/minecraft/core/world/save/mcregion/RegionFile.java
@@ -1,5 +1,9 @@
 package net.minecraft.core.world.save.mcregion;
 
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
+import org.slf4j.Logger;
+
 import java.io.*;
 import java.util.ArrayList;
 import java.util.zip.*;
@@ -9,6 +13,7 @@ import java.util.zip.*;
  */
 public class RegionFile
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private static final byte[] emptySector = new byte[4096];
     private final File regionFile;
     private RandomAccessFile dataFile;
@@ -103,7 +108,7 @@ public class RegionFile
         }
         catch(IOException e)
         {
-            e.printStackTrace();
+            LOGGER.error("Failed to fully load region data for region '{}'!", regionFile.getPath());
         }
     }
 
@@ -124,7 +129,7 @@ public class RegionFile
      */
     private void print(String message)
     {
-//        System.out.println(message);
+        LOGGER.debug(message);
     }
 
     /**
@@ -380,7 +385,7 @@ public class RegionFile
         }
         catch(IOException ioexception)
         {
-            ioexception.printStackTrace();
+            LOGGER.error("Failed to fully write data for region file '{}'!", regionFile.getPath(), ioexception);
         }
     }
 
diff --git a/src/main/java/net/minecraft/core/world/save/mcregion/RegionFileCache.java b/src/main/java/net/minecraft/core/world/save/mcregion/RegionFileCache.java
index f13fa17ee..8c4d9c351 100644
--- a/src/main/java/net/minecraft/core/world/save/mcregion/RegionFileCache.java
+++ b/src/main/java/net/minecraft/core/world/save/mcregion/RegionFileCache.java
@@ -1,5 +1,8 @@
 package net.minecraft.core.world.save.mcregion;
 
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
+
 import java.io.*;
 import java.lang.ref.Reference;
 import java.lang.ref.SoftReference;
@@ -7,7 +10,7 @@ import java.util.*;
 
 public class RegionFileCache
 {
-
+    private static final Logger LOGGER = LogUtils.getLogger();
     private RegionFileCache()
     {
     }
@@ -52,7 +55,7 @@ public class RegionFileCache
             }
             catch (IOException ex)
             {
-                ex.printStackTrace();
+                LOGGER.error("Exception while flushing references", ex);
             }
         }
         cache.clear();
diff --git a/src/main/java/net/minecraft/core/world/saveddata/SavedDataStorage.java b/src/main/java/net/minecraft/core/world/saveddata/SavedDataStorage.java
index abd51f6a7..a33901707 100644
--- a/src/main/java/net/minecraft/core/world/saveddata/SavedDataStorage.java
+++ b/src/main/java/net/minecraft/core/world/saveddata/SavedDataStorage.java
@@ -1,10 +1,13 @@
 package net.minecraft.core.world.saveddata;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.Tag;
 import com.mojang.nbt.CompoundTag;
 import com.mojang.nbt.ShortTag;
 import com.mojang.nbt.NbtIo;
+import net.minecraft.core.Global;
 import net.minecraft.core.world.save.LevelStorage;
+import org.slf4j.Logger;
 
 import java.io.*;
 import java.nio.file.Files;
@@ -16,6 +19,7 @@ import java.util.*;
 
 public class SavedDataStorage
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
     private final LevelStorage storage;
     private final Map<Serializable, SavedData> cache;
     private final List<SavedData> loadedData;
@@ -52,7 +56,7 @@ public class SavedDataStorage
                     {
                         throw new RuntimeException("Failed to instantiate " + savedDataClass.toString(), exception1);
                     }
-                    FileInputStream fis = new FileInputStream(file);
+                    InputStream fis = Files.newInputStream(file.toPath());
                     CompoundTag tag = NbtIo.readCompressed(fis);
                     fis.close();
                     savedData.load(tag.getCompound("data"));
@@ -60,7 +64,7 @@ public class SavedDataStorage
             }
             catch(Exception e)
             {
-                e.printStackTrace();
+                LOGGER.error("Exception loading saved data for id '{}'!", id, e);
             }
         }
         if(savedData != null)
@@ -113,14 +117,14 @@ public class SavedDataStorage
                 savedData.save(dataTag);
                 CompoundTag tag = new CompoundTag();
                 tag.putCompound("data", dataTag);
-                FileOutputStream fos = new FileOutputStream(file);
+                OutputStream fos = Files.newOutputStream(file.toPath());
                 NbtIo.writeCompressed(tag, fos);
                 fos.close();
             }
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Failed to save data to '{}'!", storage.getDataFile(savedData.id).getPath(), exception);
         }
     }
 
@@ -151,7 +155,7 @@ public class SavedDataStorage
         }
         catch(Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Failed to load all savedata id counts!", e);
         }
     }
 
@@ -190,7 +194,7 @@ public class SavedDataStorage
         }
         catch(Exception e)
         {
-            e.printStackTrace();
+            LOGGER.error("Failed to create data file for '{}'!", storage.getDataFile("idcounts").getPath(), e);
         }
         return metadata;
     }
diff --git a/src/main/java/net/minecraft/core/world/weather/WeatherManager.java b/src/main/java/net/minecraft/core/world/weather/WeatherManager.java
index 47c3d9f4b..417b846d5 100644
--- a/src/main/java/net/minecraft/core/world/weather/WeatherManager.java
+++ b/src/main/java/net/minecraft/core/world/weather/WeatherManager.java
@@ -10,6 +10,7 @@ import java.util.Random;
 public class WeatherManager {
     private final World world;
 
+    private Weather lastWeather = null;
     private Weather currentWeather = null;
     private Weather nextWeather = null;
     private long weatherDuration = Global.DAY_LENGTH_TICKS;
@@ -34,6 +35,7 @@ public class WeatherManager {
             this.weatherIntensity = 1.0f;
         }
     }
+    public Weather getLastWeather() { return lastWeather; }
 
     public Weather getCurrentWeather() {
         return currentWeather;
@@ -56,6 +58,7 @@ public class WeatherManager {
     }
 
     public void overrideWeather(Weather currentWeather, Weather nextWeather, long weatherDuration, float weatherIntensity, float weatherPower) {
+        this.lastWeather = this.currentWeather;
         this.currentWeather = currentWeather;
         this.nextWeather = nextWeather;
         this.weatherDuration = weatherDuration;
@@ -64,6 +67,7 @@ public class WeatherManager {
     }
 
     public void overrideWeather(Weather weather, long duration, float power) {
+        lastWeather = currentWeather;
         currentWeather = weather;
         nextWeather = null;
         weatherDuration = duration;
@@ -91,7 +95,10 @@ public class WeatherManager {
         if (world.getSeasonManager().getCurrentSeason() == null)
             return false;
 
-        if (currentWeather == null) currentWeather = world.worldType.getDefaultWeather();
+        if (currentWeather == null) {
+            lastWeather = null;
+            currentWeather = world.worldType.getDefaultWeather();
+        }
 
         if (nextWeather == null && weatherIntensity <= 1.0f)
         {
@@ -102,8 +109,15 @@ public class WeatherManager {
         else if (nextWeather != null && weatherIntensity >= 0.0f)
         {
             weatherIntensity -= 0.002f;
+            if (!world.isClientSide) {
+                if (world.dayCanHaveRainbow && world.rainbowTicks <= 0 && weatherIntensity < 0.5f && currentWeather.precipitationType == 0 && !nextWeather.isPrecipitation){ // On rain end
+                    int rainbowTicks = world.rand.nextInt(20 * 90) + 20 * 30;
+                    world.addRainbow(rainbowTicks);
+                }
+            }
             if (weatherIntensity <= 0.0f) {
                 weatherIntensity = 0.0f;
+                lastWeather = currentWeather;
                 currentWeather = nextWeather;
                 weatherPower = getRandomWeatherPower();
                 nextWeather = null;
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index a4708ee33..a6511c78c 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1,5 +1,6 @@
 package net.minecraft.server;
 
+import com.mojang.logging.LogUtils;
 import com.mojang.nbt.CompoundTag;
 import net.minecraft.core.Global;
 import net.minecraft.core.MinecraftAccessor;
@@ -48,28 +49,22 @@ import net.minecraft.server.gui.ServerGui;
 import net.minecraft.server.net.ConsoleCommandHandler;
 import net.minecraft.server.net.NetworkListenThread;
 import net.minecraft.server.net.PlayerList;
-import net.minecraft.server.net.thread.ThreadCommandReader;
-import net.minecraft.server.net.thread.ThreadServerApplication;
-import net.minecraft.server.net.thread.ThreadSleepForeverServer;
 import net.minecraft.server.world.ConvertProgressUpdater;
 import net.minecraft.server.world.WorldManager;
 import net.minecraft.server.world.WorldServer;
 import net.minecraft.server.world.WorldServerMulti;
 import net.minecraft.server.world.chunk.provider.ChunkProviderServer;
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
+import org.slf4j.Logger;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
-import java.io.OutputStream;
+import java.io.InputStreamReader;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
 
@@ -79,6 +74,45 @@ import static net.minecraft.core.Global.isServer;
 public class MinecraftServer
         implements Runnable, ICommandListener, MinecraftAccessor
 {
+    public static Logger LOGGER = LogUtils.getLogger();
+    public static final String VERSION = Global.VERSION;
+    private static MinecraftServer instance;
+    public static HashMap<String, Integer> field_6037_b = new HashMap<>();
+    public NetworkListenThread networkServer;
+    public PropertyManager propertyManager;
+    public WorldServer[] dimensionWorlds;
+    public PlayerList playerList;
+    private ConsoleCommandHandler commandHandler;
+    private boolean serverRunning;
+    public boolean serverStopped;
+    int deathTime;
+    public String currentTask;
+    public int percentDone;
+    private final List<IUpdatePlayerListBox> playerListBoxes;
+    private final List<ServerCommandEntry> commands;
+    public EntityTracker[] entityTracker;
+    public boolean onlineMode;
+    public boolean pvpOn;
+    public boolean allowFlight;
+    public int spawnProtectionRange;
+    public WorldType defaultWorldType;
+    public int difficulty;
+    public final ServerCommandHandler serverCommandHandler = new ServerCommandHandler(this);
+    public String joinMessage = null;
+    public int summonLimit;
+    public String language;
+    public int sleepPercentage = 100;
+    public int maxPlayers = 20;
+    public Gamemode defaultGamemode;
+    public static String statsToken;
+    public static boolean statsStatus;
+    public boolean disablePhotoMode = false;
+    public String motd = "";
+    private final SkinVariantList skinVariantList = new ServerSkinVariantList();
+    public int autoSaveInterval = 5;
+    public int chunksSavedPerAutosave = 24;
+    public boolean forceSaveAllChunksOnAutosave = false;
+    public SpawnerMobs.SpawnerConfig spawnerConfig = new SpawnerMobs.SpawnerConfig();
 
     public MinecraftServer()
     {
@@ -86,9 +120,22 @@ public class MinecraftServer
         serverRunning = true;
         serverStopped = false;
         deathTime = 0;
-        field_9010_p = new ArrayList();
-        commands = Collections.synchronizedList(new ArrayList());
-        new ThreadSleepForeverServer(this);
+        playerListBoxes = new ArrayList<>();
+        commands = Collections.synchronizedList(new ArrayList<>());
+        Thread t = new Thread(
+            () -> {
+                do
+                {
+                    try
+                    {
+                        Thread.sleep(0x7fffffffL);
+                    }
+                    catch(InterruptedException ignored) { }
+                } while(true);
+            }
+        );
+        t.setDaemon(true);
+        t.start();
     }
 
     private boolean startServer()
@@ -97,14 +144,25 @@ public class MinecraftServer
         instance = this;
         isServer = true;
         commandHandler = new ConsoleCommandHandler(this);
-        ThreadCommandReader threadcommandreader = new ThreadCommandReader(this);
-        threadcommandreader.setDaemon(true);
-        threadcommandreader.start();
-        logger.info("Starting Better than Adventure! server for version " + VERSION);
+        Thread commandReadingThreads = new Thread(() -> {
+            BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in));
+            String s = null;
+            try {
+                while(!this.serverStopped && MinecraftServer.isServerRunning(this) && (s = bufferedreader.readLine()) != null) {
+                    this.addCommand(s, this);
+                }
+            }
+            catch(IOException ioexception) {
+                LOGGER.error("Exception occurred while adding command '{}'!", s, ioexception);
+            }
+        });
+        commandReadingThreads.setDaemon(true);
+        commandReadingThreads.start();
+        LOGGER.info("Starting Better than Adventure! server for version {}", VERSION);
         if (Runtime.getRuntime().maxMemory() / 1024L / 1024L < 512L)
         {
-            logger.warn("**** NOT ENOUGH RAM!");
-            logger.warn("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
+            LOGGER.warn("**** NOT ENOUGH RAM!");
+            LOGGER.warn("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
         }
 
         // Manually initialize blocks and items
@@ -113,7 +171,7 @@ public class MinecraftServer
 
         Dimension.init();
 
-        logger.info("Loading properties");
+        LOGGER.info("Loading properties");
         propertyManager = new PropertyManager(new File("server.properties"));
         String s = propertyManager.getStringProperty("server-ip", "");
         onlineMode = propertyManager.getBooleanProperty("online-mode", true);
@@ -195,8 +253,8 @@ public class MinecraftServer
         int groups = Registries.RECIPES.getAllGroups().size();
         int namespaces = Registries.RECIPES.size();
         int itemGroups = Registries.ITEM_GROUPS.size();
-        System.out.printf("%d item groups.%n",itemGroups);
-        System.out.printf("%d recipes in %d groups in %d namespaces.%n",recipes,groups,namespaces);
+        logInfo(String.format("%d item groups.",itemGroups));
+        logInfo(String.format("%d recipes in %d groups in %d namespaces.",recipes,groups,namespaces));
         
         SoundTypes.registerSounds();
         
@@ -204,70 +262,70 @@ public class MinecraftServer
 
         StatList.init();
 
-        if (!statsToken.equals("only-enter-a-value-if-you-are-a-registered-server") && !(statsToken.equals("")))
+        if (!statsToken.equals("only-enter-a-value-if-you-are-a-registered-server") && !(statsToken.isEmpty()))
         {
             statsStatus = true;
             int errorCode = RestHandler.post("https://api.betterthanadventure.net/stats?serverToken=" + statsToken + "&count=0");
             switch (errorCode)
             {
                 case 401:
-                    MinecraftServer.logger.warn("Your server stats token is invalid. Please clear server.properties -> stats-token");
+                    MinecraftServer.LOGGER.warn("Your server stats token is invalid. Please clear server.properties -> stats-token");
                     statsStatus = false;
                     break;
                 case 503:
-                    MinecraftServer.logger.warn("Cannot access server stats API! Your server might be offline.");
+                    MinecraftServer.LOGGER.warn("Cannot access server stats API! Your server might be offline.");
                     statsStatus = false;
                     break;
             }
         }
         InetAddress inetaddress = null;
-        if (s.length() > 0)
+        if (!s.isEmpty())
         {
             inetaddress = InetAddress.getByName(s);
         }
         int i = propertyManager.getIntProperty("server-port", 25565);
-        logger.info("Starting Minecraft server on " + (s.length() != 0 ? s : "*") + ":" + i);
+        LOGGER.info("Starting Minecraft server on " + (!s.isEmpty() ? s : "*") + ":" + i);
         try
         {
             networkServer = new NetworkListenThread(this, inetaddress, i);
         }
         catch (IOException ioexception)
         {
-            logger.warn("**** FAILED TO BIND TO PORT!");
-            logger.warn("The exception was: " + ioexception);
-            logger.warn("Perhaps a server is already running on that port?");
+            LOGGER.warn("**** FAILED TO BIND TO PORT!");
+            LOGGER.warn("The exception was: " + ioexception);
+            LOGGER.warn("Perhaps a server is already running on that port?");
             return false;
         }
         if (!onlineMode)
         {
-            logger.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
-            logger.warn("The server will make no attempt to authenticate usernames. Beware.");
-            logger.warn("While this makes the game possible to play without internet access, it also opens up the ability for hackers to connect with any username they choose.");
-            logger.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file.");
+            LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
+            LOGGER.warn("The server will make no attempt to authenticate usernames. Beware.");
+            LOGGER.warn("While this makes the game possible to play without internet access, it also opens up the ability for hackers to connect with any username they choose.");
+            LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file.");
         }
         playerList = new PlayerList(this);
         for (int q = 0; q < Dimension.getDimensionList().size(); q++)
         {
             entityTracker[q] = new EntityTracker(this, q);
         }
-        long l = System.nanoTime();
-        String s1 = propertyManager.getStringProperty("level-name", "world");
-        String s2 = propertyManager.getStringProperty("level-seed", "");
-        long l1 = (new Random()).nextLong();
-        if (s2.length() > 0)
+        long time = System.nanoTime();
+        String lName = propertyManager.getStringProperty("level-name", "world");
+        String lSeed = propertyManager.getStringProperty("level-seed", "");
+        long randomLong = (new Random()).nextLong();
+        if (!lSeed.isEmpty())
         {
             try
             {
-                l1 = Long.parseLong(s2);
+                randomLong = Long.parseLong(lSeed);
             }
             catch (NumberFormatException numberformatexception)
             {
-                l1 = s2.hashCode();
+                randomLong = lSeed.hashCode();
             }
         }
-        logger.info("Preparing level \"" + s1 + "\"");
-        initWorld(new SaveFormat19134(new File(".")), s1, l1);
-        logger.info("Generating RSA key...");
+        LOGGER.info("Preparing level \"{}\"", lName);
+        initWorld(new SaveFormat19134(new File(".")), lName, randomLong);
+        LOGGER.info("Generating RSA key...");
         try
         {
             RSA.RSAKeyChain = RSA.generateKeyPair();
@@ -276,7 +334,7 @@ public class MinecraftServer
         {
             throw new RuntimeException(e);
         }
-        logger.info("Done (" + (System.nanoTime() - l) + "ns)! For help, type \"help\" or \"?\"");
+        LOGGER.info("Done (" + (System.nanoTime() - time) + "ns)! For help, type \"help\" or \"?\"");
         return true;
     }
 
@@ -366,7 +424,7 @@ public class MinecraftServer
         label0:
         for (int j = 0; j < dimensionWorlds.length; j++)
         {
-            logger.info("Preparing start region for level " + j);
+            LOGGER.info("Preparing start region for level " + j);
             if (j == Dimension.nether.id && !propertyManager.getBooleanProperty("allow-nether", true))
             {
                 continue;
@@ -414,7 +472,7 @@ public class MinecraftServer
     {
         currentTask = s;
         percentDone = i;
-        logger.info(s + ": " + i + "%");
+        LOGGER.info("{}: {}%", s, i);
     }
 
     private void clearCurrentTask()
@@ -425,7 +483,7 @@ public class MinecraftServer
 
     private void saveServerWorld()
     {
-        logger.info("Saving chunks");
+        LOGGER.info("Saving chunks");
         for (int i = 0; i < dimensionWorlds.length; i++)
         {
             WorldServer worldserver = dimensionWorlds[i];
@@ -437,7 +495,7 @@ public class MinecraftServer
 
     private void stopServer()
     {
-        logger.info("Stopping server");
+        LOGGER.info("Stopping server");
         if (statsStatus)
         {
             RestHandler.post("https://api.betterthanadventure.net/stats?serverToken=" + statsToken + "&count=0");
@@ -473,12 +531,12 @@ public class MinecraftServer
                     long timeChange = currentTime - startTime;
                     if (timeChange > 2000L)
                     {
-                        logger.warn("Can't keep up! Did the system time change, or is the server overloaded?");
+                        LOGGER.warn("Can't keep up! Did the system time change, or is the server overloaded?");
                         timeChange = 2000L;
                     }
                     if (timeChange < 0L)
                     {
-                        logger.warn("Time ran backwards! Did the system time change?");
+                        LOGGER.warn("Time ran backwards! Did the system time change?");
                         timeChange = 0L;
                     }
                     timeSinceLastTick += timeChange;
@@ -515,17 +573,16 @@ public class MinecraftServer
                     {
                         Thread.sleep(10L);
                     }
-                    catch (InterruptedException interruptedexception)
+                    catch (InterruptedException e)
                     {
-                        interruptedexception.printStackTrace();
+                        LOGGER.error("",e);
                     }
                 }
             }
         }
         catch (Throwable throwable1)
         {
-            throwable1.printStackTrace();
-            logger.error("Unexpected exception", throwable1);
+            LOGGER.error("Unexpected exception", throwable1);
             while (serverRunning)
             {
                 commandLineParser();
@@ -533,9 +590,9 @@ public class MinecraftServer
                 {
                     Thread.sleep(10L);
                 }
-                catch (InterruptedException interruptedexception1)
+                catch (InterruptedException e)
                 {
-                    interruptedexception1.printStackTrace();
+                    LOGGER.error("",e);
                 }
             }
         }
@@ -546,9 +603,9 @@ public class MinecraftServer
                 stopServer();
                 serverStopped = true;
             }
-            catch (Throwable throwable2)
+            catch (Throwable t)
             {
-                throwable2.printStackTrace();
+                LOGGER.error("Caught throwable in shutdown sequence!",t);
             }
             finally
             {
@@ -559,17 +616,12 @@ public class MinecraftServer
 
     private void doTick()
     {
-        ArrayList arraylist = new ArrayList();
-        for (Iterator iterator = field_6037_b.keySet().iterator(); iterator.hasNext(); )
-        {
-            String s = (String) iterator.next();
-            int i1 = ((Integer) field_6037_b.get(s)).intValue();
-            if (i1 > 0)
-            {
-                field_6037_b.put(s, Integer.valueOf(i1 - 1));
-            }
-            else
-            {
+        ArrayList<String> arraylist = new ArrayList<>();
+        for (String s : field_6037_b.keySet()) {
+            int i1 = field_6037_b.get(s);
+            if (i1 > 0) {
+                field_6037_b.put(s, i1 - 1);
+            } else {
                 arraylist.add(s);
             }
         }
@@ -609,9 +661,9 @@ public class MinecraftServer
             entityTracker[k].tick();
         }
 
-        for (int l = 0; l < field_9010_p.size(); l++)
+        for (int l = 0; l < playerListBoxes.size(); l++)
         {
-            ((IUpdatePlayerListBox) field_9010_p.get(l)).update();
+            playerListBoxes.get(l).update();
         }
 
         try
@@ -620,7 +672,7 @@ public class MinecraftServer
         }
         catch (Exception exception)
         {
-            logger.warn( "Unexpected exception while parsing console command", exception);
+            LOGGER.warn( "Unexpected exception while parsing console command", exception);
         }
     }
 
@@ -641,51 +693,23 @@ public class MinecraftServer
 
     public void func_6022_a(IUpdatePlayerListBox iupdateplayerlistbox)
     {
-        field_9010_p.add(iupdateplayerlistbox);
+        playerListBoxes.add(iupdateplayerlistbox);
     }
 
     public static void main(String[] args)
     {
-        try
-        {
-            File log4jConf = new File("log4j.properties");
-            if (!log4jConf.exists())
-            {
-                log4jConf.createNewFile();
-                String contents = "log4j.appender.file=org.apache.log4j.rolling.RollingFileAppender\n" +
-                        "log4j.appender.file.layout=org.apache.log4j.PatternLayout\n" +
-                        "log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n\n" +
-                        "log4j.appender.file.rollingPolicy=org.apache.log4j.rolling.TimeBasedRollingPolicy\n" +
-                        "log4j.appender.file.rollingPolicy.FileNamePattern=./logs/%d{yyyy-MM-dd}.log\n" +
-                        "log4j.appender.file.rollingPolicy.ActiveFileName=./logs/latest.log\n" +
-                        "\n" +
-                        "log4j.appender.stdout=org.apache.log4j.ConsoleAppender\n" +
-                        "log4j.appender.stdout.Target=System.out\n" +
-                        "log4j.appender.stdout.layout=org.apache.log4j.PatternLayout\n" +
-                        "log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n\n" +
-                        "\n" +
-                        "log4j.logger.Minecraft=DEBUG, file, stdout\n";
-                OutputStream out = Files.newOutputStream(Paths.get("log4j.properties"));
-                out.write(contents.getBytes());
-            }
-        }
-        catch (IOException e)
-        {
-            throw new RuntimeException(e);
-        }
-        PropertyConfigurator.configure("log4j.properties");
         try
         {
             MinecraftServer minecraftserver = new MinecraftServer();
-            if (!java.awt.GraphicsEnvironment.isHeadless() && (args.length <= 0 || !args[0].equals("nogui")))
+            if (!java.awt.GraphicsEnvironment.isHeadless() && (args.length == 0 || !args[0].equals("nogui")))
             {
                 ServerGui.initGui(minecraftserver);
             }
-            (new ThreadServerApplication("Server thread", minecraftserver)).start();
+            new Thread(minecraftserver, "Server thread").start();
         }
         catch (Exception exception)
         {
-            logger.error("Failed to start the minecraft server", exception);
+            LOGGER.error("Failed to start the minecraft server", exception);
         }
     }
 
@@ -704,6 +728,7 @@ public class MinecraftServer
         return VERSION;
     }
 
+
     @Override
     public IChunkProvider createChunkProvider(World world, IChunkLoader chunkLoader)
     {
@@ -711,14 +736,8 @@ public class MinecraftServer
     }
 
     @Override
-	public void log(String s)
-    {
-        logger.info(s);
-    }
-
-    public void logWarning(String s)
-    {
-        logger.warn(s);
+    public void logInfo(String s) {
+        LOGGER.info(s);
     }
 
     @Override
@@ -757,44 +776,4 @@ public class MinecraftServer
         return skinVariantList;
     }
 
-    public static Logger logger = Logger.getLogger("Minecraft");
-    public static final String VERSION = Global.VERSION;
-    private static MinecraftServer instance;
-    public static HashMap field_6037_b = new HashMap();
-    public NetworkListenThread networkServer;
-    public PropertyManager propertyManager;
-    public WorldServer[] dimensionWorlds;
-    public PlayerList playerList;
-    private ConsoleCommandHandler commandHandler;
-    private boolean serverRunning;
-    public boolean serverStopped;
-    int deathTime;
-    public String currentTask;
-    public int percentDone;
-    private final List field_9010_p;
-    private final List<ServerCommandEntry> commands;
-    public EntityTracker[] entityTracker;
-    public boolean onlineMode;
-    public boolean pvpOn;
-    public boolean allowFlight;
-    public int spawnProtectionRange;
-    public WorldType defaultWorldType;
-    public int difficulty;
-    public final ServerCommandHandler serverCommandHandler = new ServerCommandHandler(this);
-    public String joinMessage = null;
-    public int summonLimit;
-    public String language;
-    public int sleepPercentage = 100;
-    public int maxPlayers = 20;
-    public Gamemode defaultGamemode;
-    public static String statsToken;
-    public static boolean statsStatus;
-    public boolean disablePhotoMode = false;
-    public String motd = "";
-    private final SkinVariantList skinVariantList = new ServerSkinVariantList();
-    public int autoSaveInterval = 5;
-    public int chunksSavedPerAutosave = 24;
-    public boolean forceSaveAllChunksOnAutosave = false;
-    public SpawnerMobs.SpawnerConfig spawnerConfig = new SpawnerMobs.SpawnerConfig();
-
 }
diff --git a/src/main/java/net/minecraft/server/entity/player/ServerPlayer.java b/src/main/java/net/minecraft/server/entity/player/ServerPlayer.java
index 95445e365..4cf409877 100644
--- a/src/main/java/net/minecraft/server/entity/player/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/entity/player/ServerPlayer.java
@@ -42,9 +42,10 @@ import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
+import java.util.UUID;
 
 public class ServerPlayer extends Player implements ContainerListener {
-    public ServerPlayer(MinecraftServer minecraftserver, World world, String s, ServerPlayerController iteminworldmanager)
+    public ServerPlayer(MinecraftServer minecraftserver, World world, String username, UUID uuid, ServerPlayerController serverPlayerController)
     {
         super(world);
         loadedChunks = new LinkedList();
@@ -53,8 +54,8 @@ public class ServerPlayer extends Player implements ContainerListener {
         lastScore = 0xfa0a1f01;
         ticksOfInvuln = 60;
         currentWindowId = 0;
-        iteminworldmanager.player = this;
-        playerController = iteminworldmanager;
+        serverPlayerController.player = this;
+        playerController = serverPlayerController;
         ChunkCoordinates chunkcoordinates = world.getSpawnPoint();
         int i = chunkcoordinates.x;
         int j = chunkcoordinates.z;
@@ -68,7 +69,8 @@ public class ServerPlayer extends Player implements ContainerListener {
         moveTo((double) i + 0.5D, k, (double) j + 0.5D, 0.0F, 0.0F);
         mcServer = minecraftserver;
         footSize = 0.0F;
-        username = s;
+        this.username = username;
+        this.uuid = uuid;
         heightOffset = 0.0F;
         gamemode = minecraftserver.defaultGamemode;
     }
@@ -127,12 +129,12 @@ public class ServerPlayer extends Player implements ContainerListener {
 	public void awardKillScore(Entity entity, int i)
     {
         super.awardKillScore(entity, i);
-        mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(username, nickname, score, chatColor, true, isOperator()));
+        mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(username, nickname, uuid, score, chatColor, true, isOperator()));
     }
 
     public boolean isOperator()
     {
-        return mcServer.playerList.isOp(username);
+        return mcServer.playerList.isOp(uuid);
     }
 
     @Override
@@ -158,7 +160,7 @@ public class ServerPlayer extends Player implements ContainerListener {
     }
 
     @Override
-	public void func_6420_o()
+	public void animate4()
     {
     }
 
@@ -353,7 +355,7 @@ public class ServerPlayer extends Player implements ContainerListener {
         }
         if (score != lastScore)
         {
-            playerNetServerHandler.sendPacket(new UpdatePlayerProfilePacket(username, nickname, score, chatColor, true, isOperator()));
+            playerNetServerHandler.sendPacket(new UpdatePlayerProfilePacket(username, nickname, uuid, score, chatColor, true, isOperator()));
             lastScore = score;
         }
     }
@@ -502,76 +504,76 @@ public class ServerPlayer extends Player implements ContainerListener {
     }
 
     @Override
-	public void displayGUIWorkbench(int i, int j, int k)
+	public void displayWorkbenchScreen(int x, int y, int z)
     {
         getNextWindowId();
         playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 1, "Crafting", 9));
-        craftingInventory = new CraftingMenu(inventory, world, i, j, k);
+        craftingInventory = new CraftingMenu(inventory, world, x, y, z);
         craftingInventory.containerId = currentWindowId;
         craftingInventory.addSlotListener(this);
     }
 
     @Override
-    public void displayGUIPaintingPicker()
+    public void displayPaintingPickerScreen()
     {
         playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 7, "Painting", 0));
     }
 
     @Override
-	public void displayGUIChest(Container iinventory)
+	public void displayContainerScreen(Container container)
     {
         getNextWindowId();
-        ServerPacketHandler.logger.info((new StringBuilder()).append(username).append(" interacted with chest at (").append(x).append(", ").append(y).append(", ").append(z).append(")").toString());
-        playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 0, iinventory.getName(), iinventory.getContainerSize()));
-        craftingInventory = new ContainerMenu(inventory, iinventory);
+        ServerPacketHandler.LOGGER.info((new StringBuilder()).append(username).append(" interacted with chest at (").append(x).append(", ").append(y).append(", ").append(z).append(")").toString());
+        playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 0, container.getName(), container.getContainerSize()));
+        craftingInventory = new ContainerMenu(inventory, container);
         craftingInventory.containerId = currentWindowId;
         craftingInventory.addSlotListener(this);
     }
 
     @Override
-	public void displayGUIFurnace(FurnaceBlockEntity tileentityfurnace)
+	public void displayFurnaceScreen(FurnaceBlockEntity blockEntity)
     {
         getNextWindowId();
-        if (tileentityfurnace instanceof BlastFurnaceBlockEntity)
+        if (blockEntity instanceof BlastFurnaceBlockEntity)
         {
-            playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 4, tileentityfurnace.getName(), tileentityfurnace.getContainerSize()));
+            playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 4, blockEntity.getName(), blockEntity.getContainerSize()));
         }
         else
         {
-            playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 2, tileentityfurnace.getName(), tileentityfurnace.getContainerSize()));
+            playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 2, blockEntity.getName(), blockEntity.getContainerSize()));
         }
 
-        craftingInventory = new FurnaceMenu(inventory, tileentityfurnace);
+        craftingInventory = new FurnaceMenu(inventory, blockEntity);
         craftingInventory.containerId = currentWindowId;
         craftingInventory.addSlotListener(this);
     }
 
     @Override
-	public void displayGUIDispenser(DispenserBlockEntity tileentitydispenser)
+	public void displayDispenserScreen(DispenserBlockEntity blockEntity)
     {
         getNextWindowId();
-        playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 3, tileentitydispenser.getName(), tileentitydispenser.getContainerSize()));
-        craftingInventory = new TrapMenu(inventory, tileentitydispenser);
+        playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 3, blockEntity.getName(), blockEntity.getContainerSize()));
+        craftingInventory = new TrapMenu(inventory, blockEntity);
         craftingInventory.containerId = currentWindowId;
         craftingInventory.addSlotListener(this);
     }
 
     @Override
-	public void displayGUITrommel(TrommelBlockEntity tileentitytrommel)
+	public void displayTrommelScreen(TrommelBlockEntity blockEntity)
     {
         getNextWindowId();
-        playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 5, tileentitytrommel.getName(), tileentitytrommel.getContainerSize()));
-        craftingInventory = new TrommelMenu(inventory, tileentitytrommel);
+        playerNetServerHandler.sendPacket(new ContainerOpenPacket(currentWindowId, 5, blockEntity.getName(), blockEntity.getContainerSize()));
+        craftingInventory = new TrommelMenu(inventory, blockEntity);
         craftingInventory.containerId = currentWindowId;
         craftingInventory.addSlotListener(this);
     }
 
     @Override
-    public void displayGUIEditFlag(FlagBlockEntity tileEntityFlag)
+    public void displayFlagEditorScreen(FlagBlockEntity blockEntity)
     {
         getNextWindowId();
-        playerNetServerHandler.sendPacket(new FlagOpenPacket(currentWindowId, tileEntityFlag.x, tileEntityFlag.y, tileEntityFlag.z));
-        craftingInventory = new FlagMenu(inventory, tileEntityFlag);
+        playerNetServerHandler.sendPacket(new FlagOpenPacket(currentWindowId, blockEntity.x, blockEntity.y, blockEntity.z));
+        craftingInventory = new FlagMenu(inventory, blockEntity);
         craftingInventory.containerId = currentWindowId;
         craftingInventory.addSlotListener(this);
     }
diff --git a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java
index e3d78a8dc..58cfa30c0 100644
--- a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java
+++ b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java
@@ -3,6 +3,8 @@ package net.minecraft.server.gui;
 import net.minecraft.core.net.NetworkManager;
 
 import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import javax.swing.JComponent;
 import javax.swing.Timer;
 
@@ -11,6 +13,10 @@ import javax.swing.Timer;
 
 public class GuiStatsComponent extends JComponent
 {
+    private final int[] memoryUse;
+    private int updateCounter;
+    private final String[] displayStrings;
+
 
     public GuiStatsComponent()
     {
@@ -20,7 +26,7 @@ public class GuiStatsComponent extends JComponent
         setPreferredSize(new java.awt.Dimension(256, 196));
         setMinimumSize(new java.awt.Dimension(256, 196));
         setMaximumSize(new java.awt.Dimension(256, 196));
-        (new Timer(500, new GuiStatsListener(this))).start();
+        (new Timer(500, e -> GuiStatsComponent.update(this))).start();
         setBackground(Color.BLACK);
     }
 
@@ -28,8 +34,8 @@ public class GuiStatsComponent extends JComponent
     {
         long l = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
         System.gc();
-        displayStrings[0] = (new StringBuilder()).append("Memory use: ").append(l / 1024L / 1024L).append(" mb (").append((Runtime.getRuntime().freeMemory() * 100L) / Runtime.getRuntime().maxMemory()).append("% free)").toString();
-        displayStrings[1] = (new StringBuilder()).append("Threads: ").append(NetworkManager.readThreads).append(" + ").append(NetworkManager.writeThreads).toString();
+        displayStrings[0] = "Memory use: " + l / 1024L / 1024L + " mb (" + (Runtime.getRuntime().freeMemory() * 100L) / Runtime.getRuntime().maxMemory() + "% free)";
+        displayStrings[1] = "Threads: " + NetworkManager.readThreads + " + " + NetworkManager.writeThreads;
         memoryUse[updateCounter++ & 0xff] = (int)((l * 100L) / Runtime.getRuntime().maxMemory());
         repaint();
     }
@@ -62,8 +68,4 @@ public class GuiStatsComponent extends JComponent
     {
         guistatscomponent.updateStats();
     }
-
-    private int memoryUse[];
-    private int updateCounter;
-    private String displayStrings[];
 }
diff --git a/src/main/java/net/minecraft/server/gui/GuiStatsListener.java b/src/main/java/net/minecraft/server/gui/GuiStatsListener.java
deleted file mode 100644
index 1ccf53c54..000000000
--- a/src/main/java/net/minecraft/server/gui/GuiStatsListener.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package net.minecraft.server.gui;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-// Referenced classes of package net.minecraft.src:
-//            GuiStatsComponent
-
-class GuiStatsListener
-    implements ActionListener
-{
-
-    GuiStatsListener(GuiStatsComponent guistatscomponent)
-    {
-//        super();
-        statsComponent = guistatscomponent;
-    }
-
-    @Override
-	public void actionPerformed(ActionEvent actionevent)
-    {
-        GuiStatsComponent.update(statsComponent);
-    }
-
-    final GuiStatsComponent statsComponent; /* synthetic field */
-}
diff --git a/src/main/java/net/minecraft/server/gui/ServerGui.java b/src/main/java/net/minecraft/server/gui/ServerGui.java
index c785b0ea0..bc4a987eb 100644
--- a/src/main/java/net/minecraft/server/gui/ServerGui.java
+++ b/src/main/java/net/minecraft/server/gui/ServerGui.java
@@ -1,48 +1,77 @@
 package net.minecraft.server.gui;
 
-import java.awt.BorderLayout;
-import java.awt.Dimension;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
 
 import javax.swing.*;
 import javax.swing.border.EtchedBorder;
 import javax.swing.border.TitledBorder;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
 
+import com.mojang.logging.LogQueues;
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.net.ICommandListener;
 import net.minecraft.server.player.PlayerListBox;
-import net.minecraft.core.util.helper.JTextAreaWriter;
 import net.minecraft.server.MinecraftServer;
-import org.apache.log4j.Layout;
-import org.apache.log4j.Logger;
-import org.apache.log4j.WriterAppender;
-
-
-// Referenced classes of package net.minecraft.src:
-//            ICommandListener, ServerWindowAdapter, GuiStatsComponent, PlayerListBox, 
-//            GuiLogOutputHandler, ServerGuiCommandListener, ServerGuiFocusAdapter
+import org.slf4j.Logger;
 
 public class ServerGui extends JComponent
     implements ICommandListener
 {
 
-    public static void initGui(MinecraftServer minecraftserver)
+    public static Logger LOGGER = LogUtils.getLogger();
+    public static Font MONOSPACED = new Font("Monospaced", Font.PLAIN, 12);
+
+    private final MinecraftServer mcServer;
+    private Thread logAppenderThread;
+
+
+    public static void initGui(MinecraftServer mcServer)
     {
         try
         {
             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
         }
-        catch(Exception exception) { }
-        ServerGui servergui = new ServerGui(minecraftserver);
+        catch(Exception exception) {
+            LOGGER.warn("Could not set UI Look and Feel!", exception);
+        }
+        ServerGui servergui = new ServerGui(mcServer);
         JFrame jframe = new JFrame("Minecraft server");
         jframe.add(servergui);
         jframe.pack();
         jframe.setLocationRelativeTo(null);
         jframe.setVisible(true);
-        jframe.addWindowListener(new ServerWindowAdapter(minecraftserver));
+        jframe.addWindowListener(new WindowAdapter() {
+            @Override
+            public void windowClosing(WindowEvent e) {
+                mcServer.initiateShutdown();
+                while(!mcServer.serverStopped)
+                {
+                    try
+                    {
+                        Thread.sleep(100L);
+                    }
+                    catch(InterruptedException ex)
+                    {
+                        LOGGER.error("Interrupt in window close!", ex);
+                    }
+                }
+                System.exit(0);
+            }
+        });
+        servergui.start();
     }
 
-    public ServerGui(MinecraftServer minecraftserver)
+    public ServerGui(MinecraftServer mcServer)
     {
-        mcServer = minecraftserver;
+        this.mcServer = mcServer;
         setPreferredSize(new Dimension(854, 480));
         setLayout(new BorderLayout());
         try
@@ -52,7 +81,7 @@ public class ServerGui extends JComponent
         }
         catch(Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Error constructing ServerGUI!", exception);
         }
     }
 
@@ -68,35 +97,72 @@ public class ServerGui extends JComponent
     private JComponent getPlayerListComponent()
     {
         PlayerListBox playerlistbox = new PlayerListBox(mcServer);
-        JScrollPane jscrollpane = new JScrollPane(playerlistbox, 22, 30);
+        JScrollPane jscrollpane = new JScrollPane(playerlistbox, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
         jscrollpane.setBorder(new TitledBorder(new EtchedBorder(), "Players"));
         return jscrollpane;
     }
 
-    private JComponent getLogComponent()
-    {
-        JPanel jpanel = new JPanel(new BorderLayout());
-        JTextArea jtextarea = new JTextArea();
-
-        Layout layout = logger.getAppender("stdout").getLayout();
-        WriterAppender appender = new WriterAppender(layout, new JTextAreaWriter(jtextarea));
-        logger.addAppender(appender);
-
-        JScrollPane jscrollpane = new JScrollPane(jtextarea, 22, 30);
-        jtextarea.setEditable(false);
-        JTextField jtextfield = new JTextField();
-        jtextfield.addActionListener(new ServerGuiCommandListener(this, jtextfield));
-        jtextarea.addFocusListener(new ServerGuiFocusAdapter(this));
-        jpanel.add(jscrollpane, "Center");
-        jpanel.add(jtextfield, "South");
-        jpanel.setBorder(new TitledBorder(new EtchedBorder(), "Log and chat"));
-        return jpanel;
+    private JComponent getLogComponent() {
+        final JPanel jPanel = new JPanel(new BorderLayout());
+        final JTextArea jTextArea = new JTextArea();
+
+        final JScrollPane jScrollPane = new JScrollPane(jTextArea, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+        jTextArea.setEditable(false);
+        jTextArea.setFont(MONOSPACED);
+        final JTextField jTextField = new JTextField();
+        jTextField.addActionListener(e -> {
+            String s = jTextField.getText().trim();
+            if(!s.isEmpty())
+            {
+                mcServer.addCommand(s, this);
+            }
+            jTextField.setText("");
+        });
+//        jTextArea.addFocusListener(new FocusAdapter() {});
+
+        jPanel.add(jScrollPane, "Center");
+        jPanel.add(jTextField, "South");
+        jPanel.setBorder(new TitledBorder(new EtchedBorder(), "Log and chat"));
+        this.logAppenderThread = new Thread(() -> {
+            do {
+                String logEvent = LogQueues.getNextLogEvent("ServerGuiConsole");
+                if (logEvent != null) {
+                    print(jTextArea, jScrollPane, logEvent);
+                } else {
+                    break;
+                }
+            } while (true);
+        });
+        logAppenderThread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
+
+        this.logAppenderThread.setDaemon(true);
+        return jPanel;
+    }
+
+    public void print(final JTextArea textArea, final JScrollPane scrollPane, final String message) {
+        if (!SwingUtilities.isEventDispatchThread()) {
+            SwingUtilities.invokeLater(() -> this.print(textArea, scrollPane, message));
+            return;
+        }
+        final Document document = textArea.getDocument();
+        final JScrollBar scrollBar = scrollPane.getVerticalScrollBar();
+        boolean scrollMax = false;
+        if (scrollPane.getViewport().getView() == textArea) {
+            scrollMax = (scrollBar.getValue() + scrollBar.getSize().getHeight() + MONOSPACED.getSize() * 4 > scrollBar.getMaximum());
+        }
+        try {
+            document.insertString(document.getLength(), message, null);
+        }
+        catch (final BadLocationException ignored) {}
+        if (scrollMax) {
+            scrollBar.setValue(Integer.MAX_VALUE);
+        }
     }
 
     @Override
-	public void log(String s)
+	public void logInfo(String s)
     {
-        logger.info(s);
+        LOGGER.info(s);
     }
 
     @Override
@@ -105,12 +171,26 @@ public class ServerGui extends JComponent
         return "CONSOLE";
     }
 
+    public void start() {
+        this.logAppenderThread.start();
+    }
+
     static MinecraftServer getMinecraftServer(ServerGui servergui)
     {
         return servergui.mcServer;
     }
 
-    public static Logger logger = Logger.getLogger("Minecraft");
-    private final MinecraftServer mcServer;
+    public static class DefaultUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler
+    {
+        private final Logger logger;
+
+        public DefaultUncaughtExceptionHandler(final Logger logger) {
+            this.logger = logger;
+        }
 
+        @Override
+        public void uncaughtException(final Thread thread, final Throwable t) {
+            this.logger.error("Caught previously unhandled exception :", t);
+        }
+    }
 }
diff --git a/src/main/java/net/minecraft/server/gui/ServerGuiCommandListener.java b/src/main/java/net/minecraft/server/gui/ServerGuiCommandListener.java
deleted file mode 100644
index 579cd61bb..000000000
--- a/src/main/java/net/minecraft/server/gui/ServerGuiCommandListener.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package net.minecraft.server.gui;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import javax.swing.JTextField;
-
-// Referenced classes of package net.minecraft.src:
-//            ServerGUI
-
-class ServerGuiCommandListener
-    implements ActionListener
-{
-
-    ServerGuiCommandListener(ServerGui servergui, JTextField jtextfield)
-    {
-//        super();
-        mcServerGui = servergui;
-        textField = jtextfield;
-    }
-
-    @Override
-	public void actionPerformed(ActionEvent actionevent)
-    {
-        String s = textField.getText().trim();
-        if(s.length() > 0)
-        {
-            ServerGui.getMinecraftServer(mcServerGui).addCommand(s, mcServerGui);
-        }
-        textField.setText("");
-    }
-
-    final JTextField textField; /* synthetic field */
-    final ServerGui mcServerGui; /* synthetic field */
-}
diff --git a/src/main/java/net/minecraft/server/gui/ServerGuiFocusAdapter.java b/src/main/java/net/minecraft/server/gui/ServerGuiFocusAdapter.java
deleted file mode 100644
index 7fe929d24..000000000
--- a/src/main/java/net/minecraft/server/gui/ServerGuiFocusAdapter.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package net.minecraft.server.gui;
-
-import java.awt.event.FocusAdapter;
-import java.awt.event.FocusEvent;
-
-// Referenced classes of package net.minecraft.src:
-//            ServerGUI
-
-class ServerGuiFocusAdapter extends FocusAdapter
-{
-
-    ServerGuiFocusAdapter(ServerGui servergui)
-    {
-//        super();
-        mcServerGui = servergui;
-    }
-
-    @Override
-	public void focusGained(FocusEvent focusevent)
-    {
-    }
-
-    final ServerGui mcServerGui; /* synthetic field */
-}
diff --git a/src/main/java/net/minecraft/server/gui/ServerWindowAdapter.java b/src/main/java/net/minecraft/server/gui/ServerWindowAdapter.java
deleted file mode 100644
index 467be9fb5..000000000
--- a/src/main/java/net/minecraft/server/gui/ServerWindowAdapter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package net.minecraft.server.gui;
-
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import net.minecraft.server.MinecraftServer;
-
-final class ServerWindowAdapter extends WindowAdapter
-{
-
-    ServerWindowAdapter(MinecraftServer minecraftserver)
-    {
-//        super();
-        mcServer = minecraftserver;
-    }
-
-    @Override
-	public void windowClosing(WindowEvent windowevent)
-    {
-        mcServer.initiateShutdown();
-        while(!mcServer.serverStopped) 
-        {
-            try
-            {
-                Thread.sleep(100L);
-            }
-            catch(InterruptedException interruptedexception)
-            {
-                interruptedexception.printStackTrace();
-            }
-        }
-        System.exit(0);
-    }
-
-    final MinecraftServer mcServer; /* synthetic field */
-}
diff --git a/src/main/java/net/minecraft/server/net/ConsoleCommandHandler.java b/src/main/java/net/minecraft/server/net/ConsoleCommandHandler.java
index 03e0281b9..580f2c0ec 100644
--- a/src/main/java/net/minecraft/server/net/ConsoleCommandHandler.java
+++ b/src/main/java/net/minecraft/server/net/ConsoleCommandHandler.java
@@ -26,7 +26,7 @@ public class ConsoleCommandHandler
     }
 
     public void handleCommand(ServerCommandEntry serverCommandEntry) {
-    	System.out.println("ServerCommand: "+ serverCommandEntry.command);
+    	minecraftServer.logInfo("ServerCommand: "+ serverCommandEntry.command);
 
     	String[] args = serverCommandEntry.command.split(" ");
     	String[] args1 = new String[args.length - 1];
diff --git a/src/main/java/net/minecraft/server/net/NetworkListenThread.java b/src/main/java/net/minecraft/server/net/NetworkListenThread.java
index f781fe02f..27157a2c9 100644
--- a/src/main/java/net/minecraft/server/net/NetworkListenThread.java
+++ b/src/main/java/net/minecraft/server/net/NetworkListenThread.java
@@ -7,10 +7,11 @@ import java.net.Socket;
 import java.util.ArrayList;
 
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.server.net.handler.LoginPacketHandler;
 import net.minecraft.server.net.handler.ServerPacketHandler;
 import net.minecraft.server.MinecraftServer;
-import org.apache.log4j.Logger;
+import org.slf4j.Logger;
 
 
 // Referenced classes of package net.minecraft.src:
@@ -18,8 +19,16 @@ import org.apache.log4j.Logger;
 
 public class NetworkListenThread
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private final ServerSocket serverSocket;
+    private final Thread networkAcceptThread;
+    public volatile boolean isListening;
+    private int connectionCounter;
+    private final ArrayList<LoginPacketHandler> pendingConnections;
+    private final ArrayList<ServerPacketHandler> playerList;
+    public MinecraftServer mcServer;
 
-    public NetworkListenThread(MinecraftServer minecraftserver, InetAddress addr, int i)
+    public NetworkListenThread(MinecraftServer minecraftserver, InetAddress address, int i)
         throws IOException
     {
         isListening = false;
@@ -27,7 +36,7 @@ public class NetworkListenThread
         pendingConnections = new ArrayList<>();
         playerList = new ArrayList<>();
         mcServer = minecraftserver;
-        serverSocket = new ServerSocket(i, 0, addr);
+        serverSocket = new ServerSocket(i, 0, address);
         serverSocket.setPerformancePreferences(0, 2, 1);
         isListening = true;
         networkAcceptThread = new Thread(() -> {
@@ -39,7 +48,7 @@ public class NetworkListenThread
                         addPendingConnection(loginHandler);
                     }
                 } catch (IOException ioexception) {
-                    ioexception.printStackTrace();
+                    LOGGER.error("Exception in network login thread!", ioexception);
                 }
             }
         });
@@ -75,7 +84,7 @@ public class NetworkListenThread
             catch(Exception exception)
             {
                 netloginhandler.kickUser("Internal server error");
-                logger.warn("Failed to handle packet: " + exception, exception);
+                LOGGER.warn("Failed to handle packet: {}", exception, exception);
             }
             if(netloginhandler.finishedProcessing)
             {
@@ -86,32 +95,22 @@ public class NetworkListenThread
 
         for(int j = 0; j < playerList.size(); j++)
         {
-            ServerPacketHandler netserverhandler = (ServerPacketHandler)playerList.get(j);
+            ServerPacketHandler serverPacketHandler = playerList.get(j);
             try
             {
-                netserverhandler.handlePackets();
+                serverPacketHandler.handlePackets();
             }
             catch(Exception exception1)
             {
-                logger.warn("Failed to handle packet: " + exception1, exception1);
-                netserverhandler.kickPlayer("Internal server error");
+                LOGGER.warn("Failed to handle packet: {}", exception1, exception1);
+                serverPacketHandler.kickPlayer("Internal server error");
             }
-            if(netserverhandler.connectionClosed)
+            if(serverPacketHandler.connectionClosed)
             {
                 playerList.remove(j--);
             }
-            netserverhandler.netManager.wakeThreads();
+            serverPacketHandler.netManager.wakeThreads();
         }
 
     }
-
-    public static Logger logger = Logger.getLogger("Minecraft");
-    private ServerSocket serverSocket;
-    private Thread networkAcceptThread;
-    public volatile boolean isListening;
-    private int connectionCounter;
-    private ArrayList<LoginPacketHandler> pendingConnections;
-    private final ArrayList<ServerPacketHandler> playerList;
-    public MinecraftServer mcServer;
-
 }
diff --git a/src/main/java/net/minecraft/server/net/PlayerList.java b/src/main/java/net/minecraft/server/net/PlayerList.java
index 67f0580cc..69c088d56 100644
--- a/src/main/java/net/minecraft/server/net/PlayerList.java
+++ b/src/main/java/net/minecraft/server/net/PlayerList.java
@@ -1,9 +1,11 @@
 package net.minecraft.server.net;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.achievement.Achievements;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.entity.player.Player;
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.core.util.helper.MathHelper;
 import net.minecraft.server.entity.player.ServerPlayer;
 import net.minecraft.server.net.handler.LoginPacketHandler;
@@ -17,23 +19,24 @@ import net.minecraft.server.world.WorldServer;
 import net.minecraft.core.world.chunk.ChunkCoordinates;
 import net.minecraft.core.world.save.PlayerIO;
 import net.minecraft.server.MinecraftServer;
-import org.apache.log4j.Logger;
+import org.slf4j.Logger;
 import org.jetbrains.annotations.Nullable;
 
 
 import java.io.*;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class PlayerList
 {
-    public static Logger logger = Logger.getLogger("Minecraft");
+    public static Logger logger = LogUtils.getLogger();
     public List<ServerPlayer> playerEntities;
     private final MinecraftServer server;
     private final PlayerManager[] playerManagers;
-    private final Set<String> bans;
+    private final Set<UUID> bans;
     private final Set<String> ipBans;
-    private final Set<String> ops;
-    private final Set<String> whitelist;
+    private final Set<UUID> ops;
+    private final Set<UUID> whitelist;
     private final File bansFile;
     private final File ipBansFile;
     private final File opsFile;
@@ -41,6 +44,8 @@ public class PlayerList
     private PlayerIO playerIo;
     private final boolean whitelistEnforced;
 
+    AtomicInteger awaitedLoadThreads = new AtomicInteger(0);
+
     public PlayerList(MinecraftServer server)
     {
         playerEntities = new ArrayList<>();
@@ -60,14 +65,41 @@ public class PlayerList
             playerManagers[dim] = new PlayerManager(server, dim, viewDistance);
         }
         whitelistEnforced = server.propertyManager.getBooleanProperty("white-list", false);
-        readBannedPlayers();
+        loadBannedPlayers();
         loadBannedList();
         loadOps();
         loadWhiteList();
-        writeBannedPlayers();
+        saveBannedPlayers();
         saveBannedList();
         saveOps();
         saveWhiteList();
+
+        // If there's still some threads converting usernames to UUIDs then wait for them all to finish before saving their results to file
+        if (awaitedLoadThreads.get() > 0) {
+            new Thread( () ->
+                {
+                    long startTime = System.currentTimeMillis();
+                    while (awaitedLoadThreads.get() > 0) {
+                        try {
+                            Thread.sleep(100);
+                        } catch (InterruptedException e) {
+                            e.printStackTrace();
+                            break;
+                        }
+                        if (System.currentTimeMillis() - startTime > 600_000) break;
+                    }
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                    saveBannedPlayers();
+                    saveBannedList();
+                    saveOps();
+                    saveWhiteList();
+                }
+            ).start();
+        }
     }
 
     public void setPlayerManager(WorldServer[] aworldserver)
@@ -132,14 +164,14 @@ public class PlayerList
         getPlayerManager(entityplayermp.dimension).removePlayer(entityplayermp);
     }
 
-    public ServerPlayer getPlayerForLogin(LoginPacketHandler handler, String username)
+    public ServerPlayer getPlayerForLogin(LoginPacketHandler handler, String username, UUID uuid)
     {
-        if (bans.contains(username.trim().toLowerCase()))
+        if (bans.contains(uuid))
         {
             handler.kickUser("You are banned from this server!");
             return null;
         }
-        if (!isAllowedToLogin(username))
+        if (!isAllowedToLogin(uuid))
         {
             handler.kickUser("You are not white-listed on this server!");
             return null;
@@ -157,16 +189,13 @@ public class PlayerList
             handler.kickUser("The server is full!");
             return null;
         }
-        for (int i = 0; i < playerEntities.size(); i++)
-        {
-            ServerPlayer player = playerEntities.get(i);
-            if (player.username.equalsIgnoreCase(username))
-            {
+        for (ServerPlayer player : playerEntities) {
+            if (player.username.equalsIgnoreCase(username) || player.uuid.equals(uuid)) {
                 player.playerNetServerHandler.kickPlayer("You are logged in from another location!");
             }
         }
 
-        return new ServerPlayer(server, server.getDimensionWorld(0), username, new ServerPlayerController(server.getDimensionWorld(0)));
+        return new ServerPlayer(server, server.getDimensionWorld(0), username, uuid, new ServerPlayerController(server.getDimensionWorld(0)));
     }
 
     public ServerPlayer recreatePlayerEntity(ServerPlayer previousPlayer, int i)
@@ -178,7 +207,7 @@ public class PlayerList
         server.getDimensionWorld(previousPlayer.dimension).removePlayer(previousPlayer);
         ChunkCoordinates chunkcoordinates = previousPlayer.getPlayerSpawnCoordinate();
         previousPlayer.dimension = i;
-        ServerPlayer newPlayer = new ServerPlayer(server, server.getDimensionWorld(previousPlayer.dimension), previousPlayer.username, new ServerPlayerController(server.getDimensionWorld(previousPlayer.dimension)));
+        ServerPlayer newPlayer = new ServerPlayer(server, server.getDimensionWorld(previousPlayer.dimension), previousPlayer.username, previousPlayer.uuid, new ServerPlayerController(server.getDimensionWorld(previousPlayer.dimension)));
         newPlayer.id = previousPlayer.id;
         newPlayer.chatColor = previousPlayer.chatColor;
         newPlayer.nickname = previousPlayer.nickname;
@@ -273,11 +302,9 @@ public class PlayerList
 
     public void onTick()
     {
-        for (int i = 0; i < playerManagers.length; i++)
-        {
-            playerManagers[i].tick();
+        for (PlayerManager playerManager : playerManagers) {
+            playerManager.tick();
         }
-
     }
 
     public void markBlockNeedsUpdate(int i, int j, int k, int l)
@@ -287,73 +314,73 @@ public class PlayerList
 
     public void sendPacketToAllPlayers(Packet packet)
     {
-        for (int i = 0; i < playerEntities.size(); i++)
-        {
-            ServerPlayer entityplayermp = playerEntities.get(i);
-            entityplayermp.playerNetServerHandler.sendPacket(packet);
+        for (ServerPlayer player : playerEntities) {
+            player.playerNetServerHandler.sendPacket(packet);
         }
 
     }
 
     public void sendEncryptedChatToAllPlayers(String message)
     {
-        for (int i = 0; i < playerEntities.size(); i++)
-        {
-            ServerPlayer entityplayermp = playerEntities.get(i);
-            entityplayermp.playerNetServerHandler.sendPacket(new ChatPacket(message, 0, AES.keyChain.get(entityplayermp.username)));
+        for (ServerPlayer player : playerEntities) {
+            player.playerNetServerHandler.sendPacket(new ChatPacket(message, 0, AES.keyChain.get(player.username)));
         }
 
     }
 
     public void sendPacketToAllPlayersInDimension(Packet packet, int i)
     {
-        for (int j = 0; j < playerEntities.size(); j++)
-        {
-            ServerPlayer entityplayermp = playerEntities.get(j);
-            if (entityplayermp.dimension == i)
-            {
-                entityplayermp.playerNetServerHandler.sendPacket(packet);
+        for (ServerPlayer player : playerEntities) {
+            if (player.dimension == i) {
+                player.playerNetServerHandler.sendPacket(packet);
             }
         }
-
     }
 
     public String getPlayerList()
     {
-        String s = "";
+        StringBuilder s = new StringBuilder();
         for (int i = 0; i < playerEntities.size(); i++)
         {
             if (i > 0)
             {
-                s = s + ", ";
+                s.append(", ");
             }
-            s = s + playerEntities.get(i).getDisplayName();
+            s.append(playerEntities.get(i).getDisplayName());
         }
 
-        return s;
+        return s.toString();
     }
 
-    public void banPlayer(String s)
+    public synchronized void banPlayer(UUID uuid)
     {
-        bans.add(s.toLowerCase());
-        writeBannedPlayers();
+        bans.add(uuid);
+        saveBannedPlayers();
     }
 
-    public void pardonPlayer(String s)
+    public synchronized void pardonPlayer(UUID uuid)
     {
-        bans.remove(s.toLowerCase());
-        writeBannedPlayers();
+        bans.remove(uuid);
+        saveBannedPlayers();
     }
 
-    private void readBannedPlayers()
+    private synchronized void loadBannedPlayers()
     {
         try
         {
             bans.clear();
             BufferedReader bufferedreader = new BufferedReader(new FileReader(bansFile));
-            for (String s = ""; (s = bufferedreader.readLine()) != null; )
+            for (String s; (s = bufferedreader.readLine()) != null; )
             {
-                bans.add(s.trim().toLowerCase());
+                if (!UUIDHelper.isUUID(s)) {
+                    awaitedLoadThreads.addAndGet(1);
+                    UUIDHelper.runConversionAction(s, uuid -> {
+                        bans.add(uuid);
+                        awaitedLoadThreads.addAndGet(-1);
+                    }, (username) -> awaitedLoadThreads.addAndGet(-1));
+                } else {
+                    bans.add(UUID.fromString(s));
+                }
             }
 
             bufferedreader.close();
@@ -364,15 +391,15 @@ public class PlayerList
         }
     }
 
-    private void writeBannedPlayers()
+    private synchronized void saveBannedPlayers()
     {
         try
         {
             PrintWriter printwriter = new PrintWriter(new FileWriter(bansFile, false));
-            String s;
-            for (Iterator iterator = bans.iterator(); iterator.hasNext(); printwriter.println(s))
+            UUID uuid;
+            for (Iterator<UUID> iterator = bans.iterator(); iterator.hasNext(); printwriter.println(uuid))
             {
-                s = (String) iterator.next();
+                uuid = iterator.next();
             }
 
             printwriter.close();
@@ -383,27 +410,27 @@ public class PlayerList
         }
     }
 
-    public void banIP(String s)
+    public synchronized void banIP(String s)
     {
         ipBans.add(s.toLowerCase());
         saveBannedList();
     }
 
-    public void pardonIP(String s)
+    public synchronized void pardonIP(String s)
     {
         ipBans.remove(s.toLowerCase());
         saveBannedList();
     }
 
-    private void loadBannedList()
+    private synchronized void loadBannedList()
     {
         try
         {
             ipBans.clear();
             BufferedReader bufferedreader = new BufferedReader(new FileReader(ipBansFile));
-            for (String s = ""; (s = bufferedreader.readLine()) != null; )
+            for (String ip; (ip = bufferedreader.readLine()) != null; )
             {
-                ipBans.add(s.trim().toLowerCase());
+                ipBans.add(ip.trim().toLowerCase());
             }
 
             bufferedreader.close();
@@ -414,15 +441,15 @@ public class PlayerList
         }
     }
 
-    private void saveBannedList()
+    private synchronized void saveBannedList()
     {
         try
         {
             PrintWriter printwriter = new PrintWriter(new FileWriter(ipBansFile, false));
-            String s;
-            for (Iterator iterator = ipBans.iterator(); iterator.hasNext(); printwriter.println(s))
+            String ip;
+            for (Iterator<String> iterator = ipBans.iterator(); iterator.hasNext(); printwriter.println(ip))
             {
-                s = (String) iterator.next();
+                ip = iterator.next();
             }
 
             printwriter.close();
@@ -433,27 +460,35 @@ public class PlayerList
         }
     }
 
-    public void opPlayer(String s)
+    public synchronized void opPlayer(UUID uuid)
     {
-        ops.add(s.toLowerCase());
+        ops.add(uuid);
         saveOps();
     }
 
-    public void deopPlayer(String s)
+    public synchronized void deopPlayer(UUID uuid)
     {
-        ops.remove(s.toLowerCase());
+        ops.remove(uuid);
         saveOps();
     }
 
-    private void loadOps()
+    private synchronized void loadOps()
     {
         try
         {
             ops.clear();
             BufferedReader bufferedreader = new BufferedReader(new FileReader(opsFile));
-            for (String s = ""; (s = bufferedreader.readLine()) != null; )
+            for (String entry; (entry = bufferedreader.readLine()) != null; )
             {
-                ops.add(s.trim().toLowerCase());
+                if (!UUIDHelper.isUUID(entry)) {
+                    awaitedLoadThreads.addAndGet(1);
+                    UUIDHelper.runConversionAction(entry, uuid -> {
+                        ops.add(uuid);
+                        awaitedLoadThreads.addAndGet(-1);
+                    }, (username) -> awaitedLoadThreads.addAndGet(-1));
+                } else {
+                    ops.add(UUID.fromString(entry));
+                }
             }
 
             bufferedreader.close();
@@ -464,15 +499,15 @@ public class PlayerList
         }
     }
 
-    private void saveOps()
+    private synchronized void saveOps()
     {
         try
         {
             PrintWriter printwriter = new PrintWriter(new FileWriter(opsFile, false));
-            String s;
-            for (Iterator iterator = ops.iterator(); iterator.hasNext(); printwriter.println(s))
+            UUID uuid;
+            for (Iterator<UUID> iterator = ops.iterator(); iterator.hasNext(); printwriter.println(uuid.toString()))
             {
-                s = (String) iterator.next();
+                uuid = iterator.next();
             }
 
             printwriter.close();
@@ -483,15 +518,23 @@ public class PlayerList
         }
     }
 
-    private void loadWhiteList()
+    private synchronized void loadWhiteList()
     {
         try
         {
             whitelist.clear();
             BufferedReader bufferedreader = new BufferedReader(new FileReader(whitelistFile));
-            for (String s = ""; (s = bufferedreader.readLine()) != null; )
+            for (String entry; (entry = bufferedreader.readLine()) != null; )
             {
-                whitelist.add(s.trim().toLowerCase());
+                if (!UUIDHelper.isUUID(entry)) {
+                    awaitedLoadThreads.addAndGet(1);
+                    UUIDHelper.runConversionAction(entry, uuid -> {
+                        whitelist.add(uuid);
+                        awaitedLoadThreads.addAndGet(-1);
+                    }, (username) -> awaitedLoadThreads.addAndGet(-1));
+                } else {
+                    whitelist.add(UUID.fromString(entry));
+                }
             }
 
             bufferedreader.close();
@@ -502,15 +545,15 @@ public class PlayerList
         }
     }
 
-    private void saveWhiteList()
+    private synchronized void saveWhiteList()
     {
         try
         {
             PrintWriter printwriter = new PrintWriter(new FileWriter(whitelistFile, false));
-            String s;
-            for (Iterator iterator = whitelist.iterator(); iterator.hasNext(); printwriter.println(s))
+            UUID uuid;
+            for (Iterator<UUID> iterator = whitelist.iterator(); iterator.hasNext(); printwriter.println(uuid.toString()))
             {
-                s = (String) iterator.next();
+                uuid = iterator.next();
             }
 
             printwriter.close();
@@ -521,25 +564,21 @@ public class PlayerList
         }
     }
 
-    public boolean isAllowedToLogin(String s)
+    public boolean isAllowedToLogin(UUID uuid)
     {
-        s = s.trim().toLowerCase();
-        return !whitelistEnforced || ops.contains(s) || whitelist.contains(s);
+        return !whitelistEnforced || ops.contains(uuid) || whitelist.contains(uuid);
     }
 
-    public boolean isOp(String s)
+    public boolean isOp(UUID uuid)
     {
-        return ops.contains(s.trim().toLowerCase());
+        return ops.contains(uuid);
     }
     @Nullable
     public ServerPlayer getPlayerEntity(String s)
     {
-        for (int i = 0; i < playerEntities.size(); i++)
-        {
-            ServerPlayer entityplayermp = playerEntities.get(i);
-            if (entityplayermp.username.equalsIgnoreCase(s))
-            {
-                return entityplayermp;
+        for (ServerPlayer player : playerEntities) {
+            if (player.username.equalsIgnoreCase(s)) {
+                return player;
             }
         }
 
@@ -548,10 +587,10 @@ public class PlayerList
 
     public void sendChatMessageToPlayer(String s, String s1)
     {
-        ServerPlayer entityplayermp = getPlayerEntity(s);
-        if (entityplayermp != null)
+        ServerPlayer player = getPlayerEntity(s);
+        if (player != null)
         {
-            entityplayermp.playerNetServerHandler.sendPacket(new ChatPacket(s1));
+            player.playerNetServerHandler.sendPacket(new ChatPacket(s1));
         }
     }
 
@@ -580,12 +619,9 @@ public class PlayerList
     public void sendChatMessageToAllOps(String s)
     {
         ChatPacket chatPacket = new ChatPacket(s);
-        for (int i = 0; i < playerEntities.size(); i++)
-        {
-            ServerPlayer entityplayermp = playerEntities.get(i);
-            if (isOp(entityplayermp.username))
-            {
-                entityplayermp.playerNetServerHandler.sendPacket(chatPacket);
+        for (ServerPlayer player : playerEntities) {
+            if (isOp(player.uuid)) {
+                player.playerNetServerHandler.sendPacket(chatPacket);
             }
         }
 
@@ -593,10 +629,10 @@ public class PlayerList
 
     public boolean sendPacketToPlayer(String s, Packet packet)
     {
-        ServerPlayer entityplayermp = getPlayerEntity(s);
-        if (entityplayermp != null)
+        ServerPlayer player = getPlayerEntity(s);
+        if (player != null)
         {
-            entityplayermp.playerNetServerHandler.sendPacket(packet);
+            player.playerNetServerHandler.sendPacket(packet);
             return true;
         }
         else
@@ -607,9 +643,8 @@ public class PlayerList
 
     public void savePlayerStates()
     {
-        for (int i = 0; i < playerEntities.size(); i++)
-        {
-            playerIo.save(playerEntities.get(i));
+        for (ServerPlayer playerEntity : playerEntities) {
+            playerIo.save(playerEntity);
         }
 
     }
@@ -618,19 +653,19 @@ public class PlayerList
     {
     }
 
-    public void addToWhiteList(String s)
+    public synchronized void addToWhiteList(UUID uuid)
     {
-        whitelist.add(s);
+        whitelist.add(uuid);
         saveWhiteList();
     }
 
-    public void removeFromWhiteList(String s)
+    public synchronized void removeFromWhiteList(UUID uuid)
     {
-        whitelist.remove(s);
+        whitelist.remove(uuid);
         saveWhiteList();
     }
 
-    public Set<String> getWhitelist()
+    public Set<UUID> getWhitelist()
     {
         return whitelist;
     }
diff --git a/src/main/java/net/minecraft/server/net/handler/LoginPacketHandler.java b/src/main/java/net/minecraft/server/net/handler/LoginPacketHandler.java
index 38bb40bb9..8f350b750 100644
--- a/src/main/java/net/minecraft/server/net/handler/LoginPacketHandler.java
+++ b/src/main/java/net/minecraft/server/net/handler/LoginPacketHandler.java
@@ -1,38 +1,44 @@
 package net.minecraft.server.net.handler;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.Global;
 import net.minecraft.core.data.registry.Registries;
 import net.minecraft.core.data.registry.recipe.RecipeEntryBase;
 import net.minecraft.core.net.handler.PacketHandler;
+import net.minecraft.core.util.helper.UUIDHelper;
 import net.minecraft.server.entity.player.ServerPlayer;
 import net.minecraft.core.net.NetworkManager;
 import net.minecraft.core.net.command.TextFormatting;
 import net.minecraft.core.net.packet.*;
-import net.minecraft.server.net.thread.ThreadLoginVerifier;
 import net.minecraft.core.util.helper.AES;
 import net.minecraft.core.util.helper.RSA;
 import net.minecraft.core.util.helper.RestHandler;
 import net.minecraft.server.world.WorldServer;
 import net.minecraft.core.world.chunk.ChunkCoordinates;
 import net.minecraft.server.MinecraftServer;
-import org.apache.log4j.Logger;
-
+import org.slf4j.Logger;
 
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.net.Socket;
+import java.net.URL;
+import java.net.URLEncoder;
 import java.security.Key;
 import java.util.Random;
-
-
-// Referenced classes of package net.minecraft.src:
-//            PacketHandler, NetworkManager, DisconnectPacket, PreLoginPacket,
-//            LoginPacket, ThreadLoginVerifier, ServerConfigurationManager, ServerPlayer,
-//            WorldServer, ServerPacketHandler, WorldProvider, SetSpawnPositionPacket,
-//            ChunkCoordinates, ChatPacket, NetworkListenThread, SetTimePacket,
-//            Packet
+import java.util.UUID;
 
 public class LoginPacketHandler extends PacketHandler
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private static final Random rand = new Random();
+    public NetworkManager netManager;
+    public boolean finishedProcessing;
+    private final MinecraftServer mcServer;
+    private int loginTimer;
+    private String username;
+    private LoginPacket loginPacket;
+    private String serverId;
     public static String kickMessage = null;
 
     public LoginPacketHandler(MinecraftServer minecraftserver, Socket socket, String s)
@@ -74,14 +80,14 @@ public class LoginPacketHandler extends PacketHandler
     {
         try
         {
-            if (!silent) logger.info("Disconnecting " + getUserAndIPString() + ": " + s);
+            if (!silent) LOGGER.info("Disconnecting {}: {}", getUserAndIPString(), s);
             netManager.addToSendQueue(new DisconnectPacket(s));
             netManager.serverShutdown();
             finishedProcessing = true;
         }
         catch (Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Error while kicking user '{}'!", s, exception);
         }
     }
 
@@ -121,69 +127,104 @@ public class LoginPacketHandler extends PacketHandler
         }
         else
         {
-            (new ThreadLoginVerifier(this, loginPacket)).start();
+            new Thread(
+                () -> {
+                    try
+                    {
+                        String s = LoginPacketHandler.getServerId(this);
+                        URL url = new URL("http://session.minecraft.net/game/checkserver.jsp?user=" + URLEncoder.encode(loginPacket.username, "UTF-8") + "&serverId=" + URLEncoder.encode(s, "UTF-8"));
+                        BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(url.openStream()));
+                        String s1 = bufferedreader.readLine();
+                        bufferedreader.close();
+                        if(s1.equals("YES"))
+                        {
+                            LoginPacketHandler.setLoginPacket(this, loginPacket);
+                        } else
+                        {
+                            this.kickUser("Failed to verify username!");
+                        }
+                    }
+                    catch(Exception exception)
+                    {
+                        LOGGER.error("Exception while trying to verify user '{}', kicking!", this.getUserAndIPString(), exception);
+                        this.kickUser("Failed to verify username! [internal error " + exception + "]");
+                    }
+                }
+            ).start();
         }
     }
 
     public void doLogin(LoginPacket loginPacket)
     {
-        ServerPlayer entityplayermp = mcServer.playerList.getPlayerForLogin(this, loginPacket.username);
-        if (entityplayermp != null)
+        if (mcServer.onlineMode) {
+            UUID mojangUUID = UUIDHelper.getUUIDFromName(loginPacket.username);
+            if (mojangUUID == null) {
+                kickUser("Cannot authenticate UUID!");
+                return;
+            }
+            if (!mojangUUID.equals(loginPacket.uuid)) {
+                kickUser("UUID mismatch!");
+                return;
+            }
+        }
+        ServerPlayer player = mcServer.playerList.getPlayerForLogin(this, loginPacket.username, loginPacket.uuid);
+        if (player != null)
         {
-            mcServer.playerList.load(entityplayermp);
-            entityplayermp.setWorld(mcServer.getDimensionWorld(entityplayermp.dimension));
-            logger.info(getUserAndIPString() + " logged in with entity id " + entityplayermp.id + " at (" + entityplayermp.x + ", " + entityplayermp.y + ", " + entityplayermp.z + ")");
-            WorldServer worldserver = mcServer.getDimensionWorld(entityplayermp.dimension);
+            mcServer.playerList.load(player);
+            player.setWorld(mcServer.getDimensionWorld(player.dimension));
+            LOGGER.info(getUserAndIPString() + " logged in with entity id " + player.id + " at (" + player.x + ", " + player.y + ", " + player.z + ")");
+            WorldServer worldserver = mcServer.getDimensionWorld(player.dimension);
             ChunkCoordinates chunkcoordinates = worldserver.getSpawnPoint();
-            ServerPacketHandler netserverhandler = new ServerPacketHandler(mcServer, netManager, entityplayermp);
+            ServerPacketHandler packetHandler = new ServerPacketHandler(mcServer, netManager, player);
             try
             {
-                netserverhandler.sendPacket(new LoginPacket("", entityplayermp.id, worldserver.getRandomSeed(), (byte) worldserver.dimension.id, (byte) Registries.WORLD_TYPES.getNumericIdOfItem(worldserver.dimensionData.getWorldType()), NetworkManager.PACKET_DELAY, RSA.getPublicKey(RSA.RSAKeyChain.getPublic())));
+                packetHandler.sendPacket(new LoginPacket("", new UUID(0, 0), player.id, worldserver.getRandomSeed(), (byte) worldserver.dimension.id, (byte) Registries.WORLD_TYPES.getNumericIdOfItem(worldserver.dimensionData.getWorldType()), NetworkManager.PACKET_DELAY, RSA.getPublicKey(RSA.RSAKeyChain.getPublic())));
 
                 Key aesKey = AES.generateKey();
-                netserverhandler.sendPacket(new AESSendKeyPacket(RSA.encrypt(AES.getKey(aesKey), RSA.getPublicKey(loginPacket.publicKey))));
-                AES.keyChain.put(entityplayermp.username, aesKey);
+                packetHandler.sendPacket(new AESSendKeyPacket(RSA.encrypt(AES.getKey(aesKey), RSA.getPublicKey(loginPacket.publicKey))));
+                AES.keyChain.put(player.username, aesKey);
             }
             catch (Exception e)
             {
                 throw new RuntimeException(e);
             }
 
-            netserverhandler.sendPacket(new SetSpawnPositionPacket(chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z));
-            mcServer.playerList.func_28170_a(entityplayermp, worldserver);
-            mcServer.playerList.sendPacketToAllPlayers(new ChatPacket(TextFormatting.YELLOW + entityplayermp.getDisplayName() + TextFormatting.YELLOW + " joined the game."));
-            mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(entityplayermp.username, entityplayermp.nickname, entityplayermp.score, entityplayermp.chatColor, true, entityplayermp.isOperator()));
+            packetHandler.sendPacket(new SetSpawnPositionPacket(chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z));
+            mcServer.playerList.func_28170_a(player, worldserver);
+            mcServer.playerList.sendPacketToAllPlayers(new ChatPacket(TextFormatting.YELLOW + player.getDisplayName() + TextFormatting.YELLOW + " joined the game."));
+            mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(player.username, player.nickname, player.uuid, player.score, player.chatColor, true, player.isOperator()));
 
-            if (mcServer.joinMessage != null && mcServer.joinMessage.length() > 0)
+            if (mcServer.joinMessage != null && !mcServer.joinMessage.isEmpty())
             {
-                entityplayermp.playerNetServerHandler.sendPacket(new ChatPacket(mcServer.joinMessage));
+                player.playerNetServerHandler.sendPacket(new ChatPacket(mcServer.joinMessage));
             }
 
-            mcServer.playerList.playerLoggedIn(entityplayermp);
-            netserverhandler.teleportAndRotate(entityplayermp.x, entityplayermp.y, entityplayermp.z, entityplayermp.yRot, entityplayermp.xRot);
-            mcServer.networkServer.addPlayer(netserverhandler);
-            mcServer.playerList.sendPacketToAllPlayers(new PlayerGamemodePacket(entityplayermp.id, entityplayermp.gamemode.getId()));
-            netserverhandler.sendPacket(new SetTimePacket(worldserver.getWorldTime()));
-            entityplayermp.func_20057_k();
+            mcServer.playerList.playerLoggedIn(player);
+            packetHandler.teleportAndRotate(player.x, player.y, player.z, player.yRot, player.xRot);
+            mcServer.networkServer.addPlayer(packetHandler);
+            mcServer.playerList.sendPacketToAllPlayers(new PlayerGamemodePacket(player.id, player.gamemode.getId()));
+            packetHandler.sendPacket(new SetTimePacket(worldserver.getWorldTime()));
+            player.func_20057_k();
             if (MinecraftServer.statsStatus)
             {
                 RestHandler.post("https://api.betterthanadventure.net/stats?serverToken=" + MinecraftServer.statsToken + "&count=" + mcServer.playerList.playerEntities.size());
             }
-            entityplayermp.playerNetServerHandler.sendPacket(new PhotoModePacket(mcServer.disablePhotoMode));
-            entityplayermp.playerNetServerHandler.sendPacket(new GameRulePacket(mcServer.getDimensionWorld(0).getLevelData().getGameRules()));
+            player.playerNetServerHandler.sendPacket(new PhotoModePacket(mcServer.disablePhotoMode));
+            player.playerNetServerHandler.sendPacket(new GameRulePacket(mcServer.getDimensionWorld(0).getLevelData().getGameRules()));
 
             for (RecipeEntryBase<?, ?, ?> recipe : Registries.RECIPES.getAllSerializableRecipes()) {
-                entityplayermp.playerNetServerHandler.sendPacket(new RecipeSyncPacket(recipe,Registries.RECIPES.getAllSerializableRecipes().size()));
+                player.playerNetServerHandler.sendPacket(new RecipeSyncPacket(recipe,Registries.RECIPES.getAllSerializableRecipes().size()));
             }
-            entityplayermp.playerNetServerHandler.sendPacket(new SyncIDsPacket());
+            player.playerNetServerHandler.sendPacket(new SyncIDsPacket());
         }
         finishedProcessing = true;
     }
 
     @Override
-	public void handleErrorMessage(String s, Object aobj[])
+	public void handleErrorMessage(String message, Object[] objects)
     {
-        logger.info(getUserAndIPString() + " lost connection");
+        LOGGER.info("{} lost connection", getUserAndIPString());
+        LOGGER.error(message, objects);
         finishedProcessing = true;
     }
 
@@ -249,24 +290,13 @@ public class LoginPacketHandler extends PacketHandler
         return true;
     }
 
-    public static String getServerId(LoginPacketHandler netloginhandler)
+    public static String getServerId(LoginPacketHandler loginPacketHandler)
     {
-        return netloginhandler.serverId;
+        return loginPacketHandler.serverId;
     }
 
-    public static LoginPacket setLoginPacket(LoginPacketHandler netloginhandler, LoginPacket loginPacket)
+    public static LoginPacket setLoginPacket(LoginPacketHandler loginPacketHandler, LoginPacket loginPacket)
     {
-        return netloginhandler.loginPacket = loginPacket;
+        return loginPacketHandler.loginPacket = loginPacket;
     }
-
-    public static Logger logger = Logger.getLogger("Minecraft");
-    private static Random rand = new Random();
-    public NetworkManager netManager;
-    public boolean finishedProcessing;
-    private MinecraftServer mcServer;
-    private int loginTimer;
-    private String username;
-    private LoginPacket loginPacket;
-    private String serverId;
-
 }
diff --git a/src/main/java/net/minecraft/server/net/handler/ServerPacketHandler.java b/src/main/java/net/minecraft/server/net/handler/ServerPacketHandler.java
index 4b2550d1f..413f87bc7 100644
--- a/src/main/java/net/minecraft/server/net/handler/ServerPacketHandler.java
+++ b/src/main/java/net/minecraft/server/net/handler/ServerPacketHandler.java
@@ -1,5 +1,6 @@
 package net.minecraft.server.net.handler;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.entity.FlagBlockEntity;
 import net.minecraft.core.block.entity.MobSpawnerBlockEntity;
@@ -67,7 +68,7 @@ import net.minecraft.server.MinecraftServer;
 import net.minecraft.server.entity.player.ServerPlayer;
 import net.minecraft.server.util.helper.PlayerList;
 import net.minecraft.server.world.WorldServer;
-import org.apache.log4j.Logger;
+import org.slf4j.Logger;
 
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -82,7 +83,7 @@ public class ServerPacketHandler extends PacketHandler
     {
         connectionClosed = false;
         hasMoved = true;
-        field_10_k = new HashMap();
+        guiIdMap = new HashMap<>();
         mcServer = minecraftserver;
         netManager = networkManager;
         networkManager.setNetHandler(this);
@@ -106,7 +107,7 @@ public class ServerPacketHandler extends PacketHandler
         sendPacket(new DisconnectPacket(s));
         netManager.serverShutdown();
         mcServer.playerList.sendPacketToAllPlayers(new ChatPacket(playerEntity.getDisplayName() + TextFormatting.YELLOW + " was kicked from the game."));
-        mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(playerEntity.username, playerEntity.nickname, playerEntity.score, playerEntity.chatColor, false, playerEntity.isOperator()));
+        mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(playerEntity.username, playerEntity.nickname, playerEntity.uuid, playerEntity.score, playerEntity.chatColor, false, playerEntity.isOperator()));
         mcServer.playerList.playerLoggedOut(playerEntity);
         connectionClosed = true;
         if (MinecraftServer.statsStatus)
@@ -211,10 +212,6 @@ public class ServerPacketHandler extends PacketHandler
             {
                 packet.hasPosition = false;
             }
-            if (packet.hasPosition && packet.y == -999D && packet.yView == -999D)
-            {
-                packet.hasPosition = false;
-            }
             if (packet.hasPosition)
             {
                 newPosX = packet.x;
@@ -231,7 +228,7 @@ public class ServerPacketHandler extends PacketHandler
                 if (java.lang.Math.abs(packet.x) > 32000000D || java.lang.Math.abs(packet.z) > 32000000D)
                 {
 //                    kickPlayer("Illegal position");
-                    logger.warn((new StringBuilder()).append(playerEntity.username).append(" tried to move to an illegal position").toString());
+                    LOGGER.warn("{} tried to move to an illegal position", playerEntity.username);
                     teleportAndRotate(lastPosX, lastPosY, lastPosZ, f2, f3);
                     return;
                 }
@@ -255,7 +252,7 @@ public class ServerPacketHandler extends PacketHandler
             // Lag back the player if they move too quickly
             if (velSquared > 100D)
             {
-                logger.warn(playerEntity.username + " moved too quickly!");
+                LOGGER.warn("{} moved too quickly!", playerEntity.username);
                 teleportAndRotate(lastPosX, lastPosY, lastPosZ, f2, f3);
 //                kickPlayer("You moved too quickly :( (Hacking?)");
                 return;
@@ -275,9 +272,9 @@ public class ServerPacketHandler extends PacketHandler
             if (!playerEntity.getGamemode().canPlayerFly() && velSquared > 0.0625D && !playerEntity.isPlayerSleeping())
             {
                 flag1 = true;
-                logger.warn(playerEntity.username + " moved wrongly!");
-                System.out.println("Got position " + newPosX + ", " + newPosY + ", " + newPosZ);
-                System.out.println("Expected " + playerEntity.x + ", " + playerEntity.y + ", " + playerEntity.z);
+                LOGGER.warn("{} moved wrongly!", playerEntity.username);
+                LOGGER.warn("Got position {}, {}, {}", newPosX, newPosY, newPosZ);
+                LOGGER.warn("Expected {}, {}, {}", playerEntity.x, playerEntity.y, playerEntity.z);
             }
             playerEntity.absMoveTo(newPosX, newPosY, newPosZ, f2, f3);
             boolean flag2 = worldserver.getCubes(playerEntity, playerEntity.bb.copy().getInsetBoundingBox(f4, f4, f4)).size() == 0;
@@ -286,14 +283,14 @@ public class ServerPacketHandler extends PacketHandler
                 teleportAndRotate(lastPosX, lastPosY, lastPosZ, f2, f3);
                 return;
             }
-            AABB axisalignedbb = playerEntity.bb.copy().grow(f4, f4, f4).expand(0.0D, -0.55D, 0.0D);
-            if (!playerEntity.getGamemode().canPlayerFly() && !mcServer.allowFlight && !worldserver.getIsAnySolidGround(axisalignedbb))
+            AABB aabb = playerEntity.bb.copy().grow(f4, f4, f4).expand(0.0D, -0.55D, 0.0D);
+            if (!playerEntity.getGamemode().canPlayerFly() && !mcServer.allowFlight && !worldserver.getIsAnySolidGround(aabb))
             {
                 if (dy > -0.03125D)
                 {
                     playerInAirTime++;
                     if (playerInAirTime > 100) {
-                        logger.warn(playerEntity.username + " was kicked for floating too long!");
+                        LOGGER.warn(playerEntity.username + " was kicked for floating too long!");
                         kickPlayer("Flying is not enabled on this server");
                         return;
                     } else if (playerInAirTime > 80)
@@ -363,7 +360,7 @@ public class ServerPacketHandler extends PacketHandler
         }
 
         // Check spawn protection
-        boolean ignoreSpawnProtection = world.field_819_z = mcServer.spawnProtectionRange <= 0 || world.dimension.id != 0 || mcServer.playerList.isOp(playerEntity.username);
+        boolean ignoreSpawnProtection = world.field_819_z = mcServer.spawnProtectionRange <= 0 || world.dimension.id != 0 || mcServer.playerList.isOp(playerEntity.uuid);
         ChunkCoordinates spawnPos = world.getSpawnPoint();
         int spawnDistX = (int) MathHelper.abs(x - spawnPos.x);
         int spawnDistZ = (int) MathHelper.abs(z - spawnPos.z);
@@ -392,9 +389,9 @@ public class ServerPacketHandler extends PacketHandler
 
     public void handleSendInitialPlayerList()
     {
-        for (ServerPlayer entityPlayerServer : mcServer.playerList.playerEntities)
+        for (ServerPlayer serverPlayer : mcServer.playerList.playerEntities)
         {
-            sendPacket(new UpdatePlayerProfilePacket(entityPlayerServer.username, entityPlayerServer.nickname, entityPlayerServer.score, entityPlayerServer.chatColor, true, entityPlayerServer.isOperator()));
+            sendPacket(new UpdatePlayerProfilePacket(serverPlayer.username, serverPlayer.nickname, serverPlayer.uuid, serverPlayer.score, serverPlayer.chatColor, true, serverPlayer.isOperator()));
         }
     }
 
@@ -404,7 +401,7 @@ public class ServerPacketHandler extends PacketHandler
         if (!playerEntity.getGamemode().canInteract() || !playerEntity.isAlive()) return;
         WorldServer worldserver = mcServer.getDimensionWorld(playerEntity.dimension);
         ItemStack itemstack = playerEntity.inventory.getCurrentItem();
-        boolean flag = worldserver.field_819_z = worldserver.dimension.id != 0 || mcServer.playerList.isOp(playerEntity.username);
+        boolean flag = worldserver.field_819_z = worldserver.dimension.id != 0 || mcServer.playerList.isOp(playerEntity.uuid);
         if (packet.direction == Direction.NONE)
         {
             if (itemstack == null)
@@ -458,9 +455,9 @@ public class ServerPacketHandler extends PacketHandler
     @Override
     public void handleErrorMessage(String s, Object[] aobj)
     {
-        logger.info(playerEntity.username + " lost connection: " + s);
+        LOGGER.info(playerEntity.username + " lost connection: " + s);
         mcServer.playerList.sendPacketToAllPlayers(new ChatPacket(playerEntity.getDisplayName() + TextFormatting.YELLOW + " left the game."));
-        mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(playerEntity.username, playerEntity.nickname, playerEntity.score, playerEntity.chatColor, false, playerEntity.isOperator()));
+        mcServer.playerList.sendPacketToAllPlayers(new UpdatePlayerProfilePacket(playerEntity.username, playerEntity.nickname, playerEntity.uuid, playerEntity.score, playerEntity.chatColor, false, playerEntity.isOperator()));
         mcServer.playerList.playerLoggedOut(playerEntity);
         connectionClosed = true;
         if (MinecraftServer.statsStatus)
@@ -473,7 +470,7 @@ public class ServerPacketHandler extends PacketHandler
     @Override
     public void handleInvalidPacket(Packet packet)
     {
-        logger.warn(getClass() + " wasn't prepared to deal with a " + packet.getClass());
+        LOGGER.warn(getClass() + " wasn't prepared to deal with a " + packet.getClass());
         kickPlayer("Protocol error, unexpected packet");
     }
 
@@ -488,7 +485,7 @@ public class ServerPacketHandler extends PacketHandler
     {
         if (packet.id < 0 || packet.id > Inventory.func_25054_e())
         {
-            logger.warn(playerEntity.username + " tried to set an invalid carried item");
+            LOGGER.warn(playerEntity.username + " tried to set an invalid carried item");
             return;
         }
         else
@@ -516,7 +513,7 @@ public class ServerPacketHandler extends PacketHandler
 		}
 		
 		message = message.trim();
-//		message = message.replace('\u00A7', '$');
+//		message = message.replace('§', '$');
 		
 		for(int i = 0; i < message.length(); i++) {
 			char c = message.charAt(i);
@@ -531,7 +528,7 @@ public class ServerPacketHandler extends PacketHandler
 		}else {
 			message = ChatEmotes.process(message);
 			message = "<" + playerEntity.getDisplayName() + TextFormatting.RESET + "> " + TextFormatting.WHITE + message;
-			logger.info(message);
+			LOGGER.info(message);
 			mcServer.playerList.sendEncryptedChatToAllPlayers(message);
 		}
 	}
@@ -551,12 +548,12 @@ public class ServerPacketHandler extends PacketHandler
             {
                 if (!sender.isAdmin() && command.opRequired(args1))
                 {
-                    logger.info("Player " + sender.getPlayer().username + " tried command: " + s);
+                    LOGGER.info("Player {} tried command: {}", sender.getPlayer().username, s);
                     sender.sendMessage(TextFormatting.RED + "You don't have permission to use this command!");
                     return;
                 }
 
-                logger.info("Player " + sender.getPlayer().username + " used command: " + s);
+                LOGGER.info("Player {} used command: {}", sender.getPlayer().username, s);
                 try
                 {
                     boolean success = command.execute(handler, sender, args1);
@@ -571,7 +568,7 @@ public class ServerPacketHandler extends PacketHandler
                 }
                 catch (Throwable e)
                 {
-                    e.printStackTrace();
+                    LOGGER.error("Exception while trying to perform command '{}'!", s, e);
                     sender.sendMessage(TextFormatting.RED + "Error!");
                 }
                 return;
@@ -632,7 +629,7 @@ public class ServerPacketHandler extends PacketHandler
     }
 
     @Override
-    public void log(String s)
+    public void logInfo(String s)
     {
         sendPacket(new ChatPacket("\2477" + s));
     }
@@ -725,7 +722,7 @@ public class ServerPacketHandler extends PacketHandler
             }
             else
             {
-                field_10_k.put(Integer.valueOf(playerEntity.craftingInventory.containerId), Short.valueOf(packet.actionId));
+                guiIdMap.put(playerEntity.craftingInventory.containerId, packet.actionId);
                 playerEntity.playerNetServerHandler.sendPacket(new ContainerAckPacket(packet.window_Id, packet.actionId, false));
                 playerEntity.craftingInventory.setSynched(playerEntity, false);
                 ArrayList<ItemStack> arraylist = new ArrayList<>();
@@ -742,8 +739,8 @@ public class ServerPacketHandler extends PacketHandler
     @Override
     public void handleTransaction(ContainerAckPacket packet)
     {
-        Short short1 = (Short) field_10_k.get(Integer.valueOf(playerEntity.craftingInventory.containerId));
-        if (short1 != null && packet.shortWindowId == short1.shortValue() && playerEntity.craftingInventory.containerId == packet.windowId && !playerEntity.craftingInventory.isSynched(playerEntity))
+        Short short1 = guiIdMap.get(playerEntity.craftingInventory.containerId);
+        if (short1 != null && packet.shortWindowId == short1 && playerEntity.craftingInventory.containerId == packet.windowId && !playerEntity.craftingInventory.isSynched(playerEntity))
         {
             playerEntity.craftingInventory.setSynched(playerEntity, true);
         }
@@ -756,13 +753,13 @@ public class ServerPacketHandler extends PacketHandler
         WorldServer worldserver = mcServer.getDimensionWorld(playerEntity.dimension);
         if (worldserver.isBlockLoaded(packet.xPosition, packet.yPosition, packet.zPosition))
         {
-            BlockEntity tileentity = worldserver.getBlockEntity(packet.xPosition, packet.yPosition, packet.zPosition);
-            if (tileentity instanceof SignBlockEntity)
+            BlockEntity blockEntity = worldserver.getBlockEntity(packet.xPosition, packet.yPosition, packet.zPosition);
+            if (blockEntity instanceof SignBlockEntity)
             {
-                SignBlockEntity tileentitysign = (SignBlockEntity) tileentity;
-                if (!tileentitysign.isEditableBy(playerEntity))
+                SignBlockEntity sign = (SignBlockEntity) blockEntity;
+                if (!sign.isEditableBy(playerEntity))
                 {
-                    mcServer.logWarning("Player " + playerEntity.username + " just tried to change non-editable sign");
+                    LOGGER.warn("Player {} just tried to change non-editable sign", playerEntity.username);
                     return;
                 }
             }
@@ -775,7 +772,7 @@ public class ServerPacketHandler extends PacketHandler
                 }
                 else
                 {
-                    packet.signLines[i] = packet.signLines[i].replaceAll("\u00A7", "$");
+                    packet.signLines[i] = packet.signLines[i].replaceAll("§", "$");
                     for (int l = 0; l < packet.signLines[i].length(); l++)
                     {
                         if (ChatAllowedCharacters.ALLOWED_CHARACTERS.indexOf(packet.signLines[i].charAt(l)) < 0)
@@ -791,16 +788,13 @@ public class ServerPacketHandler extends PacketHandler
                 }
             }
 
-            if (tileentity instanceof SignBlockEntity)
+            if (blockEntity instanceof SignBlockEntity)
             {
                 int x = packet.xPosition;
                 int y = packet.yPosition;
                 int z = packet.zPosition;
-                SignBlockEntity tileEntity = (SignBlockEntity) tileentity;
-                for (int j1 = 0; j1 < 4; j1++)
-                {
-                    tileEntity.signText[j1] = packet.signLines[j1];
-                }
+                SignBlockEntity tileEntity = (SignBlockEntity) blockEntity;
+                System.arraycopy(packet.signLines, 0, tileEntity.signText, 0, 4);
 
                 tileEntity.setColor(TextFormatting.FORMATTINGS[packet.color]);
                 tileEntity.setPicture(EnumSignPicture.values()[packet.picture]);
@@ -852,18 +846,18 @@ public class ServerPacketHandler extends PacketHandler
     	}else if("BTA|Flag".equals(packet.channel)) {
     		if(packet.data.length == 24 * 16 && playerEntity.craftingInventory instanceof FlagMenu) {
     			FlagMenu flagMenu = (FlagMenu) playerEntity.craftingInventory;
-    			FlagBlockEntity tileEntity = flagMenu.flag;
-    			
-    			if(tileEntity.owner == null || tileEntity.owner.isEmpty() || tileEntity.owner.equals(playerEntity.username)) {
-        			tileEntity.owner = playerEntity.username;
-        			System.arraycopy(packet.data, 0, tileEntity.flagColors, 0, 24 * 16);
-        			
-        			playerEntity.world.markBlockNeedsUpdate(tileEntity.x, tileEntity.y, tileEntity.z);
+    			FlagBlockEntity flag = flagMenu.flag;
+
+    			if(flag.owner == null || flag.owner.equals(playerEntity.uuid)) {
+                    flag.owner = playerEntity.uuid;
+        			System.arraycopy(packet.data, 0, flag.flagColors, 0, 24 * 16);
+
+        			playerEntity.world.markBlockNeedsUpdate(flag.x, flag.y, flag.z);
     			}else {
-    				System.out.println("Player '" + playerEntity.username + "' tried editing a flag that belongs to '" + tileEntity.owner + "'!");
-    				
+                    LOGGER.warn("Player '{}' tried editing a flag that belongs to '{}'!", playerEntity.username, flag.owner);
+
     				// Let the client know that the flag design has been rejected
-    				playerEntity.world.markBlockNeedsUpdate(tileEntity.x, tileEntity.y, tileEntity.z);
+    				playerEntity.world.markBlockNeedsUpdate(flag.x, flag.y, flag.z);
     			}
     		}
     	} else if ("BTA|WandMonster".equals(packet.channel)) {
@@ -881,10 +875,10 @@ public class ServerPacketHandler extends PacketHandler
     }
 
 
-    public static Logger logger = Logger.getLogger("Minecraft");
+    public static Logger LOGGER = LogUtils.getLogger();
     public NetworkManager netManager;
     public boolean connectionClosed;
-    private MinecraftServer mcServer;
+    private final MinecraftServer mcServer;
     private ServerPlayer playerEntity;
     private int field_15_f;
     private int field_22004_g;
@@ -894,6 +888,6 @@ public class ServerPacketHandler extends PacketHandler
     private double lastPosY;
     private double lastPosZ;
     private boolean hasMoved;
-    private final Map<Integer, Short> field_10_k;
+    private final Map<Integer, Short> guiIdMap;
 
 }
diff --git a/src/main/java/net/minecraft/server/net/thread/ThreadCommandReader.java b/src/main/java/net/minecraft/server/net/thread/ThreadCommandReader.java
deleted file mode 100644
index 3f1d8e3af..000000000
--- a/src/main/java/net/minecraft/server/net/thread/ThreadCommandReader.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package net.minecraft.server.net.thread;
-
-import java.io.*;
-import net.minecraft.server.MinecraftServer;
-
-public class ThreadCommandReader extends Thread
-{
-
-    public ThreadCommandReader(MinecraftServer minecraftserver)
-    {
-//        super();
-        mcServer = minecraftserver;
-    }
-
-    @Override
-	public void run()
-    {
-        BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in));
-        String s = null;
-        try
-        {
-            while(!mcServer.serverStopped && MinecraftServer.isServerRunning(mcServer) && (s = bufferedreader.readLine()) != null) 
-            {
-                mcServer.addCommand(s, mcServer);
-            }
-        }
-        catch(IOException ioexception)
-        {
-            ioexception.printStackTrace();
-        }
-    }
-
-    final MinecraftServer mcServer; /* synthetic field */
-}
diff --git a/src/main/java/net/minecraft/server/net/thread/ThreadLoginVerifier.java b/src/main/java/net/minecraft/server/net/thread/ThreadLoginVerifier.java
deleted file mode 100644
index 19b67f889..000000000
--- a/src/main/java/net/minecraft/server/net/thread/ThreadLoginVerifier.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package net.minecraft.server.net.thread;
-
-import net.minecraft.core.net.packet.LoginPacket;
-import net.minecraft.server.net.handler.LoginPacketHandler;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.net.URLEncoder;
-
-// Referenced classes of package net.minecraft.src:
-//            LoginPacketHandler, LoginPacket
-
-public class ThreadLoginVerifier extends Thread
-{
-
-    public ThreadLoginVerifier(LoginPacketHandler netloginhandler, LoginPacket loginPacket)
-    {
-//        super();
-        loginHandler = netloginhandler;
-        this.loginPacket = loginPacket;
-    }
-
-    @Override
-	public void run()
-    {
-        try
-        {
-            String s = LoginPacketHandler.getServerId(loginHandler);
-            URL url = new URL((new StringBuilder()).append("http://session.minecraft.net/game/checkserver.jsp?user=").append(URLEncoder.encode(loginPacket.username, "UTF-8")).append("&serverId=").append(URLEncoder.encode(s, "UTF-8")).toString());
-            BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(url.openStream()));
-            String s1 = bufferedreader.readLine();
-            bufferedreader.close();
-            if(s1.equals("YES"))
-            {
-                LoginPacketHandler.setLoginPacket(loginHandler, loginPacket);
-            } else
-            {
-                loginHandler.kickUser("Failed to verify username!");
-            }
-        }
-        catch(Exception exception)
-        {
-            loginHandler.kickUser((new StringBuilder()).append("Failed to verify username! [internal error ").append(exception).append("]").toString());
-            exception.printStackTrace();
-        }
-    }
-
-    final LoginPacket loginPacket; /* synthetic field */
-    final LoginPacketHandler loginHandler; /* synthetic field */
-}
diff --git a/src/main/java/net/minecraft/server/net/thread/ThreadServerApplication.java b/src/main/java/net/minecraft/server/net/thread/ThreadServerApplication.java
deleted file mode 100644
index 606663ea7..000000000
--- a/src/main/java/net/minecraft/server/net/thread/ThreadServerApplication.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package net.minecraft.server.net.thread;
-
-import net.minecraft.server.MinecraftServer;
-
-public final class ThreadServerApplication extends Thread
-{
-
-    public ThreadServerApplication(String s, MinecraftServer minecraftserver)
-    {
-        super(s);
-        mcServer = minecraftserver;
-    }
-
-    @Override
-	public void run()
-    {
-        mcServer.run();
-    }
-
-    final MinecraftServer mcServer; /* synthetic field */
-}
diff --git a/src/main/java/net/minecraft/server/net/thread/ThreadSleepForeverServer.java b/src/main/java/net/minecraft/server/net/thread/ThreadSleepForeverServer.java
deleted file mode 100644
index 1e040c506..000000000
--- a/src/main/java/net/minecraft/server/net/thread/ThreadSleepForeverServer.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package net.minecraft.server.net.thread;
-
-import net.minecraft.server.MinecraftServer;
-
-public class ThreadSleepForeverServer extends Thread
-{
-
-    public ThreadSleepForeverServer(MinecraftServer minecraftserver)
-    {
-//        super();
-        mc = minecraftserver;
-        setDaemon(true);
-        start();
-    }
-
-    @Override
-	public void run()
-    {
-        do
-        {
-            try
-            {
-                Thread.sleep(0x7fffffffL);
-            }
-            catch(InterruptedException interruptedexception) { }
-        } while(true);
-    }
-
-    final MinecraftServer mc; /* synthetic field */
-}
diff --git a/src/main/java/net/minecraft/server/world/ConvertProgressUpdater.java b/src/main/java/net/minecraft/server/world/ConvertProgressUpdater.java
index 7ccbf75d3..3ef1589bf 100644
--- a/src/main/java/net/minecraft/server/world/ConvertProgressUpdater.java
+++ b/src/main/java/net/minecraft/server/world/ConvertProgressUpdater.java
@@ -26,7 +26,7 @@ public class ConvertProgressUpdater
         if(System.currentTimeMillis() - lastTimeMillis >= 1000L)
         {
             lastTimeMillis = System.currentTimeMillis();
-            MinecraftServer.logger.info("Converting... " + i + "%");
+            MinecraftServer.LOGGER.info("Converting... " + i + "%");
         }
     }
 
diff --git a/src/main/java/net/minecraft/server/world/WorldManager.java b/src/main/java/net/minecraft/server/world/WorldManager.java
index 62e3d8f79..cb300ce19 100644
--- a/src/main/java/net/minecraft/server/world/WorldManager.java
+++ b/src/main/java/net/minecraft/server/world/WorldManager.java
@@ -3,6 +3,7 @@ package net.minecraft.server.world;
 import java.util.HashSet;
 import java.util.Set;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.entity.Entity;
 import net.minecraft.core.entity.ItemEntity;
@@ -13,20 +14,16 @@ import net.minecraft.core.sound.SoundTypes;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.world.LevelListener;
 import net.minecraft.server.MinecraftServer;
-
-// Referenced classes of package net.minecraft.src:
-//            IWorldAccess, WorldServer, WorldProvider, EntityTracker, 
-//            ServerConfigurationManager, Packet61DoorChange, Entity, BlockEntity,
-//            Player
+import org.slf4j.Logger;
 
 public class WorldManager
     implements LevelListener
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
+	private static final Set<String> unknownSoundTypes = new HashSet<>();
 
-	private static Set<String> unknownSoundTypes = new HashSet<>();
-
-    private MinecraftServer mcServer;
-    private WorldServer worldServer;
+    private final MinecraftServer mcServer;
+    private final WorldServer worldServer;
 
     public WorldManager(MinecraftServer minecraftserver, WorldServer worldserver)
     {
@@ -75,7 +72,7 @@ public class WorldManager
 		int soundId = SoundTypes.getSoundId(soundPath);
 		if(soundId == -1) {
 			if(!unknownSoundTypes.contains(soundPath)) {
-				System.out.println("Unable to play unknown sound '" + soundPath + "'!");
+                LOGGER.warn("Unable to play unknown sound '{}'!", soundPath);
 				unknownSoundTypes.add(soundPath);
 			}
 			return;
diff --git a/src/main/java/net/minecraft/server/world/WorldServer.java b/src/main/java/net/minecraft/server/world/WorldServer.java
index 29cc2d08a..4291a924d 100644
--- a/src/main/java/net/minecraft/server/world/WorldServer.java
+++ b/src/main/java/net/minecraft/server/world/WorldServer.java
@@ -86,7 +86,7 @@ public class WorldServer extends World
         {
             i1 = l;
         }
-        return i1 > 16 || mcServer.playerList.isOp(entityplayer.username);
+        return i1 > 16 || mcServer.playerList.isOp(entityplayer.uuid);
     }
 
     @Override
@@ -252,6 +252,17 @@ public class WorldServer extends World
         mcServer.playerList.sendPacketToAllPlayers(new ChatPacket(message));
     }
 
+    @Override
+    public void addRainbow(int rainbowTicks){
+        byte b0 = (byte) ((rainbowTicks >> 24) & 0xFF);
+        byte b1 = (byte) ((rainbowTicks >> 16) & 0xFF);
+        byte b2 = (byte) ((rainbowTicks >>  8) & 0xFF);
+        byte b3 = (byte) ((rainbowTicks >>  0) & 0xFF);
+//        System.out.printf("b0:%s b1:%s b2:%s b3:%s\n", b0, b1, b2, b3);
+//        System.out.println("Sent rainbow with " + rainbowTicks + " ticks!");
+        mcServer.playerList.sendPacketToAllPlayersInDimension(new CustomPayloadPacket("BTA|RainbowStart", new byte[]{b0, b1, b2, b3}), dimension.id);
+        super.addRainbow(rainbowTicks);
+    }
     public ChunkProviderServer chunkProviderServer;
     public boolean field_819_z;
     public boolean levelSaving;
diff --git a/src/main/java/net/minecraft/server/world/chunk/provider/ChunkProviderServer.java b/src/main/java/net/minecraft/server/world/chunk/provider/ChunkProviderServer.java
index ef9680909..831209fee 100644
--- a/src/main/java/net/minecraft/server/world/chunk/provider/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/world/chunk/provider/ChunkProviderServer.java
@@ -1,10 +1,12 @@
 package net.minecraft.server.world.chunk.provider;
 
+import com.mojang.logging.LogUtils;
 import net.minecraft.core.world.ProgressListener;
 import net.minecraft.core.world.chunk.provider.IChunkProvider;
 import net.minecraft.server.world.WorldServer;
 import net.minecraft.core.world.chunk.*;
 import net.minecraft.core.world.generate.chunk.ChunkGenerator;
+import org.slf4j.Logger;
 
 import java.io.IOException;
 import java.util.*;
@@ -12,6 +14,15 @@ import java.util.*;
 public class ChunkProviderServer
     implements IChunkProvider
 {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private final Set<Integer> droppedChunksSet;
+    private final Chunk emptyChunk;
+    public ChunkGenerator chunkGenerator;
+    private final IChunkLoader chunkLoader;
+    public boolean chunkLoadOverride;
+    private final Map<Integer, Chunk> chunkMap;
+    private final List<Chunk> chunkList;
+    private final WorldServer world;
 
     public ChunkProviderServer(WorldServer world, IChunkLoader chunkLoader, ChunkGenerator chunkGenerator)
     {
@@ -168,7 +179,7 @@ public class ChunkProviderServer
         }
         catch (Exception exception)
         {
-            exception.printStackTrace();
+            LOGGER.error("Failed to load chunk at X:{}, Z:{} to disk!", chunkX, chunkZ, exception);
         }
         return null;
     }
@@ -186,7 +197,7 @@ public class ChunkProviderServer
         }
         catch (IOException ioexception)
         {
-            ioexception.printStackTrace();
+            LOGGER.error("Failed to save chunk at X:{}, Z:{} to disk!", chunk.xPosition, chunk.zPosition, ioexception);
         }
     }
 
@@ -275,13 +286,4 @@ public class ChunkProviderServer
     public void setCurrentChunkOver(int chunkX, int chunkZ) {
         // Do nothing
     }
-
-    private final Set<Integer> droppedChunksSet;
-    private final Chunk emptyChunk;
-    public ChunkGenerator chunkGenerator;
-    private final IChunkLoader chunkLoader;
-    public boolean chunkLoadOverride;
-    private final Map<Integer, Chunk> chunkMap;
-    private final List<Chunk> chunkList;
-    private final WorldServer world;
 }
diff --git a/src/main/java/org/lwjgl/opengl/Display.java b/src/main/java/org/lwjgl/opengl/Display.java
index 260bf6337..add8b0847 100644
--- a/src/main/java/org/lwjgl/opengl/Display.java
+++ b/src/main/java/org/lwjgl/opengl/Display.java
@@ -28,5 +28,4 @@ public abstract class Display {
 	public static long getHandle() {
 		return window.window;
 	}
-
 }
diff --git a/src/main/java/org/useless/seedviewer/SeedViewerMain.java b/src/main/java/org/useless/seedviewer/SeedViewerMain.java
new file mode 100644
index 000000000..a88e811f8
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/SeedViewerMain.java
@@ -0,0 +1,54 @@
+package org.useless.seedviewer;
+
+import com.formdev.flatlaf.FlatDarculaLaf;
+import com.mojang.logging.LogUtils;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.useless.seedviewer.gui.SeedViewer;
+
+import javax.swing.*;
+import java.util.Properties;
+
+public class SeedViewerMain {
+    public static final String VERSION = "1.1.1";
+    public static final Logger LOGGER = LogUtils.getLogger();
+
+    public static void main(String[] args) {
+        try { // Validate BTA jar is present
+            Class.forName("net.minecraft.core.world.biome.provider.BiomeProviderOverworld");
+        } catch (ClassNotFoundException e) {
+            LOGGER.error("Could not locate BTA jar! Canceling Startup!", e);
+            return;
+        }
+        try {
+            UIManager.setLookAndFeel( new FlatDarculaLaf() );
+        } catch( Exception ex ) {
+            LOGGER.error("Failed to initialize LaF theme!", ex);
+        }
+        new SeedViewer(argsToProperties(args));
+    }
+
+    /**
+     * Reads all provided strings for key value pairs, for strings which fail to follow the
+     * key value format will be ignored
+     * @param args Array of strings formated like { -key1, value1, -key2, value2}
+     * @return Properties map representation of provided key value pairs
+     */
+    public static @NotNull Properties argsToProperties(String[] args) {
+        Properties properties = new Properties();
+        for (int i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.startsWith("-")) {
+                String key = arg.substring(1);
+                if (key.isEmpty()) continue;
+                if (i >= args.length - 1) continue; // Ensure that can't index out of bound
+                String value = args[++i]; // Get next argument and shift pointer
+                properties.setProperty(key, value);
+            } else {
+                LOGGER.error("Unrecognized argument '{}'!", arg);
+            }
+
+        }
+        return properties;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/useless/seedviewer/TestChunkProvider.java b/src/main/java/org/useless/seedviewer/TestChunkProvider.java
new file mode 100644
index 000000000..965e87d40
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/TestChunkProvider.java
@@ -0,0 +1,56 @@
+package org.useless.seedviewer;
+
+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;
+
+import java.awt.*;
+
+public class TestChunkProvider implements ChunkProvider {
+    @Override
+    public Chunk getChunk(ChunkLocation location) {
+        return new Chunk() {
+            @Override
+            public Biome getBiome(ChunkPos3D pos) {
+                return new Biome() {
+                    @Override
+                    public String getName() {
+                        return "Test Biome";
+                    }
+
+                    @Override
+                    public NamespaceID getID() {
+                        return new NamespaceID("viewer:test");
+                    }
+
+                    @Override
+                    public int getColor() {
+                        int r = (pos.x << 3) & 0xFF;
+                        int g = (pos.y) & 0xFF;
+                        int b = (pos.z << 3) & 0xFF;
+                        return r << 16 | g << 8 | b;
+                    }
+                };
+            }
+
+            @Override
+            public int getBlockColor(ChunkPos3D pos) {
+                return 0;
+            }
+
+            @Override
+            public int getHeight(ChunkPos2D pos) {
+                return 128;
+            }
+
+            @Override
+            public int getWaterDepth(ChunkPos2D pos) {
+                return 0;
+            }
+        };
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/bta/BTABiome.java b/src/main/java/org/useless/seedviewer/bta/BTABiome.java
new file mode 100644
index 000000000..0088af62d
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/bta/BTABiome.java
@@ -0,0 +1,29 @@
+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 org.useless.seedviewer.data.Biome;
+
+public class BTABiome implements Biome {
+    private final net.minecraft.core.world.biome.Biome biome;
+    public BTABiome(net.minecraft.core.world.biome.Biome biome) {
+        this.biome = biome;
+    }
+    @Override
+    public String getName() {
+        if (biome == null) return "Unknown";
+        return I18n.getInstance().translateKey(biome.translationKey);
+    }
+
+    @Override
+    public NamespaceID getID() {
+        return new NamespaceID(Registries.BIOMES.getKey(biome));
+    }
+
+    @Override
+    public int getColor() {
+        if (biome == null) return 0x00000000;
+        return biome.color;
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/bta/BTAChunkProvider.java b/src/main/java/org/useless/seedviewer/bta/BTAChunkProvider.java
new file mode 100644
index 000000000..eddf95ff2
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/bta/BTAChunkProvider.java
@@ -0,0 +1,65 @@
+package org.useless.seedviewer.bta;
+
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
+import net.minecraft.core.block.Blocks;
+import net.minecraft.core.data.registry.Registries;
+import net.minecraft.core.item.Items;
+import net.minecraft.core.lang.I18n;
+import net.minecraft.core.world.biome.Biomes;
+import net.minecraft.core.world.biome.provider.BiomeProvider;
+import net.minecraft.core.world.biome.provider.BiomeProviderOverworld;
+import net.minecraft.core.world.save.LevelData;
+import net.minecraft.core.world.type.WorldTypes;
+import org.slf4j.Logger;
+import org.useless.seedviewer.bta.worldloader.ChunkLoader;
+import org.useless.seedviewer.collections.ChunkLocation;
+import org.useless.seedviewer.data.Chunk;
+import org.useless.seedviewer.gui.ChunkProvider;
+
+import java.io.File;
+import java.io.IOException;
+
+public class BTAChunkProvider implements ChunkProvider {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    static {
+        if (Global.accessor == null) {
+            Global.accessor = new DummyMinecraft();
+            Blocks.init();
+            Items.init();
+            new Registries();
+            Biomes.init();
+            WorldTypes.init();
+            BiomeProviderOverworld.init();
+            I18n.initialize("en_US");
+        }
+    }
+
+    ChunkLoader chunkLoader = null;
+    private final BiomeProvider biomeProvider;
+
+
+    public BTAChunkProvider(long seed) {
+        biomeProvider = new BiomeProviderOverworld(seed, WorldTypes.OVERWORLD_EXTENDED);
+    }
+
+    public BTAChunkProvider(File worldFolder, LevelData data) {
+        biomeProvider = new BiomeProviderOverworld(data.getRandomSeed(), WorldTypes.OVERWORLD_EXTENDED);
+        chunkLoader = new ChunkLoader(worldFolder, 0);
+    }
+    @Override
+    public Chunk getChunk(ChunkLocation location) {
+        if (chunkLoader != null) {
+            try {
+                net.minecraft.core.world.chunk.Chunk c = chunkLoader.loadChunk(location);
+                if (c != null) {
+                    return new BTAComplexChunk(c);
+                }
+            } catch (IOException e) {
+                LOGGER.error("Failed to load chunk data for chunk {}, {}", location.x, location.z, e);
+            }
+        }
+        return new BTASimpleChunk(location, biomeProvider);
+    }
+
+}
diff --git a/src/main/java/org/useless/seedviewer/bta/BTAComplexChunk.java b/src/main/java/org/useless/seedviewer/bta/BTAComplexChunk.java
new file mode 100644
index 000000000..ee8677775
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/bta/BTAComplexChunk.java
@@ -0,0 +1,51 @@
+package org.useless.seedviewer.bta;
+
+import net.minecraft.core.block.Block;
+import net.minecraft.core.block.material.Material;
+import net.minecraft.core.block.material.MaterialColor;
+import org.jetbrains.annotations.NotNull;
+import org.useless.seedviewer.collections.ChunkPos2D;
+import org.useless.seedviewer.collections.ChunkPos3D;
+import org.useless.seedviewer.data.Biome;
+import org.useless.seedviewer.data.Chunk;
+
+import java.awt.*;
+
+public class BTAComplexChunk implements Chunk {
+    private final net.minecraft.core.world.chunk.Chunk chunk;
+    public BTAComplexChunk(@NotNull net.minecraft.core.world.chunk.Chunk chunk) {
+        this.chunk = chunk;
+    }
+    @Override
+    public Biome getBiome(ChunkPos3D pos) {
+        return new BTABiome(chunk.getBlockBiome(pos.x, pos.y, pos.z));
+    }
+
+    @Override
+    public int getBlockColor(ChunkPos3D pos) {
+        Block b = Block.getBlock(chunk.getBlockID(pos.x, pos.y, pos.z));
+        if (b == null) return 0;
+        int meta = chunk.getBlockMetadata(pos.x, pos.y, pos.z);
+        return MaterialColor.getColorFromIndex(MaterialColor.getColorIndexFromBlock(b, meta)) | 0xFF_00_00_00;
+    }
+
+    @Override
+    public int getHeight(ChunkPos2D pos) {
+        return chunk.getHeightValue(pos.x, pos.z);
+    }
+
+    @Override
+    public int getWaterDepth(ChunkPos2D pos) {
+        int start = getHeight(pos) - 1;
+        int depth = 0;
+        while (true) {
+            int y = start - depth;
+            if (y < 0) break;
+            Block b = Block.getBlock(chunk.getBlockID(pos.x, y, pos.z));
+            if (b == null) break;
+            if (b.blockMaterial != Material.water) break;
+            depth++;
+        }
+        return depth;
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/bta/BTASimpleChunk.java b/src/main/java/org/useless/seedviewer/bta/BTASimpleChunk.java
new file mode 100644
index 000000000..657415819
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/bta/BTASimpleChunk.java
@@ -0,0 +1,38 @@
+package org.useless.seedviewer.bta;
+
+import net.minecraft.core.world.biome.provider.BiomeProvider;
+import org.useless.seedviewer.collections.ChunkLocation;
+import org.useless.seedviewer.collections.ChunkPos2D;
+import org.useless.seedviewer.collections.ChunkPos3D;
+import org.useless.seedviewer.data.Biome;
+import org.useless.seedviewer.data.Chunk;
+
+import java.awt.*;
+
+public class BTASimpleChunk implements Chunk {
+    private final ChunkLocation location;
+    private final BiomeProvider provider;
+    public BTASimpleChunk(ChunkLocation location, BiomeProvider biomeProvider) {
+        this.location = location;
+        provider = biomeProvider;
+    }
+    @Override
+    public Biome getBiome(ChunkPos3D pos) {
+        return new BTABiome(provider.getBiome(location.x * Chunk.CHUNK_SIZE_X + pos.x, pos.y, location.z * Chunk.CHUNK_SIZE_Z + pos.z));
+    }
+
+    @Override
+    public int getBlockColor(ChunkPos3D pos) {
+        return 0;
+    }
+
+    @Override
+    public int getHeight(ChunkPos2D pos) {
+        return 128;
+    }
+
+    @Override
+    public int getWaterDepth(ChunkPos2D pos) {
+        return 0;
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/bta/BTAWorld.java b/src/main/java/org/useless/seedviewer/bta/BTAWorld.java
new file mode 100644
index 000000000..34329fad4
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/bta/BTAWorld.java
@@ -0,0 +1,43 @@
+package org.useless.seedviewer.bta;
+
+import net.minecraft.core.world.save.LevelData;
+import org.jetbrains.annotations.NotNull;
+import org.useless.seedviewer.bta.worldloader.LevelDataLoader;
+import org.useless.seedviewer.data.World;
+import org.useless.seedviewer.gui.ChunkProvider;
+
+import java.io.File;
+import java.util.Objects;
+
+public class BTAWorld implements World {
+    private final @NotNull File worldFolder;
+    private final LevelData data;
+    public BTAWorld(@NotNull File worldFolder) {
+        this.worldFolder = worldFolder;
+        this.data = Objects.requireNonNull(LevelDataLoader.getLevelData(worldFolder), "Failed to get level data from world '" + worldFolder + "'");
+    }
+    @Override
+    public File getFolder() {
+        return worldFolder;
+    }
+
+    @Override
+    public long getSeed() {
+        return data.getRandomSeed();
+    }
+
+    @Override
+    public String getName() {
+        return data.getWorldName();
+    }
+
+    @Override
+    public long getLastPlayed() {
+        return data.getLastTimePlayed();
+    }
+
+    @Override
+    public ChunkProvider getChunkProvider() {
+        return new BTAChunkProvider(worldFolder, data);
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/bta/DummyMinecraft.java b/src/main/java/org/useless/seedviewer/bta/DummyMinecraft.java
new file mode 100644
index 000000000..20be08c87
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/bta/DummyMinecraft.java
@@ -0,0 +1,33 @@
+package org.useless.seedviewer.bta;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.world.chunk.provider.ChunkProviderStatic;
+import net.minecraft.core.MinecraftAccessor;
+import net.minecraft.core.entity.SkinVariantList;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.chunk.IChunkLoader;
+import net.minecraft.core.world.chunk.provider.IChunkProvider;
+
+import java.io.File;
+
+public class DummyMinecraft implements MinecraftAccessor {
+    public File getMinecraftDir() {
+        return Minecraft.getAppDir("minecraft-bta");
+    }
+
+    public IChunkProvider createChunkProvider(World world, IChunkLoader chunkLoader) {
+        return new ChunkProviderStatic(world, chunkLoader, world.getWorldType().createChunkGenerator(world));
+    }
+
+    public int getAutosaveTimer() {
+        return 0;
+    }
+
+    public SkinVariantList getSkinVariantList() {
+        return null;
+    }
+
+    public String getMinecraftVersion() {
+        return null;
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/bta/worldloader/ChunkLoader.java b/src/main/java/org/useless/seedviewer/bta/worldloader/ChunkLoader.java
new file mode 100644
index 000000000..1060f5454
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/bta/worldloader/ChunkLoader.java
@@ -0,0 +1,114 @@
+package org.useless.seedviewer.bta.worldloader;
+
+import com.mojang.logging.LogUtils;
+import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.NbtIo;
+import net.minecraft.core.world.World;
+import net.minecraft.core.world.chunk.Chunk;
+import net.minecraft.core.world.chunk.ChunkLoaderLegacy;
+import net.minecraft.core.world.chunk.reader.ChunkReader;
+import net.minecraft.core.world.chunk.reader.ChunkReaderLegacy;
+import net.minecraft.core.world.chunk.reader.ChunkReaderVersion1;
+import net.minecraft.core.world.chunk.reader.ChunkReaderVersion2;
+import net.minecraft.core.world.save.mcregion.RegionFileCache;
+import org.slf4j.Logger;
+import org.useless.seedviewer.collections.ChunkLocation;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Map;
+
+public class ChunkLoader {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private static final World dummyWorld = new World();
+    private final File dimensionDir;
+    public ChunkLoader(File worldFolder, int dimension) {
+        this.dimensionDir = new File(worldFolder, "dimensions/" + dimension);
+    }
+
+    public boolean chunkExists(ChunkLocation location) {
+        DataInputStream regionStream = RegionFileCache.getChunkInputStream(dimensionDir, location.x, location.z);
+        CompoundTag tag;
+        if(regionStream != null)
+        {
+            try {
+                tag = NbtIo.read(regionStream);
+            } catch (IOException e) {
+                LOGGER.error("Failed to read tag for location {}, {}", location.x, location.z, e);
+                return false;
+            }
+        }
+        else
+        {
+            return false;
+        }
+        return tag.containsKey("Level");
+    }
+
+    public Chunk loadChunk(ChunkLocation location) throws IOException {
+        DataInputStream regionStream = RegionFileCache.getChunkInputStream(dimensionDir, location.x, location.z);
+        CompoundTag tag;
+        if(regionStream != null)
+        {
+            tag = NbtIo.read(regionStream);
+        }
+        else
+        {
+            return null;
+        }
+        if(!tag.containsKey("Level"))
+        {
+            LOGGER.error("Chunk file at {},{} is missing level data, skipping", location.x, location.z);
+            return null;
+        }
+        return loadChunkFromCompound(tag.getCompound("Level"));
+    }
+
+    public static Chunk loadChunkFromCompound(CompoundTag tag) {
+        int version = tag.getIntegerOrDefault("Version", -1);
+        ChunkReader reader = getChunkReaderByVersion(tag, version);
+        int x = reader.getX();
+        int z = reader.getZ();
+        Chunk chunk = new Chunk(dummyWorld, x, z);
+        chunk.heightMap = reader.getHeightMap();
+        chunk.averageBlockHeight = reader.getAverageBlockHeight();
+        chunk.isTerrainPopulated = reader.getIsTerrainPopulated();
+        chunk.temperature = reader.getTemperatureMap();
+        chunk.humidity = reader.getHumidityMap();
+        Map<Integer, String> biomeRegistry = reader.getBiomeRegistry();
+
+        for(int i = 0; i < Chunk.CHUNK_SECTIONS; ++i) {
+            ChunkLoaderLegacy.loadChunkSectionFromCompound(chunk.getSection(i), reader, biomeRegistry);
+        }
+
+        if (chunk.heightMap == null) {
+            chunk.heightMap = new short[256];
+            chunk.recalcHeightmap();
+        }
+
+        if (chunk.temperature == null || chunk.temperature.length == 0) {
+            chunk.temperature = new double[256];
+            Arrays.fill(chunk.temperature, Double.NEGATIVE_INFINITY);
+        }
+
+        if (chunk.humidity == null || chunk.humidity.length == 0) {
+            chunk.humidity = new double[256];
+            Arrays.fill(chunk.humidity, Double.NEGATIVE_INFINITY);
+        }
+
+        return chunk;
+    }
+    private static ChunkReader getChunkReaderByVersion(CompoundTag tag, int version) {
+        switch (version) {
+            case 1:
+                return new ChunkReaderVersion1(null, tag);
+            case 2:
+                return new ChunkReaderVersion2(null, tag);
+            default:
+                return new ChunkReaderLegacy(null, tag);
+        }
+    }
+
+}
diff --git a/src/main/java/org/useless/seedviewer/bta/worldloader/DimensionDataLoader.java b/src/main/java/org/useless/seedviewer/bta/worldloader/DimensionDataLoader.java
new file mode 100644
index 000000000..cb7a5026c
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/bta/worldloader/DimensionDataLoader.java
@@ -0,0 +1,63 @@
+package org.useless.seedviewer.bta.worldloader;
+
+import com.mojang.logging.LogUtils;
+import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.NbtIo;
+import net.minecraft.core.world.save.DimensionData;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.Objects;
+
+public class DimensionDataLoader {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    @Nullable
+    public static DimensionData getDimensionData(@NotNull File worldDir, int dimensionId) {
+        Objects.requireNonNull(worldDir, "WorldDir must not be null!");
+        CompoundTag tag = getDimensionDataRaw(worldDir, dimensionId);
+        if (tag == null) return null;
+        return new DimensionData(tag);
+    }
+
+    @Nullable
+    public static CompoundTag getDimensionDataRaw(@NotNull File worldDir, int dimensionId)
+    {
+        if(!worldDir.exists())
+        {
+            return null;
+        }
+        File dimensionsDir = new File(worldDir, "dimensions");
+        File dimensionDir = new File(dimensionsDir, "" + dimensionId);
+        File dimensionDat = new File(dimensionDir, "dimension.dat");
+        if (dimensionDat.exists())
+        {
+            try
+            {
+                CompoundTag nbtRoot = NbtIo.readCompressed(Files.newInputStream(dimensionDat.toPath()));
+                return nbtRoot.getCompound("Data");
+            }
+            catch (Exception ex)
+            {
+                LOGGER.error("Error parsing 'dimension.dat' in '{}' dimension {}", worldDir, dimensionId, ex);
+            }
+        }
+        dimensionDat = new File(dimensionDir, "dimension.dat_old");
+        if (dimensionDat.exists())
+        {
+            try
+            {
+                CompoundTag oldNbtRoot = NbtIo.readCompressed(Files.newInputStream(dimensionDat.toPath()));
+                return oldNbtRoot.getCompound("Data");
+            }
+            catch (Exception ex)
+            {
+                LOGGER.error("Error parsing 'dimension.dat_old' in '{}' dimension {}", worldDir, dimensionId, ex);
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/bta/worldloader/LevelDataLoader.java b/src/main/java/org/useless/seedviewer/bta/worldloader/LevelDataLoader.java
new file mode 100644
index 000000000..991d09397
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/bta/worldloader/LevelDataLoader.java
@@ -0,0 +1,63 @@
+package org.useless.seedviewer.bta.worldloader;
+
+import com.mojang.logging.LogUtils;
+import com.mojang.nbt.CompoundTag;
+import com.mojang.nbt.NbtIo;
+import net.minecraft.core.world.save.LevelData;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.Objects;
+
+public class LevelDataLoader {
+    private static final Logger LOGGER = LogUtils.getLogger();
+
+    @Nullable
+    public static LevelData getLevelData(@NotNull File worldDir)
+    {
+        Objects.requireNonNull(worldDir, "WorldDir must not be null!");
+        CompoundTag tag = getLevelDataRaw(worldDir);
+        if (tag == null) return null;
+        return new LevelData(tag);
+    }
+
+    @Nullable
+    public static CompoundTag getLevelDataRaw(@NotNull File worldDir)
+    {
+        Objects.requireNonNull(worldDir, "WorldDir must not be null!");
+        if(!worldDir.exists())
+        {
+            return null;
+        }
+        File worldLevelDat = new File(worldDir, "level.dat");
+        if(worldLevelDat.exists())
+        {
+            try
+            {
+                CompoundTag nbtRoot = NbtIo.readCompressed(Files.newInputStream(worldLevelDat.toPath()));
+                return nbtRoot.getCompound("Data");
+            }
+            catch(Exception ex)
+            {
+                LOGGER.error("Error parsing 'level.dat' in '{}'", worldDir, ex);
+            }
+        }
+        worldLevelDat = new File(worldDir, "level.dat_old");
+        if(worldLevelDat.exists())
+        {
+            try
+            {
+                CompoundTag oldNbtRoot = NbtIo.readCompressed(Files.newInputStream(worldLevelDat.toPath()));
+                return oldNbtRoot.getCompound("Data");
+            }
+            catch(Exception ex)
+            {
+                LOGGER.error("Error parsing 'level.dat_old' in '{}'", worldDir, ex);
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/collections/BlockPos2D.java b/src/main/java/org/useless/seedviewer/collections/BlockPos2D.java
new file mode 100644
index 000000000..20a2bba7b
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/collections/BlockPos2D.java
@@ -0,0 +1,34 @@
+package org.useless.seedviewer.collections;
+
+import java.util.Objects;
+
+public class BlockPos2D {
+    public final int x;
+    public final int z;
+
+    public BlockPos2D(int x, int z) {
+        this.x = x;
+        this.z = z;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        BlockPos2D blockPos2D = (BlockPos2D) o;
+        return x == blockPos2D.x && z == blockPos2D.z;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(x, z);
+    }
+
+    @Override
+    public String toString() {
+        return "BlockPos3D{" +
+            "x=" + x +
+            ", z=" + z +
+            '}';
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/collections/BlockPos3D.java b/src/main/java/org/useless/seedviewer/collections/BlockPos3D.java
new file mode 100644
index 000000000..3fcbff2f7
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/collections/BlockPos3D.java
@@ -0,0 +1,37 @@
+package org.useless.seedviewer.collections;
+
+import java.util.Objects;
+
+/**
+ * Block coordinates of a position relative to the world
+ */
+public final class BlockPos3D extends BlockPos2D {
+    public final int y;
+
+    public BlockPos3D(int x, int y, int z) {
+        super(x, z);
+        this.y = y;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        BlockPos3D blockPos3D = (BlockPos3D) o;
+        return x == blockPos3D.x && y == blockPos3D.y && z == blockPos3D.z;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(x, y, z);
+    }
+
+    @Override
+    public String toString() {
+        return "BlockPos3D{" +
+            "x=" + x +
+            ", y=" + y +
+            ", z=" + z +
+            '}';
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/collections/ChunkLocation.java b/src/main/java/org/useless/seedviewer/collections/ChunkLocation.java
new file mode 100644
index 000000000..373ae718c
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/collections/ChunkLocation.java
@@ -0,0 +1,37 @@
+package org.useless.seedviewer.collections;
+
+import java.util.Objects;
+
+/**
+ * Chunk coordinates of a chunk in the world
+ */
+public final class ChunkLocation {
+    public final int x;
+    public final int z;
+
+    public ChunkLocation(int x, int z) {
+        this.x = x;
+        this.z = z;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ChunkLocation that = (ChunkLocation) o;
+        return x == that.x && z == that.z;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(x, z);
+    }
+
+    @Override
+    public String toString() {
+        return "ChunkLocation{" +
+            "x=" + x +
+            ", z=" + z +
+            '}';
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/collections/ChunkPos2D.java b/src/main/java/org/useless/seedviewer/collections/ChunkPos2D.java
new file mode 100644
index 000000000..13c13f016
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/collections/ChunkPos2D.java
@@ -0,0 +1,48 @@
+package org.useless.seedviewer.collections;
+
+import org.useless.seedviewer.data.Chunk;
+
+import java.util.Objects;
+
+public class ChunkPos2D {
+    public final int x;
+    public final int z;
+
+    public ChunkPos2D(int x, int z) {
+        if (x < 0) {
+            throw new IllegalArgumentException("X must be between in range [0, " + Chunk.CHUNK_SIZE_X + "]!");
+        }
+        if (x > Chunk.CHUNK_SIZE_X) {
+            throw new IllegalArgumentException("X must be between in range [0, " + Chunk.CHUNK_SIZE_X + "]!");
+        }
+        if (z < 0) {
+            throw new IllegalArgumentException("Z must be between in range [0, " + Chunk.CHUNK_SIZE_Z + "]!");
+        }
+        if (z > Chunk.CHUNK_SIZE_Z) {
+            throw new IllegalArgumentException("Z must be between in range [0, " + Chunk.CHUNK_SIZE_Z + "]!");
+        }
+        this.x = x;
+        this.z = z;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ChunkPos2D that = (ChunkPos2D) o;
+        return x == that.x && z == that.z;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(x, z);
+    }
+
+    @Override
+    public String toString() {
+        return "ChunkPos3D{" +
+            "x=" + x +
+            ", z=" + z +
+            '}';
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/collections/ChunkPos3D.java b/src/main/java/org/useless/seedviewer/collections/ChunkPos3D.java
new file mode 100644
index 000000000..48100c7ab
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/collections/ChunkPos3D.java
@@ -0,0 +1,45 @@
+package org.useless.seedviewer.collections;
+
+import org.useless.seedviewer.data.Chunk;
+
+import java.util.Objects;
+
+/**
+ * Block coordinates of a position relative to a chunk
+ */
+public final class ChunkPos3D extends ChunkPos2D {
+    public final int y;
+
+    public ChunkPos3D(int x, int y, int z) {
+        super(x, z);
+        if (y < 0) {
+            throw new IllegalArgumentException("Y must be between in range [0, " + Chunk.CHUNK_SIZE_Y + "]!");
+        }
+        if (y > Chunk.CHUNK_SIZE_Y) {
+            throw new IllegalArgumentException("Y must be between in range [0, " + Chunk.CHUNK_SIZE_Y + "]!");
+        }
+        this.y = y;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ChunkPos3D that = (ChunkPos3D) o;
+        return x == that.x && y == that.y && z == that.z;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(x, y, z);
+    }
+
+    @Override
+    public String toString() {
+        return "ChunkPos3D{" +
+            "x=" + x +
+            ", y=" + y +
+            ", z=" + z +
+            '}';
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/collections/NamespaceID.java b/src/main/java/org/useless/seedviewer/collections/NamespaceID.java
new file mode 100644
index 000000000..e83a58a17
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/collections/NamespaceID.java
@@ -0,0 +1,72 @@
+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/src/main/java/org/useless/seedviewer/collections/ObjectWrapper.java b/src/main/java/org/useless/seedviewer/collections/ObjectWrapper.java
new file mode 100644
index 000000000..6ad6bcbe0
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/collections/ObjectWrapper.java
@@ -0,0 +1,55 @@
+package org.useless.seedviewer.collections;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class ObjectWrapper<T> {
+    protected List<ValueListener<T>> listeners = new ArrayList<>();
+    protected T value;
+    public ObjectWrapper(T initialValue) {
+        this.value = initialValue;
+    }
+
+    public void set(T value) {
+        this.value = value;
+        for (ValueListener<T> listener : listeners) {
+            listener.onValueChanged(value);
+        }
+    }
+
+    public T get() {
+        return value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ObjectWrapper<?> that = (ObjectWrapper<?>) o;
+        return Objects.equals(value, that.value);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(value);
+    }
+
+    @Override
+    public String toString() {
+        if (value == null) return "null";
+        return value.toString();
+    }
+
+    public ObjectWrapper<T> addChangeListener(@NotNull ValueListener<T> listener) {
+        Objects.requireNonNull(listener);
+        listeners.add(listener);
+        return this;
+    }
+
+    public interface ValueListener<T> {
+        void onValueChanged(T newValue);
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/data/Biome.java b/src/main/java/org/useless/seedviewer/data/Biome.java
new file mode 100644
index 000000000..57b70c018
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/data/Biome.java
@@ -0,0 +1,9 @@
+package org.useless.seedviewer.data;
+
+import org.useless.seedviewer.collections.NamespaceID;
+
+public interface Biome {
+    String getName();
+    NamespaceID getID();
+    int getColor();
+}
diff --git a/src/main/java/org/useless/seedviewer/data/Chunk.java b/src/main/java/org/useless/seedviewer/data/Chunk.java
new file mode 100644
index 000000000..b3d54c63f
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/data/Chunk.java
@@ -0,0 +1,17 @@
+package org.useless.seedviewer.data;
+
+import net.minecraft.core.world.chunk.ChunkSection;
+import org.useless.seedviewer.collections.ChunkPos2D;
+import org.useless.seedviewer.collections.ChunkPos3D;
+
+import java.awt.*;
+
+public interface Chunk {
+    int CHUNK_SIZE_X = net.minecraft.core.world.chunk.Chunk.CHUNK_SIZE_X;
+    int CHUNK_SIZE_Y = net.minecraft.core.world.chunk.Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y;
+    int CHUNK_SIZE_Z = net.minecraft.core.world.chunk.Chunk.CHUNK_SIZE_Z;
+    Biome getBiome(ChunkPos3D pos);
+    int getBlockColor(ChunkPos3D pos);
+    int getHeight(ChunkPos2D pos);
+    int getWaterDepth(ChunkPos2D pos);
+}
diff --git a/src/main/java/org/useless/seedviewer/data/World.java b/src/main/java/org/useless/seedviewer/data/World.java
new file mode 100644
index 000000000..0bfb5c442
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/data/World.java
@@ -0,0 +1,13 @@
+package org.useless.seedviewer.data;
+
+import org.useless.seedviewer.gui.ChunkProvider;
+
+import java.io.File;
+
+public interface World {
+    File getFolder();
+    long getSeed();
+    String getName();
+    long getLastPlayed();
+    ChunkProvider getChunkProvider();
+}
diff --git a/src/main/java/org/useless/seedviewer/gui/ChunkProvider.java b/src/main/java/org/useless/seedviewer/gui/ChunkProvider.java
new file mode 100644
index 000000000..8493502e4
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/gui/ChunkProvider.java
@@ -0,0 +1,9 @@
+package org.useless.seedviewer.gui;
+
+import org.useless.seedviewer.collections.ChunkLocation;
+import org.useless.seedviewer.data.Biome;
+import org.useless.seedviewer.data.Chunk;
+
+public interface ChunkProvider {
+    Chunk getChunk(ChunkLocation location);
+}
diff --git a/src/main/java/org/useless/seedviewer/gui/ChunkView.java b/src/main/java/org/useless/seedviewer/gui/ChunkView.java
new file mode 100644
index 000000000..7f330651c
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/gui/ChunkView.java
@@ -0,0 +1,170 @@
+package org.useless.seedviewer.gui;
+
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
+import org.useless.seedviewer.collections.ChunkLocation;
+import org.useless.seedviewer.collections.ChunkPos2D;
+import org.useless.seedviewer.collections.ChunkPos3D;
+import org.useless.seedviewer.data.Biome;
+import org.useless.seedviewer.data.Chunk;
+import org.useless.seedviewer.gui.components.Viewport;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+public class ChunkView {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private static final ExecutorService InitializerService = Executors.newFixedThreadPool(10);
+    private static final ExecutorService PostProcessorService = Executors.newFixedThreadPool(10);
+
+    private final BufferedImage biomeMapImage = new BufferedImage(Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, BufferedImage.TYPE_INT_ARGB);
+    private final BufferedImage terrainMapImage = new BufferedImage(Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, BufferedImage.TYPE_INT_ARGB);
+    private final BufferedImage heightMapImage = new BufferedImage(Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, BufferedImage.TYPE_INT_ARGB);
+    private final BufferedImage waterDepthMapImage = new BufferedImage(Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, BufferedImage.TYPE_INT_ARGB);
+
+    private final Rectangle bounds;
+    private final ChunkLocation location;
+    private final ChunkProvider provider;
+    private final Viewport viewport;
+
+    public long lastSeenTime = System.currentTimeMillis();
+
+    private Future<?> loadTask;
+    private Future<?> processTask = null;
+
+    private boolean hasInitialized = false;
+    private volatile boolean hasPostProcessed = false;
+
+    public ChunkView(Viewport viewport, ChunkLocation location, ChunkProvider provider) {
+        this.viewport = viewport;
+        this.location = location;
+        this.provider = provider;
+        this.bounds = new Rectangle(location.x * Chunk.CHUNK_SIZE_X, location.z * Chunk.CHUNK_SIZE_Z, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z);
+
+        loadTask = InitializerService.submit(
+            () -> {
+                try {
+                    Chunk chunk = provider.getChunk(location);
+
+                    for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
+                        for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
+                            ChunkPos2D pos2D = new ChunkPos2D(x, z);
+                            int h = chunk.getHeight(pos2D) - 1;
+                            if (h < 0) h = 0;
+                            heightMapImage.setRGB(x, z, h & 0xFF);
+
+                            int wd = chunk.getWaterDepth(pos2D) & 0xFF;
+                            waterDepthMapImage.setRGB(x, z, 0xFF_00_00_00 | wd << 16 | wd << 8 | wd);
+
+                            Biome b = chunk.getBiome(new ChunkPos3D(x, h, z));
+                            biomeMapImage.setRGB(x, z, b.getColor() | 0x80_00_00_00);
+
+                            terrainMapImage.setRGB(x, z, chunk.getBlockColor(new ChunkPos3D(x, h, z)));
+                        }
+                    }
+                } catch (Exception e) {
+                    LOGGER.error("Error when initializing chunk {}, {}", location.x, location.z, e);
+                }
+                finally {
+                    hasInitialized = true;
+                }
+            }
+        );
+    }
+
+    public boolean hasInit() {
+        return hasInitialized;
+    }
+
+    public boolean hasProcessed() {
+        return hasPostProcessed;
+    }
+
+    public void process(ChunkView posZ) {
+        if (hasProcessed()) return;
+        synchronized (this) {
+            processTask = PostProcessorService.submit(() -> {
+                try {
+                    for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
+                        for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
+                            int depth = waterDepthMapImage.getRGB(x, z) & 0xFF;
+
+                            int shade = 220;
+                            if (depth == 0) {
+                                int lastHeight;
+                                if (z == 0) {
+                                    lastHeight = posZ.getHeightMapImage().getRGB(x, z + 15) & 0xFF;
+                                } else {
+                                    lastHeight = heightMapImage.getRGB(x, z - 1) & 0xFF;
+                                }
+                                int height = heightMapImage.getRGB(x, z) & 0xFF;
+
+                                if (height == lastHeight) {
+                                    shade = 220;
+                                } else if (height < lastHeight) {
+                                    shade = 180;
+                                } else {
+                                    shade = 255;
+                                }
+                            } else {
+                                double d3 = (double) depth * 0.1D + (double) ((x + z) & 0b1) * 0.2D;
+                                if(d3 < 0.5D) {
+                                    shade = 255;
+                                } else if (d3 > 0.9D) {
+                                    shade = 180;
+                                } else {
+                                    shade = 220;
+                                }
+                            }
+
+
+                            if (shade != 255) {
+                                final int current = terrainMapImage.getRGB(x, z) ;
+                                final int a = (((current >> 24) & 0xFF));
+                                final int r = (((current >> 16) & 0xFF) * shade) / 0xFF;
+                                final int g = (((current >>  8) & 0xFF) * shade) / 0xFF;
+                                final int b = (((current      ) & 0xFF) * shade) / 0xFF;
+                                terrainMapImage.setRGB(x, z, (a << 24 | r << 16 | g << 8 | b));
+                            }
+                        }
+                    }
+                } finally {
+                    hasPostProcessed = true;
+                    viewport.repaint();
+                }
+            });
+        }
+    }
+
+    public ChunkLocation getLocation() {
+        return location;
+    }
+
+    public BufferedImage getBiomeMapImage() {
+        return biomeMapImage;
+    }
+
+    public BufferedImage getTerrainMapImage() {
+        return terrainMapImage;
+    }
+
+    public BufferedImage getHeightMapImage() {
+        return heightMapImage;
+    }
+
+    public Rectangle getWorldBounds() {
+        return bounds;
+    }
+
+    public void kill() {
+        if (processTask != null) {
+            processTask.cancel(true);
+        }
+        if (loadTask != null) {
+            loadTask.cancel(true);
+        }
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/gui/SeedViewer.java b/src/main/java/org/useless/seedviewer/gui/SeedViewer.java
new file mode 100644
index 000000000..9ebbd4b00
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/gui/SeedViewer.java
@@ -0,0 +1,184 @@
+package org.useless.seedviewer.gui;
+
+import com.mojang.logging.LogUtils;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.useless.seedviewer.SeedViewerMain;
+import org.useless.seedviewer.collections.ChunkLocation;
+import org.useless.seedviewer.gui.components.InfoPanel;
+import org.useless.seedviewer.gui.components.InputPanel;
+import org.useless.seedviewer.gui.components.Viewport;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+
+public class SeedViewer extends JFrame {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    // Static Configuration
+    public static final int TICKS_PER_SECOND = 10;
+    public static final int BEZEL = 15;
+
+    // Storage
+    public final Properties launchProperties;
+    private volatile boolean needsResize = true;
+
+    // Configuration
+
+    // Components
+    public final Viewport viewport;
+    public final InputPanel inputPanel;
+    public final InfoPanel infoPanel;
+
+    public SeedViewer(Properties properties) {
+        LOGGER.info("Starting Seed Viewer!");
+        this.launchProperties = properties;
+
+        viewport = new Viewport(this);
+        inputPanel = new InputPanel(this);
+        infoPanel = new InfoPanel(this);
+
+
+        initFrame();
+        addComponents();
+
+        Thread mainThread = new Thread(
+            () -> {
+                long tickCount = 0;
+                while (true) {
+                    try {
+                        tick();
+                        tickCount++;
+                    } catch (Exception e){
+                        LOGGER.error("Exception when running tick!", e);
+                    }
+
+                    if (tickCount % (5 * TICKS_PER_SECOND) == 0) {
+                        System.gc();
+                    }
+
+                    try {
+                        Thread.sleep(1000/TICKS_PER_SECOND);
+                    } catch (InterruptedException e) {
+                        LOGGER.error("Unexpected interrupt in tick thread!", e);
+                    }
+                }
+            }
+        );
+        mainThread.setName("Main");
+        mainThread.setPriority(6);
+        mainThread.start();
+    }
+
+    public void initFrame() {
+        // Creating instance of JFrame
+        LOGGER.info("Initializing Frame");
+        this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+        this.setTitle("BTA Seed Viewer! Version: " + SeedViewerMain.VERSION);
+        this.setSize(960, 720);
+        this.setMinimumSize(new Dimension(480, 360));
+        this.setResizable(true);
+        this.addComponentListener(new ComponentAdapter() {
+            @Override
+            public void componentResized(ComponentEvent e) {
+                needsResize = true;
+                viewport.repaint();
+            }
+        });
+        this.setLayout(null); // using no layout managers
+        this.setVisible(true); // making the frame visible
+
+        LOGGER.info("Loading Icons");
+        try {
+            List<Image> l = new ArrayList<>();
+            l.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/assets/seedviewer/textures/icons/1024.png")));
+            l.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/assets/seedviewer/textures/icons/512.png")));
+            l.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/assets/seedviewer/textures/icons/256.png")));
+            l.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/assets/seedviewer/textures/icons/128.png")));
+            l.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/assets/seedviewer/textures/icons/64.png")));
+            l.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/assets/seedviewer/textures/icons/32.png")));
+            l.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/assets/seedviewer/textures/icons/16.png")));
+            this.setIconImages(l);
+        } catch (Exception e) {
+            LOGGER.error("Failed to load icons!", e);
+        }
+    }
+
+    public void addComponents() {
+        // State labels
+        LOGGER.info("Creating Labels");
+        infoPanel.setup();
+        this.add(infoPanel);
+
+        // Checkboxes
+        LOGGER.info("Creating Check boxes");
+        inputPanel.setup();
+        this.add(inputPanel);
+
+        LOGGER.info("Creating Image frame");
+        viewport.setup();
+        this.add(viewport);
+    }
+
+    public void initComponents() {
+        if (!needsResize) return;
+        LOGGER.info("Initializing Components");
+        needsResize = false;
+        int screenWidth = this.getContentPane().getWidth();
+        int screenHeight = this.getContentPane().getHeight();
+
+        {
+            int inWidth = screenWidth / 4;
+            if (inWidth < 100) inWidth = 100;
+            if (inWidth > 200) inWidth = 200;
+            int inHeight = screenHeight - BEZEL * 2;
+            inputPanel.onResize(new Rectangle(0, BEZEL, inWidth, inHeight/2));
+            inputPanel.setVisible(true);
+        }
+
+        {
+            int inWidth = screenWidth / 4;
+            if (inWidth < 100) inWidth = 100;
+            if (inWidth > 200) inWidth = 200;
+            int inHeight = screenHeight - BEZEL * 2;
+            infoPanel.onResize(new Rectangle(0, inputPanel.getY() + inputPanel.getHeight() - 1, inWidth, inHeight/2));
+            infoPanel.setVisible(true);
+        }
+
+        {
+            int viewWidth = screenWidth - (BEZEL * 2) - (inputPanel.isVisible() ? inputPanel.getWidth() : 0);
+            int viewX = BEZEL + (inputPanel.isVisible() ? inputPanel.getWidth() : 0);
+            viewport.onResize(
+                new Rectangle(
+                    viewX,
+                    BEZEL,
+                    viewWidth,
+                    screenHeight - BEZEL * 2));
+        }
+    }
+
+    public void queueResize() {
+        needsResize = true;
+    }
+
+    public void forceResize() {
+        queueResize();
+        initComponents();
+    }
+
+    public synchronized void tick() {
+        initComponents();
+        viewport.tick();
+    }
+
+    public static boolean isSlimeChunk(long worldSeed, @NotNull ChunkLocation location) {
+        long slimeXOR = 0x3AD8025FL;
+        Random slimerandom = new Random(worldSeed + (location.x * location.x * 0x4c1906L) + (location.x * 0x5ac0dbL) + (location.z * location.z * 0x4307a7L) + (location.z * 0x5f24fL) ^ slimeXOR);
+        return slimerandom.nextInt(10) == 0;
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/gui/components/InfoPanel.java b/src/main/java/org/useless/seedviewer/gui/components/InfoPanel.java
new file mode 100644
index 000000000..de52b10a1
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/gui/components/InfoPanel.java
@@ -0,0 +1,166 @@
+package org.useless.seedviewer.gui.components;
+
+import net.minecraft.core.Global;
+import org.useless.seedviewer.data.Biome;
+import org.useless.seedviewer.gui.SeedViewer;
+
+import javax.swing.*;
+import javax.swing.border.LineBorder;
+import java.awt.*;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class InfoPanel extends JPanel {
+    private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss");
+    private final SeedViewer seedViewer;
+    public JLabel titleLabel;
+
+    public JLabel btaLabel;
+    public JLabel seedLabel;
+    public JLabel viewLabel;
+    public JLabel zoomLabel;
+    public JLabel biomeLabel;
+
+    public JLabel worldNameLabel;
+    public JLabel worldSeedLabel;
+    public JLabel worldPlayedLabel;
+
+    public List<Component> resizeList = new ArrayList<>();
+
+    public InfoPanel(SeedViewer seedViewer) {
+        this.seedViewer = seedViewer;
+        this.setLayout(null);
+        this.setBorder(new LineBorder(Color.BLACK, 1));
+    }
+
+    public void setup() {
+        final int textHeight = 15;
+
+        titleLabel = new JLabel("Information: ");
+        titleLabel.setSize(0, textHeight);
+        this.add(titleLabel);
+
+        try {
+            Class.forName("net.minecraft.core.Global");
+            btaLabel = new JLabel("BTA Version: " + Global.VERSION);
+        } catch (ClassNotFoundException e) {
+            btaLabel = new JLabel("BTA Version: Missing!");
+        }
+        add(btaLabel);
+        resizeList.add(btaLabel);
+
+        seedLabel = new JLabel("Seed: " + seedViewer.viewport.seed);
+        seedLabel.setSize(0, textHeight);
+        seedViewer.viewport.seed.addChangeListener(newValue -> seedLabel.setText("Seed: " + seedViewer.viewport.seed));
+
+        viewLabel = new JLabel(String.format("View: X:%s, Z:%s", seedViewer.viewport.viewX, seedViewer.viewport.viewZ));
+        viewLabel.setSize(0, textHeight);
+        seedViewer.viewport.viewX.addChangeListener(newValue -> viewLabel.setText(String.format("View: X:%.2f, Z:%.2f", seedViewer.viewport.viewX.get(), seedViewer.viewport.viewZ.get())));
+        seedViewer.viewport.viewX.addChangeListener(newValue -> {
+            Biome b = seedViewer.viewport.getHoveredBiome();
+            if (b == null) {
+                biomeLabel.setText("Biome: null");
+            } else {
+                biomeLabel.setText(String.format("Biome: %s", b.getName()));
+            }
+        });
+        seedViewer.viewport.viewZ.addChangeListener(newValue -> viewLabel.setText(String.format("View: X:%.2f, Z:%.2f", seedViewer.viewport.viewX.get(), seedViewer.viewport.viewZ.get())));
+        seedViewer.viewport.viewZ.addChangeListener(newValue -> {
+            Biome b = seedViewer.viewport.getHoveredBiome();
+            if (b == null) {
+                biomeLabel.setText("Biome: null");
+            } else {
+                biomeLabel.setText(String.format("Biome: %s", b.getName()));
+            }
+        });
+
+        zoomLabel = new JLabel("Zoom: " + seedViewer.viewport.zoom);
+        zoomLabel.setSize(0, textHeight);
+        seedViewer.viewport.zoom.addChangeListener(newValue -> zoomLabel.setText("Zoom: " + seedViewer.viewport.zoom));
+
+        biomeLabel = new JLabel("Biome: None");
+        biomeLabel.setSize(0, textHeight);
+
+        worldNameLabel = new JLabel();
+        worldNameLabel.setSize(0, textHeight);
+        seedViewer.viewport.world.addChangeListener(newValue -> worldNameLabel.setText("World: " + (seedViewer.viewport.world.get() == null ? "null" : seedViewer.viewport.world.get().getName())));
+        seedViewer.viewport.world.addChangeListener(newValue -> {
+            if (newValue != null) {
+                onWorldOpen();
+                seedViewer.queueResize();
+            } else {
+                onWorldClose();
+                seedViewer.queueResize();
+            }
+        });
+
+        worldSeedLabel = new JLabel();
+        worldSeedLabel.setSize(0, textHeight);
+        seedViewer.viewport.world.addChangeListener(newValue -> worldSeedLabel.setText("Seed: " + (seedViewer.viewport.world.get() == null ? "null" : seedViewer.viewport.world.get().getSeed())));
+
+        worldPlayedLabel = new JLabel();
+        worldPlayedLabel.setSize(0, textHeight);
+        seedViewer.viewport.world.addChangeListener(newValue -> worldPlayedLabel.setText("Last Played: " + (seedViewer.viewport.world.get() == null ? "?" : DateFormat.getDateTimeInstance().format(new Date(seedViewer.viewport.world.get().getLastPlayed())))));
+
+        addManaged(seedLabel);
+        addManaged(viewLabel);
+        addManaged(zoomLabel);
+        addManaged(biomeLabel);
+        addManaged(worldNameLabel);
+        addManaged(worldSeedLabel);
+        addManaged(worldPlayedLabel);
+
+        if (seedViewer.viewport.world.get() == null) {
+            onWorldClose();
+        } else {
+            onWorldOpen();
+        }
+    }
+
+    public void addManaged(Component c) {
+        add(c);
+        resizeList.add(c);
+    }
+
+    public void onWorldOpen() {
+        worldNameLabel.setEnabled(true);
+        worldNameLabel.setVisible(true);
+        worldSeedLabel.setEnabled(true);
+        worldSeedLabel.setVisible(true);
+        worldPlayedLabel.setEnabled(true);
+        worldPlayedLabel.setVisible(true);
+
+        seedLabel.setEnabled(false);
+        seedLabel.setVisible(false);
+    }
+
+    public void onWorldClose() {
+        worldNameLabel.setEnabled(false);
+        worldNameLabel.setVisible(false);
+        worldSeedLabel.setEnabled(false);
+        worldSeedLabel.setVisible(false);
+        worldPlayedLabel.setEnabled(false);
+        worldPlayedLabel.setVisible(false);
+
+        seedLabel.setEnabled(true);
+        seedLabel.setVisible(true);
+    }
+
+    public void onResize(Rectangle newDimensions) {
+        setBounds(newDimensions.x, newDimensions.y, newDimensions.width, newDimensions.height);
+
+        final int edgePad = 5;
+        final int elementPad = 2;
+        titleLabel.setBounds(edgePad, edgePad, newDimensions.width - edgePad * 2, titleLabel.getHeight());
+
+        int lastY = titleLabel.getY() + titleLabel.getHeight() + edgePad * 2;
+        for (Component c : resizeList) {
+            if (!c.isVisible()) continue;
+            c.setBounds(edgePad, lastY, newDimensions.width - edgePad * 2, c.getHeight());
+            lastY += c.getHeight() + elementPad;
+        }
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/gui/components/InputPanel.java b/src/main/java/org/useless/seedviewer/gui/components/InputPanel.java
new file mode 100644
index 000000000..ab3c9e65a
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/gui/components/InputPanel.java
@@ -0,0 +1,250 @@
+package org.useless.seedviewer.gui.components;
+
+import com.mojang.logging.LogUtils;
+import net.minecraft.core.Global;
+import org.slf4j.Logger;
+import org.useless.seedviewer.gui.SeedViewer;
+
+import javax.imageio.ImageIO;
+import javax.swing.*;
+import javax.swing.border.LineBorder;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class InputPanel extends JPanel {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss");
+    private final SeedViewer seedViewer;
+
+    public JLabel titleLabel;
+
+    public JCheckBox slimeChunksBox;
+    public JCheckBox showBordersBox;
+    public JCheckBox showBiomesBox;
+    public JCheckBox showTerrainBox;
+    public JCheckBox showCrosshairBox;
+    public JTextField seedInputBox;
+    public JButton screenshot;
+    public JButton openWorld;
+    public JButton closeWorld;
+
+    private final List<Component> resizeList = new ArrayList<>();
+
+    public InputPanel(SeedViewer seedViewer) {
+        this.seedViewer = seedViewer;
+        this.setLayout(null); // using no layout managers
+        this.setBorder(new LineBorder(Color.BLACK, 1));
+    }
+
+    public void setup() {
+        final int boxHeight = 15;
+        final int textHeight = 15;
+        final int textFieldHeight = 30;
+        final int button = 30;
+
+        titleLabel = new JLabel("User Controls: ");
+        titleLabel.setSize(0, textHeight);
+        this.add(titleLabel);
+
+        slimeChunksBox = new JCheckBox("Slime Chunks");
+        slimeChunksBox.setSize(0, boxHeight);
+        slimeChunksBox.setSelected(seedViewer.viewport.showSlimeChunks.get());
+        slimeChunksBox.addChangeListener(e -> seedViewer.viewport.showSlimeChunks.set(slimeChunksBox.isSelected()));
+        slimeChunksBox.addChangeListener(e -> seedViewer.viewport.repaint());
+
+        showBordersBox = new JCheckBox("Chunk Borders");
+        showBordersBox.setSize(0, boxHeight);
+        showBordersBox.setSelected(seedViewer.viewport.showChunkBorders.get());
+        showBordersBox.addChangeListener(e -> seedViewer.viewport.showChunkBorders.set(showBordersBox.isSelected()));
+        showBordersBox.addChangeListener(e -> seedViewer.viewport.repaint());
+
+        showBiomesBox = new JCheckBox("Show Biomes");
+        showBiomesBox.setSize(0, boxHeight);
+        showBiomesBox.setSelected(seedViewer.viewport.showBiomes.get());
+        showBiomesBox.addChangeListener(e -> seedViewer.viewport.showBiomes.set(showBiomesBox.isSelected()));
+        showBiomesBox.addChangeListener(e -> seedViewer.viewport.repaint());
+
+        showTerrainBox = new JCheckBox("Show Terrain");
+        showTerrainBox.setSize(0, boxHeight);
+        showTerrainBox.setSelected(seedViewer.viewport.showTerrain.get());
+        showTerrainBox.addChangeListener(e -> seedViewer.viewport.showTerrain.set(showTerrainBox.isSelected()));
+        showTerrainBox.addChangeListener(e -> seedViewer.viewport.repaint());
+
+        showCrosshairBox = new JCheckBox("Enable Cross-hair");
+        showCrosshairBox.setSize(0, boxHeight);
+        showCrosshairBox.setSelected(seedViewer.viewport.showCrosshair.get());
+        showCrosshairBox.addChangeListener(e -> seedViewer.viewport.showCrosshair.set(showCrosshairBox.isSelected()));
+        showCrosshairBox.addChangeListener(e -> seedViewer.viewport.repaint());
+
+        addManaged(slimeChunksBox);
+        addManaged(showBordersBox);
+        addManaged(showBiomesBox);
+        addManaged(showTerrainBox);
+        addManaged(showCrosshairBox);
+
+        seedInputBox = new JTextField(seedViewer.viewport.seed.toString());
+        seedInputBox.setSize(0, textFieldHeight);
+        seedInputBox.addActionListener(new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                long boxSeed;
+                try {
+                    boxSeed = Long.parseLong(seedInputBox.getText());
+                } catch (NumberFormatException exception) {
+                    boxSeed = seedInputBox.getText().hashCode();
+                }
+                if (boxSeed != seedViewer.viewport.seed.get()) {
+                    seedViewer.viewport.setSeed(boxSeed);
+                }
+            }
+        });
+        addManaged(seedInputBox);
+
+        screenshot = new JButton("Save Screenshot");
+        screenshot.setSize(0, button);
+        screenshot.addActionListener(new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                final File screenShotFolder = new File(Global.accessor.getMinecraftDir(), "screenshots");
+                screenShotFolder.mkdirs();
+                JFileChooser screenShotSelect = new JFileChooser(screenShotFolder);
+
+                String name = "Seed-Viewer-" + dateFormat.format(new Date());
+                File defaultFile;
+                int k = 1;
+                while ((defaultFile = new File(screenShotFolder, name + (k != 1 ? "_" + k : "") + ".png")).exists()) {
+                    k++;
+                }
+
+                screenShotSelect.setSelectedFile(defaultFile);
+
+                screenShotSelect.setDialogTitle("Save Screenshot");
+                screenShotSelect.setApproveButtonText("Save");
+                screenShotSelect.setFileSelectionMode(JFileChooser.FILES_ONLY);
+                screenShotSelect.addChoosableFileFilter(new FileNameExtensionFilter("Image (*.png)", "png"));
+
+                screenShotSelect.setAcceptAllFileFilterUsed(true);
+
+                int result = screenShotSelect.showOpenDialog(seedViewer);
+                if (result == JFileChooser.APPROVE_OPTION) {
+                    File destFile = screenShotSelect.getSelectedFile();
+                    LOGGER.info("Selected file: {}", destFile.getAbsolutePath());
+
+                    BufferedImage viewportImage = new BufferedImage(seedViewer.viewport.getWidth(), seedViewer.viewport.getHeight(), BufferedImage.TYPE_INT_ARGB);
+                    Graphics g = viewportImage.getGraphics();
+                    seedViewer.viewport.paintToGraphics(g);
+                    g.dispose();
+
+                    LOGGER.info("Attempting to save screenshot to '{}'!", destFile);
+                    try {
+                        destFile.createNewFile();
+                        String[] dotSep = destFile.getName().split("\\.");
+                        ImageIO.write(viewportImage, dotSep[dotSep.length - 1], destFile);
+                    } catch (IOException ex) {
+                        LOGGER.error("Failed to save screenshot to '{}'!", destFile, ex);
+                    }
+
+                }
+            }
+        });
+        addManaged(screenshot);
+
+        openWorld = new JButton("Open World");
+        openWorld.setSize(0, button);
+        openWorld.addActionListener(new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                JFileChooser worldSelector = new JFileChooser(new File(Global.accessor.getMinecraftDir(), "saves/"));
+
+                worldSelector.setDialogTitle("Select World");
+                worldSelector.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+                worldSelector.setAcceptAllFileFilterUsed(false);
+
+                int result = worldSelector.showOpenDialog(seedViewer);
+                if (result == JFileChooser.APPROVE_OPTION) {
+                    File selectedFile = worldSelector.getSelectedFile();
+                    LOGGER.info("Selected file: {}", selectedFile.getAbsolutePath());
+                    seedViewer.viewport.setWorld(selectedFile);
+
+                } else {
+                    seedViewer.viewport.setWorld(null);
+                }
+            }
+        });
+        seedViewer.viewport.world.addChangeListener(newValue -> {
+            if (newValue != null) {
+                onWorldOpen();
+                seedViewer.queueResize();
+            } else {
+                onWorldClose();
+                seedViewer.queueResize();
+            }
+        });
+        addManaged(openWorld);
+
+        closeWorld = new JButton("Close World");
+        closeWorld.setSize(0, button);
+        closeWorld.addActionListener(new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                seedViewer.viewport.setWorld(null);
+            }
+        });
+        addManaged(closeWorld);
+
+        if (seedViewer.viewport.world.get() == null) {
+            onWorldClose();
+        } else {
+            onWorldOpen();
+        }
+    }
+
+    public void onWorldOpen() {
+        seedInputBox.setEnabled(false);
+        seedInputBox.setVisible(false);
+
+        closeWorld.setEnabled(true);
+        closeWorld.setVisible(true);
+        showTerrainBox.setEnabled(true);
+        showTerrainBox.setVisible(true);
+    }
+
+    public void onWorldClose() {
+        seedInputBox.setEnabled(true);
+        seedInputBox.setVisible(true);
+
+        closeWorld.setEnabled(false);
+        closeWorld.setVisible(false);
+        showTerrainBox.setEnabled(false);
+        showTerrainBox.setVisible(false);
+    }
+
+    public void addManaged(Component c) {
+        add(c);
+        resizeList.add(c);
+    }
+
+    public void onResize(Rectangle newDimensions) {
+        setBounds(newDimensions.x, newDimensions.y, newDimensions.width, newDimensions.height);
+
+        final int edgePad = 5;
+        final int elementPad = 2;
+        titleLabel.setBounds(edgePad, edgePad, newDimensions.width - edgePad * 2, titleLabel.getHeight());
+
+        int lastY = titleLabel.getY() + titleLabel.getHeight() + edgePad * 2;
+        for (Component c : resizeList) {
+            if (!c.isVisible()) continue;
+            c.setBounds(edgePad, lastY, newDimensions.width - edgePad * 2, c.getHeight());
+            lastY += c.getHeight() + elementPad;
+        }
+    }
+}
diff --git a/src/main/java/org/useless/seedviewer/gui/components/Viewport.java b/src/main/java/org/useless/seedviewer/gui/components/Viewport.java
new file mode 100644
index 000000000..8860674c8
--- /dev/null
+++ b/src/main/java/org/useless/seedviewer/gui/components/Viewport.java
@@ -0,0 +1,396 @@
+package org.useless.seedviewer.gui.components;
+
+import com.mojang.logging.LogUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.useless.seedviewer.TestChunkProvider;
+import org.useless.seedviewer.bta.BTAChunkProvider;
+import org.useless.seedviewer.bta.BTAWorld;
+import org.useless.seedviewer.collections.ChunkLocation;
+import org.useless.seedviewer.collections.ChunkPos2D;
+import org.useless.seedviewer.collections.ChunkPos3D;
+import org.useless.seedviewer.collections.ObjectWrapper;
+import org.useless.seedviewer.data.Biome;
+import org.useless.seedviewer.data.Chunk;
+import org.useless.seedviewer.data.World;
+import org.useless.seedviewer.gui.ChunkProvider;
+import org.useless.seedviewer.gui.ChunkView;
+import org.useless.seedviewer.gui.SeedViewer;
+
+import javax.imageio.ImageIO;
+import javax.swing.*;
+import javax.swing.border.LineBorder;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
+import java.awt.event.MouseWheelEvent;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+public class Viewport extends JLabel {
+    private static final Logger LOGGER = LogUtils.getLogger();
+    public static final long MS_UNTIL_CHUNK_UNLOAD = 10_000;
+    public static final int VIEWPORT_CHUNKS_OVERSCAN = 4;
+    public static final int VIEWPORT_UNLOAD_OVERSCAN = 10;
+
+    public static final float ZOOM_SENSITIVITY = 0.125f;
+    public static final float ZOOM_MIN = 1f;
+    public static final float ZOOM_MAX = 16f;
+
+    private final Map<ChunkLocation, ChunkView> chunkViewMap = new HashMap<>();
+    private final Set<ChunkView> chunksPendingPostProcess = new HashSet<>();
+    private final BufferedImage slimeVignette;
+
+    public ChunkProvider chunkProvider = new TestChunkProvider();
+    public final ObjectWrapper<@NotNull Long> seed = new ObjectWrapper<>(100L);
+    public final ObjectWrapper<@Nullable World> world = new ObjectWrapper<>(null);
+
+    public final ObjectWrapper<@NotNull Float> zoom = new ObjectWrapper<>(1F);
+    public final ObjectWrapper<@NotNull Float> viewX = new ObjectWrapper<>(0F);
+    public final ObjectWrapper<@NotNull Float> viewZ = new ObjectWrapper<>(0F);
+
+    public final ObjectWrapper<@NotNull Boolean> showSlimeChunks = new ObjectWrapper<>(true);
+    public final ObjectWrapper<@NotNull Boolean> showChunkBorders = new ObjectWrapper<>(true);
+    public final ObjectWrapper<@NotNull Boolean> showBiomes = new ObjectWrapper<>(true);
+    public final ObjectWrapper<@NotNull Boolean> showTerrain = new ObjectWrapper<>(true);
+    public final ObjectWrapper<@NotNull Boolean> showCrosshair = new ObjectWrapper<>(true);
+
+    private final SeedViewer seedViewer;
+
+    private Point lastLeftClickPoint = null;
+
+    public Viewport(SeedViewer seedViewer) {
+        this.seedViewer = seedViewer;
+
+        BufferedImage _vignette = null;
+        try {
+            InputStream stream = Viewport.class.getResourceAsStream("/assets/seedviewer/textures/slime_vignette.png");
+            if (stream != null) {
+                _vignette = ImageIO.read(stream);
+            } else {
+                LOGGER.error("Stream for '/seedviewer/slime_vignette.png' is null!");
+            }
+        } catch (IOException e) {
+            LOGGER.error("Failed to load slime vignette!");
+        }
+        slimeVignette = _vignette;
+
+        try {
+            setSeed(Long.parseLong(seedViewer.launchProperties.getProperty("seed", "100")));
+        } catch (NumberFormatException ignored){
+            setSeed(seedViewer.launchProperties.getProperty("seed", "100").hashCode());
+        }
+    }
+
+    public void setup() {
+        addMouseWheelListener(e -> {
+            if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
+                offsetZoom(-e.getUnitsToScroll() * ZOOM_SENSITIVITY);
+            }
+        });
+        addMouseListener(new MouseAdapter() {
+            @Override
+            public void mousePressed(MouseEvent e) {
+                if (e.getButton() == MouseEvent.BUTTON1) {
+                    lastLeftClickPoint = e.getPoint();
+                }
+            }
+        });
+        addMouseMotionListener(new MouseMotionAdapter() {
+            @Override
+            public void mouseDragged(MouseEvent e) {
+                if (lastLeftClickPoint != null) {
+                    int dx = e.getX() - lastLeftClickPoint.x;
+                    int dy = e.getY() - lastLeftClickPoint.y;
+                    lastLeftClickPoint = e.getPoint();
+
+                    offsetView(-dx, dy);
+                }
+            }
+        });
+        this.setBorder(new LineBorder(Color.BLACK, 1, false));
+        this.setFocusable(true);
+    }
+
+    public void onResize(Rectangle newShape) {
+        this.setBounds(newShape.x, newShape.y, newShape.width, newShape.height);
+    }
+
+    public synchronized void tick() {
+        Rectangle viewportBounds = getViewportBounds();
+        Rectangle unloadBounds = new Rectangle(viewportBounds.x - VIEWPORT_UNLOAD_OVERSCAN, viewportBounds.y - VIEWPORT_UNLOAD_OVERSCAN, viewportBounds.width + VIEWPORT_UNLOAD_OVERSCAN * 2, viewportBounds.height + VIEWPORT_UNLOAD_OVERSCAN * 2);
+        Set<ChunkLocation> removalQueue = new HashSet<>();
+        for (ChunkView view : chunkViewMap.values()) {
+            if (unloadBounds.intersects(view.getWorldBounds())) {
+                view.lastSeenTime = System.currentTimeMillis();
+            }
+            if (System.currentTimeMillis() - view.lastSeenTime > MS_UNTIL_CHUNK_UNLOAD) {
+                removalQueue.add(view.getLocation());
+            }
+        }
+        for (ChunkLocation location : removalQueue) {
+            removeChunkView(location);
+        }
+
+        addMissingViewers(viewportBounds);
+
+        if (showTerrain.get() && world.get() != null) {
+            List<ChunkView> unpendedChunks = new ArrayList<>();
+            for (ChunkView view : chunksPendingPostProcess) {
+                if (!view.hasInit()) continue;
+                if (view.hasProcessed()) continue;
+                ChunkLocation up = new ChunkLocation(view.getLocation().x, view.getLocation().z - 1);
+                if (chunkViewMap.containsKey(up) && chunkViewMap.get(up).hasInit()) {
+                    view.process(chunkViewMap.get(up));
+                    unpendedChunks.add(view);
+                }
+            }
+            unpendedChunks.forEach(chunksPendingPostProcess::remove);
+        }
+        repaint();
+
+//        long total = 0;
+//        for (long l : TIME_BUFFER) {
+//            total += l;
+//        }
+//        Global.LOGGER.info("Render average {}HZ", 1D/(((double) total/TIME_BUFFER.length)/1_000_000_000));
+    }
+
+    public synchronized void addMissingViewers(Rectangle viewportBounds) {
+        ChunkLocation topLeftLocation =
+            new ChunkLocation(viewportBounds.x/Chunk.CHUNK_SIZE_X,
+                viewportBounds.y/Chunk.CHUNK_SIZE_Z);
+        int chunksX = viewportBounds.width/Chunk.CHUNK_SIZE_X;
+        int chunksZ = viewportBounds.height/Chunk.CHUNK_SIZE_Z;
+
+        List<ChunkLocation> pendingLocation = new ArrayList<>();
+        for (int _x = topLeftLocation.x; _x < topLeftLocation.x + chunksX; _x++) {
+            for (int _z = topLeftLocation.z; _z < topLeftLocation.z + chunksZ; _z++) {
+                ChunkLocation location = new ChunkLocation(_x, _z);
+                if (chunkViewMap.containsKey(location)) continue;
+                pendingLocation.add(location);
+            }
+        }
+        pendingLocation.sort((o1, o2) -> {
+            ChunkLocation viewLoc = new ChunkLocation((int) Math.floor(viewX.get()/ Chunk.CHUNK_SIZE_X), (int) Math.floor(-viewZ.get()/ Chunk.CHUNK_SIZE_Z));
+            int d1;
+            {
+                int dx = o1.x - viewLoc.x;
+                int dz = o1.z - viewLoc.z;
+                d1 = (dx * dx) + (dz * dz);
+            }
+            int d2;
+            {
+                int dx = o2.x - viewLoc.x;
+                int dz = o2.z - viewLoc.z;
+                d2 = (dx * dx) + (dz * dz);
+            }
+            return d1 - d2;
+        });
+        pendingLocation.forEach(this::addChunkView);
+    }
+
+    public synchronized void setSeed(long seed) {
+        this.seed.set(seed);
+        clearChunkViews();
+        viewX.set(0F);
+        viewZ.set(0F);
+        chunkProvider = new BTAChunkProvider(this.seed.get());
+        seedViewer.queueResize();
+    }
+
+    public synchronized void setWorld(@Nullable File file) {
+        if (file != null) {
+            try {
+                world.set(new BTAWorld(file));
+                chunkProvider = Objects.requireNonNull(world.get()).getChunkProvider();
+            } catch (Exception e) {
+                LOGGER.error("", e);
+                world.set(null);
+                chunkProvider = new BTAChunkProvider(seed.get());
+            }
+        } else {
+            world.set(null);
+            chunkProvider = new BTAChunkProvider(seed.get());
+        }
+
+        clearChunkViews();
+        viewX.set(0F);
+        viewZ.set(0F);
+        seedViewer.queueResize();
+    }
+
+    public Rectangle getViewportBounds() {
+        final int blockX = (int) Math.floor((viewX.get() - (getWidth()/(zoom.get() * 2))));
+        final int blockZ = (int) Math.floor((-viewZ.get() - (getHeight()/(zoom.get() * 2))));
+        final int widthBlocks = (int) Math.ceil((getWidth()/zoom.get()));
+        final int heightBlocks = (int) Math.ceil((getHeight()/zoom.get()));
+        return new Rectangle(blockX - (Chunk.CHUNK_SIZE_X * VIEWPORT_CHUNKS_OVERSCAN), blockZ - (Chunk.CHUNK_SIZE_Z * VIEWPORT_CHUNKS_OVERSCAN), widthBlocks + Chunk.CHUNK_SIZE_X * (VIEWPORT_CHUNKS_OVERSCAN * 2 + 1), heightBlocks + Chunk.CHUNK_SIZE_Z * (VIEWPORT_CHUNKS_OVERSCAN * 2 + 1));
+    }
+
+    public synchronized void offsetZoom(float delta) {
+        setZoom(zoom.get() + delta);
+    }
+
+    public synchronized void setZoom(float newZoom) {
+        if (newZoom < Viewport.ZOOM_MIN) newZoom = Viewport.ZOOM_MIN;
+        if (newZoom > Viewport.ZOOM_MAX) newZoom = Viewport.ZOOM_MAX;
+        zoom.set(newZoom);
+        repaint();
+    }
+
+    public synchronized void offsetView(float deltaX, float deltaZ) {
+        setOffsetView(viewX.get() + (deltaX / zoom.get()), viewZ.get() + (deltaZ / zoom.get()));
+    }
+
+    public synchronized void setOffsetView(float newX, float newZ) {
+        viewX.set(newX);
+        viewZ.set(newZ);
+        repaint();
+    }
+
+    public synchronized void addChunkView(ChunkLocation location) {
+        ChunkView view = new ChunkView(this, location, chunkProvider);
+        chunkViewMap.put(location, view);
+        chunksPendingPostProcess.add(view);
+    }
+
+    public synchronized void removeChunkView(ChunkLocation location) {
+        ChunkView view = chunkViewMap.remove(location);
+        if (view != null) {
+            view.kill();
+            chunksPendingPostProcess.remove(view);
+        }
+    }
+
+    public synchronized void clearChunkViews() {
+        chunkViewMap.forEach((l, c) -> c.kill());
+        chunkViewMap.clear();
+        chunksPendingPostProcess.clear();
+    }
+
+    private ChunkLocation lastHoveredLocation = null;
+    private Chunk lastHoveredChunk = null;
+    public synchronized Biome getHoveredBiome() {
+        ChunkLocation chunkLocation = new ChunkLocation((int) Math.floor(viewX.get()/ Chunk.CHUNK_SIZE_X), (int) Math.floor(-viewZ.get()/ Chunk.CHUNK_SIZE_Z));
+        Chunk chunk;
+        if (lastHoveredLocation != null && lastHoveredChunk != null && lastHoveredLocation.equals(chunkLocation)) {
+            chunk = lastHoveredChunk;
+        } else {
+            chunk = chunkProvider.getChunk(chunkLocation);
+            lastHoveredChunk = chunk;
+            lastHoveredLocation = chunkLocation;
+        }
+        ChunkPos2D c2D = new ChunkPos2D(((int) Math.floor(viewX.get())) - chunkLocation.x * Chunk.CHUNK_SIZE_X, ((int) Math.floor(-viewZ.get())) - chunkLocation.z * Chunk.CHUNK_SIZE_Z);
+        return chunk.getBiome(new ChunkPos3D(c2D.x, chunk.getHeight(c2D), c2D.z));
+    }
+
+    @Override
+    protected void paintComponent(Graphics g) {
+        super.paintComponent(g);
+        paintToGraphics(g);
+    }
+//    private static final int TIME_BUFFER_SIZE = 32;
+//    private static final long[] TIME_BUFFER = new long[TIME_BUFFER_SIZE];
+//    private static int renderPointer = 0;
+    public void paintToGraphics(Graphics g) {
+        synchronized (this) {
+//            long start = System.nanoTime();
+            Rectangle viewportBounds = getViewportBounds();
+            long seed = world.get() == null ? this.seed.get() : world.get().getSeed();
+            for (ChunkView view : chunkViewMap.values()) {
+                if (!viewportBounds.intersects(view.getWorldBounds())) continue;
+                int blockX = view.getLocation().x * Chunk.CHUNK_SIZE_X;
+                int blockZ = view.getLocation().z * Chunk.CHUNK_SIZE_Z;
+
+                int subImgX = (int) Math.floor((blockX - viewX.get()) * zoom.get() + getWidth()/2d);
+                int subImgZ = (int) Math.floor((blockZ + viewZ.get()) * zoom.get() + getHeight()/2d);
+                int subImgWidth = (int) Math.floor(Chunk.CHUNK_SIZE_X * zoom.get());
+                int subImgHeight = (int) Math.floor(Chunk.CHUNK_SIZE_Z * zoom.get());
+                if (showTerrain.get() && world.get() != null) {
+                    g.drawImage(view.getTerrainMapImage(),
+                        subImgX,
+                        subImgZ,
+                        subImgWidth,
+                        subImgHeight,
+                        null,
+                        null);
+                }
+                if (showBiomes.get()) {
+                    g.drawImage(view.getBiomeMapImage(),
+                        subImgX,
+                        subImgZ,
+                        subImgWidth,
+                        subImgHeight,
+                        null,
+                        null);
+                }
+                if (showSlimeChunks.get() && SeedViewer.isSlimeChunk(seed, view.getLocation())) {
+                    Graphics gSlime = g.create();
+                    if (slimeVignette == null) {
+                        gSlime.setColor(new Color(64, 255, 120, 128));
+                        gSlime.fillRect(
+                            subImgX,
+                            subImgZ,
+                            subImgWidth,
+                            subImgHeight);
+                    } else {
+                        gSlime.drawImage(slimeVignette,
+                            subImgX,
+                            subImgZ,
+                            subImgWidth,
+                            subImgHeight,
+                            null, null);
+                    }
+                    gSlime.dispose();
+                }
+            }
+            if (showChunkBorders.get()) {
+                int leftChunk = viewportBounds.x / Chunk.CHUNK_SIZE_X;
+                int widthChunks = viewportBounds.width / Chunk.CHUNK_SIZE_X;
+                int topChunk = viewportBounds.y / Chunk.CHUNK_SIZE_Z;
+                int heightChunks = viewportBounds.height / Chunk.CHUNK_SIZE_Z;
+
+                Graphics gBorders = g.create();
+                gBorders.setColor(new Color(0, 0, 0, 64));
+                for (int _x = leftChunk; _x <= leftChunk + widthChunks; _x++) {
+                    float blockX = (_x * Chunk.CHUNK_SIZE_X);
+                    int subImgX = (int) Math.floor((blockX - viewX.get()) * zoom.get() + getWidth()/2d);
+
+                    gBorders.drawLine(subImgX, 0, subImgX, getHeight());
+                }
+                for (int _z = topChunk; _z < topChunk + heightChunks; _z++) {
+                    float blockZ = (_z * Chunk.CHUNK_SIZE_Z);
+                    int subImgZ = (int) Math.floor((blockZ + viewZ.get()) * zoom.get() + getHeight()/2d);
+
+                    gBorders.drawLine(0, subImgZ, getWidth(), subImgZ);
+                }
+                gBorders.dispose();
+            }
+            if (showCrosshair.get()) {
+                Graphics gCrosshair = g.create();
+                int centX = getWidth()/2;
+                int centZ = getHeight()/2;
+                int lineReach = 10;
+                int lineWidth = 2;
+                gCrosshair.setColor(Color.BLACK);
+                gCrosshair.setXORMode(Color.WHITE);
+                gCrosshair.fillRect(centX - lineReach, centZ - lineWidth/2, lineReach * 2, lineWidth);
+                gCrosshair.fillRect(centX - lineWidth/2, centZ - lineReach, lineWidth, lineReach * 2);
+                gCrosshair.dispose();
+            }
+//            TIME_BUFFER[renderPointer++ & (TIME_BUFFER_SIZE-1)] = System.nanoTime() - start;
+        }
+    }
+}
diff --git a/src/main/resources/assets/minecraft/textures/block/repeater_active_overlay.png b/src/main/resources/assets/minecraft/textures/block/repeater_active_overlay.png
index 2bf42da37..2be1a6a7a 100644
Binary files a/src/main/resources/assets/minecraft/textures/block/repeater_active_overlay.png and b/src/main/resources/assets/minecraft/textures/block/repeater_active_overlay.png differ
diff --git a/src/main/resources/assets/minecraft/textures/gui/title/splashes.txt b/src/main/resources/assets/minecraft/textures/gui/title/splashes.txt
index 5a629a1c5..3fb22c348 100644
--- a/src/main/resources/assets/minecraft/textures/gui/title/splashes.txt
+++ b/src/main/resources/assets/minecraft/textures/gui/title/splashes.txt
@@ -12,6 +12,7 @@ Also try Jet Set Radio!
 Also try ReIndev!
 Also try Better than Adventure!
 Also try Legacy+!
+Also try Factorio!
 Also try going outside!
 Happy birthday!
 This text is so small that you'll probably find it hard to read even at 1080p given how incredibly long it is, but at 1440p it should be fine!
diff --git a/src/main/resources/assets/seedviewer/textures/icons/1024.png b/src/main/resources/assets/seedviewer/textures/icons/1024.png
new file mode 100644
index 000000000..da7faa7b5
Binary files /dev/null and b/src/main/resources/assets/seedviewer/textures/icons/1024.png differ
diff --git a/src/main/resources/assets/seedviewer/textures/icons/128.png b/src/main/resources/assets/seedviewer/textures/icons/128.png
new file mode 100644
index 000000000..77a92dad0
Binary files /dev/null and b/src/main/resources/assets/seedviewer/textures/icons/128.png differ
diff --git a/src/main/resources/assets/seedviewer/textures/icons/16.png b/src/main/resources/assets/seedviewer/textures/icons/16.png
new file mode 100644
index 000000000..b070e4aae
Binary files /dev/null and b/src/main/resources/assets/seedviewer/textures/icons/16.png differ
diff --git a/src/main/resources/assets/seedviewer/textures/icons/256.png b/src/main/resources/assets/seedviewer/textures/icons/256.png
new file mode 100644
index 000000000..f2d8f3506
Binary files /dev/null and b/src/main/resources/assets/seedviewer/textures/icons/256.png differ
diff --git a/src/main/resources/assets/seedviewer/textures/icons/32.png b/src/main/resources/assets/seedviewer/textures/icons/32.png
new file mode 100644
index 000000000..54a38f7ef
Binary files /dev/null and b/src/main/resources/assets/seedviewer/textures/icons/32.png differ
diff --git a/src/main/resources/assets/seedviewer/textures/icons/512.png b/src/main/resources/assets/seedviewer/textures/icons/512.png
new file mode 100644
index 000000000..765732747
Binary files /dev/null and b/src/main/resources/assets/seedviewer/textures/icons/512.png differ
diff --git a/src/main/resources/assets/seedviewer/textures/icons/64.png b/src/main/resources/assets/seedviewer/textures/icons/64.png
new file mode 100644
index 000000000..9239a130d
Binary files /dev/null and b/src/main/resources/assets/seedviewer/textures/icons/64.png differ
diff --git a/src/main/resources/assets/seedviewer/textures/slime_vignette.png b/src/main/resources/assets/seedviewer/textures/slime_vignette.png
new file mode 100644
index 000000000..e52f0d612
Binary files /dev/null and b/src/main/resources/assets/seedviewer/textures/slime_vignette.png differ
diff --git a/src/main/resources/font/font_00.png b/src/main/resources/font/font_00.png
index b51fd9627..05f061c2a 100644
Binary files a/src/main/resources/font/font_00.png and b/src/main/resources/font/font_00.png differ
diff --git a/src/main/resources/terrain/rainbow.png b/src/main/resources/terrain/rainbow.png
new file mode 100644
index 000000000..1c9e54f3d
Binary files /dev/null and b/src/main/resources/terrain/rainbow.png differ
