# Hand fixes applied on top of FernFlower's output. # # Decompiling is repeatable; these corrections are not, so they live here and # get re-applied by tools/apply_patches.py after every re-decompile. # # Why each one is needed is in the patch body. === FILE net/minecraft/block/BlockPortal.java --- BEFORE PropertyEnum.create("axis", EnumFacing.Axis.class, (Enum[])(EnumFacing.Axis.X, EnumFacing.Axis.Z)); --- AFTER PropertyEnum.create("axis", EnumFacing.Axis.class, new EnumFacing.Axis[]{EnumFacing.Axis.X, EnumFacing.Axis.Z}); === FILE net/minecraft/util/IObjectIntIterable.java --- REPLACE package net.minecraft.util; /** * Signature restored by hand. * * ProGuard dropped the generic Signature attribute from this class, so the * decompiler emitted it raw while every use site still carried a type argument. * That single missing parameter produced the majority of the compile errors: * raw here means raw everywhere downstream. * * There is no method on this interface. The "object to int" name comes from the * classes that implement it, which each expose their own lookup; declaring one * here would force every implementation to invent it. */ public interface IObjectIntIterable extends Iterable { } # An Object[] cast assigned into a K[] field. Vanilla writes (K[])new Object[n], # an unchecked cast that compiles; the decompiler emitted the erased type # instead, which does not. === FILE net/minecraft/util/IntIdentityHashBiMap.java --- BEFORE (Object[]) (new Object[i]) --- AFTER (K[]) (new Object[i]) # getEntities/getPlayers take Predicate, but the decompiler typed the # loop variable as raw Entity, so the call cannot be checked. Declaring it as T # is what vanilla does. Multi-line context on purpose: a bare "list.add(entity)" # would also rewrite this.loadedEntityList.add(entity). === FILE net/minecraft/world/storage/loot/properties/EntityPropertyManager.java --- BEFORE throw new IllegalArgumentException("Unknown loot entity property " + t0); } else { return entityproperty_serializer; --- AFTER throw new IllegalArgumentException("Unknown loot entity property " + t0); } else { return (EntityProperty.Serializer) entityproperty_serializer; === FILE net/minecraft/world/World.java --- BEFORE if (oclass.isAssignableFrom(entity.getClass()) && predicate.apply(entity)) { list.add(entity); } --- AFTER if (oclass.isAssignableFrom(entity.getClass()) && predicate.apply((T) entity)) { list.add((T) entity); } === FILE net/minecraft/world/World.java --- BEFORE T t2 = (Entity) list.get(i); --- AFTER T t2 = (T) list.get(i); # Overriding methods came out protected while every one of them is public in # MinecraftServer. Narrowing visibility is not an override, so all six fail. === FILE net/minecraft/server/integrated/IntegratedServer.java --- BEFORE protected ServerCommandManager createCommandManager() { --- AFTER public ServerCommandManager createCommandManager() { === FILE net/minecraft/server/integrated/IntegratedServer.java --- BEFORE protected void loadAllWorlds(String s, String s1, long i, WorldType worldtype, String s2) { --- AFTER public void loadAllWorlds(String s, String s1, long i, WorldType worldtype, String s2) { === FILE net/minecraft/server/integrated/IntegratedServer.java --- BEFORE protected boolean init() throws IOException { --- AFTER public boolean init() throws IOException { === FILE net/minecraft/server/integrated/IntegratedServer.java --- BEFORE protected void tick() { --- AFTER public void tick() { === FILE net/minecraft/server/integrated/IntegratedServer.java --- BEFORE protected void saveAllWorlds(boolean flag) { --- AFTER public void saveAllWorlds(boolean flag) { === FILE net/minecraft/server/integrated/IntegratedServer.java --- BEFORE protected void finalTick(CrashReport crashreport) { --- AFTER public void finalTick(CrashReport crashreport) { # The constructor took a raw Function, so no constructor reference could bind to # it. Typing it as the field is what lets MovementStep::new resolve. === FILE net/minecraft/client/tutorial/TutorialSteps.java --- BEFORE private TutorialSteps(String s, Function function) { --- AFTER private TutorialSteps(String s, Function function) { # Erased types where the surrounding signature is generic: Object[] cannot be # assigned to T[], and a raw Iterator yields Object. === FILE net/minecraft/util/math/Cartesian.java --- BEFORE Iterator iterator = iterable.iterator(); while (iterator.hasNext()) { T t0 = iterator.next(); --- AFTER Iterator iterator = iterable.iterator(); while (iterator.hasNext()) { T t0 = iterator.next(); === FILE net/minecraft/util/math/Cartesian.java --- BEFORE return (Object[]) list.toArray(createArray(oclass, list.size())); --- AFTER return (T[]) list.toArray(createArray(oclass, list.size())); === FILE net/minecraft/util/math/Cartesian.java --- BEFORE return (Object[]) ((Object[]) Array.newInstance(oclass, i)); --- AFTER return (T[]) Array.newInstance(oclass, i); === FILE net/minecraft/util/math/Cartesian.java --- BEFORE return (Object[]) this.results.clone(); --- AFTER return (T[]) this.results.clone(); # matchOneEntity returns T, not Entity. And the team/name/tag arguments are # rewritten below their own declaration, so they cannot be final. === FILE net/minecraft/command/EntitySelector.java --- BEFORE return list.size() == 1 ? (Entity) list.get(0) : null; --- AFTER return list.size() == 1 ? (T) list.get(0) : null; === FILE net/minecraft/command/EntitySelector.java --- BEFORE return Lists.newArrayList(new Entity[]{entity}); --- AFTER return Lists.newArrayList((T) entity); === FILE net/minecraft/command/EntitySelector.java --- BEFORE final String s = getArgument(map, EntitySelector.ARGUMENT_TEAM_NAME); --- AFTER String s = getArgument(map, EntitySelector.ARGUMENT_TEAM_NAME); === FILE net/minecraft/command/EntitySelector.java --- BEFORE final String s = getArgument(map, EntitySelector.ARGUMENT_PLAYER_NAME); --- AFTER String s = getArgument(map, EntitySelector.ARGUMENT_PLAYER_NAME); === FILE net/minecraft/command/EntitySelector.java --- BEFORE final String s = getArgument(map, EntitySelector.ARGUMENT_ENTITY_TAG); --- AFTER String s = getArgument(map, EntitySelector.ARGUMENT_ENTITY_TAG); # FernFlower wrote "null." where the owning type belonged, so every setRespawnState # call referenced a literal null. The constants live on DragonSpawnManager itself. === FILE net/minecraft/world/end/DragonSpawnManager.java --- BEFORE setRespawnState(null. --- AFTER setRespawnState(DragonSpawnManager. # getEntityClassRenderObject is generic in T but the local was declared with a # wildcard, so the recursive call and the return could not be checked. Also the # ternary has no inferable T at all. === FILE net/minecraft/client/renderer/entity/RenderManager.java --- BEFORE Render render = (Render) this.entityRenderMap.get(oclass); --- AFTER Render render = (Render) this.entityRenderMap.get(oclass); === FILE net/minecraft/client/renderer/entity/RenderManager.java --- BEFORE render = this.getEntityClassRenderObject(oclass.getSuperclass()); --- AFTER render = (Render) this.getEntityClassRenderObject(oclass.getSuperclass()); === FILE net/minecraft/client/renderer/entity/RenderManager.java --- BEFORE return renderplayer != null ? renderplayer : this.playerRenderer; --- AFTER return (Render) (renderplayer != null ? renderplayer : this.playerRenderer); # UserListEntry is the erased supertype; the method is generic in V, so the cast # has to be to V. createEntry also needs its type argument spelled out because the # null argument gives the compiler nothing to infer from. === FILE net/minecraft/server/management/UserList.java --- BEFORE return (UserListEntry) this.values.get(this.getObjectKey(k0)); --- AFTER return (V) this.values.get(this.getObjectKey(k0)); === FILE net/minecraft/server/management/UserList.java --- BEFORE V v0 = (UserListEntry) iterator.next(); --- AFTER V v0 = (V) iterator.next(); === FILE net/minecraft/server/management/UserList.java --- BEFORE K k0 = iterator.next(); --- AFTER K k0 = (K) iterator.next(); === FILE net/minecraft/server/management/UserList.java --- BEFORE return new UserListEntry<>((Object) null, jsonobject); --- AFTER return new UserListEntry((Object) null, jsonobject); # Erased types where the surrounding signature is generic. In every case below # the decompiler substituted the supertype it could see for the type parameter. === FILE net/minecraft/util/ClassInheritanceMultiMap.java --- BEFORE T t0 = iterator.next(); --- AFTER T t0 = (T) iterator.next(); === FILE net/minecraft/util/ClassInheritanceMultiMap.java --- BEFORE this.map.put(oclass, Lists.newArrayList(new Object[]{t0})); --- AFTER this.map.put(oclass, Lists.newArrayList(t0)); === FILE net/minecraft/util/ClassInheritanceMultiMap.java --- BEFORE T t0 = object; --- AFTER T t0 = (T) object; # getName is generic in the property's own type, so the redundant (Enum) cast # forced the argument to Enum and broke the call. === FILE net/minecraft/client/renderer/BlockModelShapes.java --- BEFORE BlockDirt.VARIANT.getName((Enum) ((BlockDirt.DirtType) map.remove(BlockDirt.VARIANT))) --- AFTER BlockDirt.VARIANT.getName((BlockDirt.DirtType) map.remove(BlockDirt.VARIANT)) === FILE net/minecraft/client/renderer/BlockModelShapes.java --- BEFORE BlockStoneSlab.VARIANT.getName((Enum) ((BlockStoneSlab.EnumType) map.remove(BlockStoneSlab.VARIANT))) --- AFTER BlockStoneSlab.VARIANT.getName((BlockStoneSlab.EnumType) map.remove(BlockStoneSlab.VARIANT)) === FILE net/minecraft/client/renderer/BlockModelShapes.java --- BEFORE BlockStoneSlabNew.VARIANT.getName((Enum) ((BlockStoneSlabNew.EnumType) map.remove(BlockStoneSlabNew.VARIANT))) --- AFTER BlockStoneSlabNew.VARIANT.getName((BlockStoneSlabNew.EnumType) map.remove(BlockStoneSlabNew.VARIANT)) # readArray returns List but stores byte, long and int, none of # which is T. Vanilla keeps this list raw for exactly that reason. === FILE net/minecraft/nbt/JsonToNBT.java --- BEFORE List list = Lists.newArrayList(); --- AFTER List list = Lists.newArrayList(); === FILE net/minecraft/block/state/BlockStateContainer.java --- BEFORE T t0 = (Comparable) iterator.next(); --- AFTER T t0 = (T) iterator.next(); === FILE net/minecraft/block/state/BlockStateContainer.java --- BEFORE return (Comparable) iproperty.getValueClass().cast(comparable); --- AFTER return (T) iproperty.getValueClass().cast(comparable); # RoomCollection and SecondFloor both have no-argument constructors; the # decompiler passed a literal null that could not match any of them. === FILE net/minecraft/world/gen/structure/WoodlandMansionPieces.java --- BEFORE super(null); --- AFTER super(); === FILE net/minecraft/command/CommandBase.java --- BEFORE return (Entity) object; --- AFTER return (T) object; === FILE net/minecraft/command/CommandBase.java --- BEFORE return iblockstate.withProperty(iproperty, comparable); --- AFTER return iblockstate.withProperty(iproperty, (T) comparable); === FILE net/minecraft/command/CommandBase.java --- BEFORE return (Comparable) iproperty.parseValue(s).orNull(); --- AFTER return (T) iproperty.parseValue(s).orNull(); # withProperty and getName both need the property's own type parameter, not the # Comparable supertype the decompiler settled on. === FILE net/minecraft/nbt/NBTUtil.java --- BEFORE return iblockstate.withProperty(iproperty, (Comparable) optional.get()); --- AFTER return iblockstate.withProperty(iproperty, (T) optional.get()); === FILE net/minecraft/nbt/NBTUtil.java --- BEFORE return iproperty.getName(comparable); --- AFTER return iproperty.getName((T) comparable); # raw Entry, so getKey() is Object and cannot go straight into a Map === FILE net/minecraft/profiler/Snooper.java --- BEFORE map.put(entry.getKey(), entry.getValue().toString()); --- AFTER map.put((String) entry.getKey(), entry.getValue().toString()); # getPropertyName returns String, so the cast belongs on the argument, not on # the call. Casting the result produced a second error instead of fixing one. === FILE net/minecraft/block/state/BlockStateBase.java --- BEFORE return iproperty.getName(comparable); --- AFTER return iproperty.getName((T) comparable); === FILE net/minecraft/client/renderer/block/statemap/StateMapperBase.java --- BEFORE return iproperty.getName(comparable); --- AFTER return iproperty.getName((T) comparable); # Advancement.Builder.resolveParent takes a java.util.function.Function while # Guava's forMap hands back com.google.common.base.Function. Bridging with a # method reference keeps both sides on their own interface. === FILE net/minecraft/advancements/AdvancementList.java --- BEFORE Function function = Functions.forMap(this.advancements, (Object) null); --- AFTER Function function = Functions.forMap(this.advancements, null)::apply; # criteria is keyed by String, the set is a keySet: the second pass needs its # own iterator of the right element type. === FILE net/minecraft/advancements/AdvancementProgress.java --- BEFORE iterator = set.iterator(); while (iterator.hasNext()) { String s = (String) iterator.next(); --- AFTER Iterator iterator1 = set.iterator(); while (iterator1.hasNext()) { String s = iterator1.next(); === FILE net/minecraft/block/state/BlockStateBase.java --- BEFORE return this.withProperty(iproperty, (Comparable) cyclePropertyValue(iproperty.getAllowedValues(), this.getValue(iproperty))); --- AFTER return this.withProperty(iproperty, (T) cyclePropertyValue(iproperty.getAllowedValues(), this.getValue(iproperty))); # getAllowedValues hands back Collection, which is not the declared # element type. Vanilla keeps this list raw for the same reason. === FILE net/minecraft/block/state/BlockStateContainer.java --- BEFORE List>> list = Lists.newArrayList(); --- AFTER List list = Lists.newArrayList(); === FILE net/minecraft/block/state/pattern/BlockStateMatcher.java --- BEFORE return predicate.apply(iblockstate.getValue(iproperty)); --- AFTER return ((Predicate) predicate).apply(iblockstate.getValue(iproperty)); === FILE net/minecraft/block/state/pattern/FactoryBlockPattern.java --- BEFORE this.symbolMap.put(c0, (Object) null); --- AFTER this.symbolMap.put(c0, (Predicate) null); # the local is filled from an ArrayList and from a List, so List is the only # type both fit === FILE net/minecraft/client/gui/GuiIngame.java --- BEFORE ArrayList arraylist; --- AFTER List arraylist; === FILE net/minecraft/client/gui/toasts/GuiToast.java --- BEFORE return guitoast_toastinstance.getToast(); --- AFTER return (T) guitoast_toastinstance.getToast(); # the counter is reused below the loop, so it cannot be final === FILE net/minecraft/client/particle/ParticleManager.java --- BEFORE for (final int i = 0; i < 3; ++i) { --- AFTER for (int i = 0; i < 3; ++i) { === FILE net/minecraft/client/renderer/ItemRenderer.java --- BEFORE RenderPlayer renderplayer = (RenderPlayer) this.renderManager.getEntityRenderObject(entityplayersp); --- AFTER RenderPlayer renderplayer = (RenderPlayer) this.renderManager.getEntityRenderObject(entityplayersp, RenderPlayer.class); # getHardware() is declared without getProcessors in the public interface; the # com.sun one is needed, and its Processor type is not named so the class does # not have to be resolved at compile time. === FILE net/minecraft/client/renderer/OpenGlHelper.java --- BEFORE Processor[] aprocessor = (new SystemInfo()).getHardware().getProcessors(); --- AFTER Object[] aprocessor = (Object[]) ((com.sun.management.SystemInfo) new SystemInfo()).getHardware().getProcessors(); === FILE net/minecraft/client/renderer/tileentity/TileEntityRendererDispatcher.java --- BEFORE TileEntitySpecialRenderer tileentityspecialrenderer = (TileEntitySpecialRenderer) this.renderers.get(oclass); --- AFTER TileEntitySpecialRenderer tileentityspecialrenderer = (TileEntitySpecialRenderer) this.renderers.get(oclass); === FILE net/minecraft/client/renderer/tileentity/TileEntityRendererDispatcher.java --- BEFORE tileentityspecialrenderer = this.getRenderer(oclass.getSuperclass()); --- AFTER tileentityspecialrenderer = (TileEntitySpecialRenderer) this.getRenderer(oclass.getSuperclass()); # listFiles is overloaded on FileFilter and FilenameFilter, and the filter is # an IOFileFilter implementing both === FILE net/minecraft/client/resources/FolderResourcePack.java --- BEFORE File[] afile = file.listFiles(DirectoryFileFilter.DIRECTORY); --- AFTER File[] afile = file.listFiles((java.io.FileFilter) DirectoryFileFilter.DIRECTORY); === FILE net/minecraft/client/util/SearchTree.java --- BEFORE this.byName.add(t0, s.toLowerCase(Locale.ROOT)); --- AFTER this.byName.add(t0, ((String) s).toLowerCase(Locale.ROOT)); === FILE net/minecraft/command/CommandSpreadPlayers.java --- BEFORE set.add((Object) null); --- AFTER set.add((Team) null); === FILE net/minecraft/util/NonNullList.java --- BEFORE return new NonNullList<>(Arrays.asList(aobject), e0); --- AFTER return new NonNullList(Arrays.asList(aobject), e0); === FILE net/minecraft/util/datafix/walkers/Filtered.java --- BEFORE this.key = EntityList.getKey(oclass); --- AFTER this.key = EntityList.getKey((Class) (Class) oclass); === FILE net/minecraft/util/datafix/walkers/Filtered.java --- BEFORE this.key = TileEntity.getKey(oclass); --- AFTER this.key = TileEntity.getKey((Class) (Class) oclass); # getEntityRenderObject infers its type parameter from the assignment target and # lands on Entity. Naming it gives the right renderer type. === FILE net/minecraft/client/renderer/ItemRenderer.java --- BEFORE RenderPlayer renderplayer = (RenderPlayer) this.renderManager.getEntityRenderObject(entityplayersp, RenderPlayer.class); --- AFTER RenderPlayer renderplayer = (RenderPlayer) this.renderManager.getEntityRenderObject(entityplayersp); # oshi exposes the processor list through CentralProcessor, not directly on # HardwareAbstractionLayer. Naming Processor is unnecessary, so the class does # not need to be resolved. === FILE net/minecraft/client/renderer/OpenGlHelper.java --- BEFORE Object[] aprocessor = (Object[]) ((com.sun.management.SystemInfo) new SystemInfo()).getHardware().getProcessors(); --- AFTER Object[] aprocessor = (Object[]) systeminfo.getHardware().getProcessor().getProcessors(); === FILE net/minecraft/client/renderer/debug/DebugRendererNeighborsUpdate.java --- BEFORE iterator = map.entrySet().iterator(); --- AFTER iterator = (Iterator) map.entrySet().iterator(); === FILE net/minecraft/client/renderer/entity/RenderLivingBase.java --- BEFORE return this.layerRenderers.add(u0); --- AFTER return this.layerRenderers.add((LayerRenderer) u0); === FILE net/minecraft/client/renderer/entity/RenderManager.java --- BEFORE render = (Render) this.getEntityClassRenderObject(oclass.getSuperclass()); --- AFTER render = (Render) this.getEntityClassRenderObject((Class) (Class) oclass.getSuperclass()); === FILE net/minecraft/client/renderer/texture/TextureAtlasSprite.java --- BEFORE this.framesTextureData.add((Object) null); --- AFTER this.framesTextureData.add((int[][]) null); === FILE net/minecraft/client/renderer/tileentity/TileEntityRendererDispatcher.java --- BEFORE tileentityspecialrenderer = (TileEntitySpecialRenderer) this.getRenderer(oclass.getSuperclass()); --- AFTER tileentityspecialrenderer = (TileEntitySpecialRenderer) this.getRenderer((Class) (Class) oclass.getSuperclass()); === FILE net/minecraft/command/EntitySelector.java --- BEFORE list = Lists.newArrayList(new Entity[]{entity}); --- AFTER list = Lists.newArrayList((T) entity); === FILE net/minecraft/entity/Entity.java --- BEFORE set.add(entity); --- AFTER set.add((T) entity); === FILE net/minecraft/entity/EntityList.java --- BEFORE EntityList.OLD_NAMES.add((Object) null); --- AFTER EntityList.OLD_NAMES.add((String) null); === FILE net/minecraft/entity/ai/EntityAINearestAttackableTarget.java --- BEFORE }, this.targetEntitySelector); --- AFTER }, (Predicate) this.targetEntitySelector); === FILE net/minecraft/item/ItemSlab.java --- BEFORE return this.doubleSlab.getDefaultState().withProperty(iproperty, comparable); --- AFTER return this.doubleSlab.getDefaultState().withProperty(iproperty, (T) comparable); # Packet.processPacket takes T, which here is the concrete handler subtype. # Erasing the packet keeps the INetHandler it already is. === FILE net/minecraft/network/NetworkManager.java --- BEFORE packet.processPacket(this.packetListener); --- AFTER ((Packet) packet).processPacket(this.packetListener); === FILE net/minecraft/tileentity/TileEntityPiston.java --- BEFORE TileEntityPiston.MOVING_ENTITY.set((Object) null); --- AFTER TileEntityPiston.MOVING_ENTITY.set((EnumFacing) null); === FILE net/minecraft/network/datasync/EntityDataManager.java --- BEFORE list.add(new EntityDataManager.DataEntry<>(dataserializer.createKey(short0), dataserializer.read(packetbuffer))); --- AFTER list.add(new EntityDataManager.DataEntry(dataserializer.createKey(short0), dataserializer.read(packetbuffer))); === FILE net/minecraft/client/renderer/OpenGlHelper.java --- BEFORE Object[] aprocessor = (Object[]) systeminfo.getHardware().getProcessor().getProcessors(); --- AFTER Object[] aprocessor = (Object[]) (new SystemInfo()).getHardware().getProcessor().getProcessors(); === FILE net/minecraft/entity/ai/EntityAINearestAttackableTarget.java --- BEFORE this.targetEntity = this.taskOwner.world.getNearestAttackablePlayer( --- AFTER this.targetEntity = (EntityLivingBase) this.taskOwner.world.getNearestAttackablePlayer( === FILE net/minecraft/network/datasync/EntityDataManager.java --- BEFORE list.add(new EntityDataManager.DataEntry(dataserializer.createKey(short0), dataserializer.read(packetbuffer))); --- AFTER list.add(new EntityDataManager.DataEntry((DataParameter) dataserializer.createKey(short0), dataserializer.read(packetbuffer))); === FILE net/minecraft/network/datasync/EntityDataManager.java --- BEFORE entitydatamanager_dataentry.setValue(entitydatamanager_dataentry1.getValue()); --- AFTER entitydatamanager_dataentry.setValue((T) entitydatamanager_dataentry1.getValue()); === FILE net/minecraft/util/HttpUtil.java --- BEFORE return listenablefuture; --- AFTER return (ListenableFuture) listenablefuture; === FILE net/minecraft/util/JsonUtils.java --- BEFORE return gson.getAdapter(TypeToken.get(type)).read(jsonreader); --- AFTER return (T) gson.getAdapter(TypeToken.get(type)).read(jsonreader); === FILE net/minecraft/util/NonNullList.java --- BEFORE return new NonNullList(Arrays.asList(aobject), e0); --- AFTER return new NonNullList((List) Arrays.asList(aobject), e0); === FILE net/minecraft/util/math/Cartesian.java --- BEFORE return Arrays.asList((Object[]) aobject); --- AFTER return Arrays.asList((T[]) aobject); # EntityPlayer is not imported here, so the type witness needs its full name. === FILE net/minecraft/client/renderer/ItemRenderer.java --- BEFORE RenderPlayer renderplayer = (RenderPlayer) this.renderManager.getEntityRenderObject(entityplayersp); --- AFTER RenderPlayer renderplayer = (RenderPlayer) this.renderManager.getEntityRenderObject(entityplayersp); # The bundled oshi is 5.8.5, where CentralProcessor no longer has # getProcessors(); getProcessorIdentifier() is the replacement that still yields # a name for this label. === FILE net/minecraft/client/renderer/OpenGlHelper.java --- BEFORE Object[] aprocessor = (Object[]) (new SystemInfo()).getHardware().getProcessor().getProcessors(); --- AFTER Object[] aprocessor = new Object[]{String.valueOf((new SystemInfo()).getHardware().getProcessor().getProcessorIdentifier())}; # the parameter is final, so the fallback needs its own local === FILE net/minecraft/client/renderer/texture/TextureManager.java --- BEFORE itextureobject = TextureUtil.MISSING_TEXTURE; this.mapTextureObjects.put(resourcelocation, itextureobject); --- AFTER ITextureObject missing = TextureUtil.MISSING_TEXTURE; this.mapTextureObjects.put(resourcelocation, missing); # targetEntity is declared as T, the class's own type parameter === FILE net/minecraft/entity/ai/EntityAINearestAttackableTarget.java --- BEFORE this.targetEntity = (EntityLivingBase) this.taskOwner.world.getNearestAttackablePlayer( --- AFTER this.targetEntity = (T) this.taskOwner.world.getNearestAttackablePlayer( # The anonymous class captures the loop variable, which a for-loop never lets be # effectively final. Capturing a copy is what the original bytecode did. === FILE net/minecraft/client/particle/ParticleManager.java --- BEFORE crashreportcategory.addDetail("Particle Type", new ICrashReportDetail() { public String call() throws Exception { return i == 0 ? "MISC_TEXTURE" : (i == 1 ? "TERRAIN_TEXTURE" : (i == 3 ? "ENTITY_PARTICLE_TEXTURE" : "Unknown - " + i)); } }); --- AFTER final int layer = i; crashreportcategory.addDetail("Particle Type", new ICrashReportDetail() { public String call() throws Exception { return layer == 0 ? "MISC_TEXTURE" : (layer == 1 ? "TERRAIN_TEXTURE" : (layer == 3 ? "ENTITY_PARTICLE_TEXTURE" : "Unknown - " + layer)); } }); # j is a mouse-Y scratch value reused a second time further down. The decompiler # declared it final, which makes the second assignment an error. === FILE net/minecraft/client/renderer/EntityRenderer.java --- BEFORE final int j; --- AFTER int j; # j is assigned twice, so it is not effectively final, and the crash report # class captures it. Capturing a copy keeps the report correct. === FILE net/minecraft/client/renderer/EntityRenderer.java --- BEFORE crashreportcategory.addDetail("Mouse location", new ICrashReportDetail() { public String call() throws Exception { return String.format("Scaled: (%d, %d). Absolute: (%d, %d)", i1, j, Mouse.getX(), Mouse.getY()); } }); --- AFTER final int scaledMouseY = j; crashreportcategory.addDetail("Mouse location", new ICrashReportDetail() { public String call() throws Exception { return String.format("Scaled: (%d, %d). Absolute: (%d, %d)", i1, scaledMouseY, Mouse.getX(), Mouse.getY()); } }); # A blank final assigned in both try and catch is rejected: the catch may run # after the try already stored a value. Computing into a plain local first and # freezing it afterwards says the same thing and is legal. === FILE net/minecraft/command/EntitySelector.java --- BEFORE final GameType gametype; try { int i = Integer.parseInt(s); gametype = GameType.parseGameTypeWithDefault(i, GameType.NOT_SET); } catch (Throwable throwable) { gametype = GameType.parseGameTypeWithDefault(s, GameType.NOT_SET); } --- AFTER GameType parsedGameType; try { int i = Integer.parseInt(s); parsedGameType = GameType.parseGameTypeWithDefault(i, GameType.NOT_SET); } catch (Throwable throwable) { parsedGameType = GameType.parseGameTypeWithDefault(s, GameType.NOT_SET); } final GameType gametype = parsedGameType; # s is rewritten when the argument is negated, so the predicate captures a copy. === FILE net/minecraft/command/EntitySelector.java --- BEFORE if (s != null) { list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { if (!(entity instanceof EntityLivingBase)) { --- AFTER if (s != null) { final String teamName = s; list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { if (!(entity instanceof EntityLivingBase)) { === FILE net/minecraft/command/EntitySelector.java --- BEFORE return s1.equals(s) != flag; --- AFTER return s1.equals(teamName) != flag; === FILE net/minecraft/command/EntitySelector.java --- BEFORE if (s != null) { list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { return entity != null && entity.getName().equals(s) != flag; } }); } --- AFTER if (s != null) { final String playerName = s; list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { return entity != null && entity.getName().equals(playerName) != flag; } }); } # i and j are blank finals assigned in two separate blocks, and each predicate # captures them. One pair of locals per block is what the original meant. === FILE net/minecraft/command/EntitySelector.java --- BEFORE final int i; final int j; if (map.containsKey(EntitySelector.ARGUMENT_ROTY_MIN) || map.containsKey(EntitySelector.ARGUMENT_ROTY_MAX)) { i = MathHelper.wrapDegrees(getInt(map, EntitySelector.ARGUMENT_ROTY_MIN, 0)); j = MathHelper.wrapDegrees(getInt(map, EntitySelector.ARGUMENT_ROTY_MAX, 359)); list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { if (entity == null) { return false; } else { int k = MathHelper.wrapDegrees(MathHelper.floor(entity.rotationYaw)); return i > j ? k >= i || k <= j : k >= i && k <= j; } } }); } if (map.containsKey(EntitySelector.ARGUMENT_ROTX_MIN) || map.containsKey(EntitySelector.ARGUMENT_ROTX_MAX)) { i = MathHelper.wrapDegrees(getInt(map, EntitySelector.ARGUMENT_ROTX_MIN, 0)); j = MathHelper.wrapDegrees(getInt(map, EntitySelector.ARGUMENT_ROTX_MAX, 359)); list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { if (entity == null) { return false; } else { int k = MathHelper.wrapDegrees(MathHelper.floor(entity.rotationPitch)); return i > j ? k >= i || k <= j : k >= i && k <= j; } } }); } --- AFTER if (map.containsKey(EntitySelector.ARGUMENT_ROTY_MIN) || map.containsKey(EntitySelector.ARGUMENT_ROTY_MAX)) { final int minYaw = MathHelper.wrapDegrees(getInt(map, EntitySelector.ARGUMENT_ROTY_MIN, 0)); final int maxYaw = MathHelper.wrapDegrees(getInt(map, EntitySelector.ARGUMENT_ROTY_MAX, 359)); list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { if (entity == null) { return false; } else { int k = MathHelper.wrapDegrees(MathHelper.floor(entity.rotationYaw)); return minYaw > maxYaw ? k >= minYaw || k <= maxYaw : k >= minYaw && k <= maxYaw; } } }); } if (map.containsKey(EntitySelector.ARGUMENT_ROTX_MIN) || map.containsKey(EntitySelector.ARGUMENT_ROTX_MAX)) { final int minPitch = MathHelper.wrapDegrees(getInt(map, EntitySelector.ARGUMENT_ROTX_MIN, 0)); final int maxPitch = MathHelper.wrapDegrees(getInt(map, EntitySelector.ARGUMENT_ROTX_MAX, 359)); list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { if (entity == null) { return false; } else { int k = MathHelper.wrapDegrees(MathHelper.floor(entity.rotationPitch)); return minPitch > maxPitch ? k >= minPitch || k <= maxPitch : k >= minPitch && k <= maxPitch; } } }); } === FILE net/minecraft/command/EntitySelector.java --- BEFORE if (s != null) { list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { return entity == null ? false : ("".equals(s) ? entity.getTags().isEmpty() != flag : entity.getTags().contains(s) != flag); } }); } --- AFTER if (s != null) { final String tag = s; list.add(new Predicate() { public boolean apply(@Nullable Entity entity) { return entity == null ? false : ("".equals(tag) ? entity.getTags().isEmpty() != flag : entity.getTags().contains(tag) != flag); } }); } # FernFlower moved shutdownMinecraftApplet() into a finally on the game loop # body. A continue inside a try runs the finally first, so the client shut # down after one frame. javap on the original bytecode shows shutdown is # only reached at loop exit (offset 103) and from the catch handlers. === FILE net/minecraft/client/Minecraft.java --- BEFORE public void run() { this.running = true; CrashReport crashreport; try { this.init(); } catch (Throwable throwable) { crashreport = CrashReport.makeCrashReport(throwable, "Initializing game"); crashreport.makeCategory("Initialization"); this.displayCrashReport(this.addGraphicsAndWorldToCrashReport(crashreport)); return; } while (true) { try { if (!this.running) { break; } if (!this.hasCrashed || this.crashReporter == null) { try { this.runGameLoop(); } catch (OutOfMemoryError outofmemoryerror) { this.freeMemory(); this.displayGuiScreen(new GuiMemoryErrorScreen()); System.gc(); } continue; } this.displayCrashReport(this.crashReporter); } catch (MinecraftError minecrafterror) { break; } catch (ReportedException reportedexception) { this.addGraphicsAndWorldToCrashReport(reportedexception.getCrashReport()); this.freeMemory(); Minecraft.LOGGER.fatal("Reported exception thrown!", reportedexception); this.displayCrashReport(reportedexception.getCrashReport()); break; } catch (Throwable throwable1) { crashreport = this.addGraphicsAndWorldToCrashReport(new CrashReport("Unexpected error", throwable1)); this.freeMemory(); Minecraft.LOGGER.fatal("Unreported exception thrown!", throwable1); this.displayCrashReport(crashreport); break; } finally { this.shutdownMinecraftApplet(); } return; } } --- AFTER public void run() { this.running = true; CrashReport crashreport; try { this.init(); } catch (Throwable throwable) { crashreport = CrashReport.makeCrashReport(throwable, "Initializing game"); crashreport.makeCategory("Initialization"); this.displayCrashReport(this.addGraphicsAndWorldToCrashReport(crashreport)); return; } try { while (true) { if (!this.running) { break; } if (this.hasCrashed && this.crashReporter != null) { this.displayCrashReport(this.crashReporter); this.shutdownMinecraftApplet(); return; } try { this.runGameLoop(); } catch (OutOfMemoryError outofmemoryerror) { this.freeMemory(); this.displayGuiScreen(new GuiMemoryErrorScreen()); System.gc(); } } this.shutdownMinecraftApplet(); } catch (MinecraftError minecrafterror) { this.shutdownMinecraftApplet(); } catch (ReportedException reportedexception) { this.addGraphicsAndWorldToCrashReport(reportedexception.getCrashReport()); this.freeMemory(); Minecraft.LOGGER.fatal("Reported exception thrown!", reportedexception); this.displayCrashReport(reportedexception.getCrashReport()); this.shutdownMinecraftApplet(); } catch (Throwable throwable1) { crashreport = this.addGraphicsAndWorldToCrashReport(new CrashReport("Unexpected error", throwable1)); this.freeMemory(); Minecraft.LOGGER.fatal("Unreported exception thrown!", throwable1); this.displayCrashReport(crashreport); this.shutdownMinecraftApplet(); } } === FILE net/minecraft/entity/player/EntityPlayerMP.java --- BEFORE this.entityRemoveQueue.remove(entity.getEntityId()); --- AFTER this.entityRemoveQueue.remove(Integer.valueOf(entity.getEntityId())); === FILE net/minecraft/client/Minecraft.java --- BEFORE this.renderGlobal.makeEntityOutlineShader(); } private void populateSearchTreeManager() { --- AFTER net.rustnotmc.client.RsxBootstrap.start(this); this.renderGlobal.makeEntityOutlineShader(); } private void populateSearchTreeManager() { === FILE net/minecraft/client/Minecraft.java --- BEFORE GlStateManager.popMatrix(); this.profiler.startSection("root"); this.updateDisplay(); --- AFTER GlStateManager.popMatrix(); net.rustnotmc.client.RsxBootstrap.renderFrame(this); this.profiler.startSection("root"); this.updateDisplay(); === FILE net/minecraft/client/gui/GuiScreen.java --- BEFORE public void sendChatMessage(String s, boolean flag) { if (flag) { this.mc.ingameGUI.getChatGUI().addToSentMessages(s); } this.mc.player.sendChatMessage(s); } --- AFTER public void sendChatMessage(String s, boolean flag) { if (flag) { this.mc.ingameGUI.getChatGUI().addToSentMessages(s); } // a mod command scoped to the client is carried out here and stops here. // Anything the server owns is left alone so it still reaches the server. if (net.rustnotmc.client.RsxBootstrap.handleChatCommand(s)) { return; } this.mc.player.sendChatMessage(s); } === FILE net/minecraft/entity/Entity.java --- BEFORE this.collidedHorizontally = d7 != d0 || d9 != d2; this.collidedVertically = d1 != d1; this.onGround = this.collidedVertically && d8 < 0.0D; --- AFTER this.collidedHorizontally = d7 != d0 || d9 != d2; this.collidedVertically = d8 != d1; this.onGround = this.collidedVertically && d8 < 0.0D; === FILE net/minecraft/client/particle/Particle.java --- BEFORE this.onGround = d1 != d1 && d3 < 0.0D; if (d0 != d0) { this.motionX = 0.0D; } if (d2 != d2) { this.motionZ = 0.0D; } --- AFTER this.onGround = originalY != d1 && originalY < 0.0D; if (originalX != d0) { this.motionX = 0.0D; } if (originalZ != d2) { this.motionZ = 0.0D; } === FILE net/minecraft/client/particle/Particle.java --- BEFORE double d3 = d1; if (this.canCollide) { --- AFTER // the motion before collision; the axis is only stopped when collision // actually changed it, which a comparison against itself can never see double originalX = d0; double originalY = d1; double originalZ = d2; if (this.canCollide) { === FILE net/minecraft/entity/Entity.java --- BEFORE boolean flag = this.onGround || d1 != d1 && d1 < 0.0D; --- AFTER boolean flag = this.onGround || d8 != d1 && d8 < 0.0D; === FILE net/minecraft/client/Minecraft.java --- BEFORE for (int k = 0; k < Math.min(10, this.timer.elapsedTicks); ++k) { this.runTick(); } --- AFTER for (int k = 0; k < Math.min(10, this.timer.elapsedTicks); ++k) { this.runTick(); net.rustnotmc.client.RsxBootstrap.clientTick(); } === FILE net/minecraft/client/LoadingScreenRenderer.java --- BEFORE this.framebuffer.framebufferRender(l * k, i1 * k); } this.mc.updateDisplay(); --- AFTER this.framebuffer.framebufferRender(l * k, i1 * k); } net.rustnotmc.client.RsxBootstrap.renderLoadingScreen(this.mc); this.mc.updateDisplay();