Update to Minecraft 1.9.4
This commit is contained in:
@@ -143,6 +143,7 @@ public class InputReplayTimer extends WrappedTimer {
|
||||
|
||||
// Following are a ton of vanilla keyboard shortcuts, some are removed as they're useless in the
|
||||
// replay viewer as of now
|
||||
// TODO Update maybe add new key bindings
|
||||
// TODO: Translate magic values to Keyboard.KEY_ constants
|
||||
|
||||
if (key == 32 && Keyboard.isKeyDown(61) && mc.ingameGUI != null) {
|
||||
|
||||
@@ -16,8 +16,6 @@ import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@Getter
|
||||
@@ -45,7 +43,7 @@ public class NoGuiScreenshot {
|
||||
mc.getFramebuffer().bindFramebuffer(true);
|
||||
GlStateManager.enableTexture2D();
|
||||
|
||||
mc.entityRenderer.updateCameraAndRender(mc.timer.renderPartialTicks);
|
||||
mc.entityRenderer.updateCameraAndRender(mc.timer.renderPartialTicks, System.nanoTime());
|
||||
|
||||
mc.getFramebuffer().unbindFramebuffer();
|
||||
GlStateManager.popMatrix();
|
||||
@@ -101,9 +99,7 @@ public class NoGuiScreenshot {
|
||||
// of the game loop. We cannot use the addScheduledTask method as it'll run the task if called
|
||||
// from the minecraft thread which is exactly what we want to avoid.
|
||||
synchronized (mc.scheduledTasks) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Queue<FutureTask> queue = mc.scheduledTasks;
|
||||
queue.add(ListenableFutureTask.create(runnable, null));
|
||||
mc.scheduledTasks.add(ListenableFutureTask.create(runnable, null));
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,10 @@ import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static net.minecraft.client.renderer.GlStateManager.*;
|
||||
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
|
||||
@@ -311,7 +314,7 @@ public class ReplayHandler {
|
||||
mc.getFramebuffer().bindFramebuffer(true);
|
||||
mc.entityRenderer.setupOverlayRendering();
|
||||
|
||||
ScaledResolution resolution = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
|
||||
ScaledResolution resolution = new ScaledResolution(mc);
|
||||
guiScreen.setWorldAndResolution(mc, resolution.getScaledWidth(), resolution.getScaledHeight());
|
||||
guiScreen.drawScreen(0, 0, 0);
|
||||
|
||||
@@ -328,10 +331,8 @@ public class ReplayHandler {
|
||||
replaySender.setAsyncMode(true);
|
||||
replaySender.setReplaySpeed(0);
|
||||
|
||||
mc.getNetHandler().getNetworkManager().processReceivedPackets();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Entity> entities = (List<Entity>) mc.theWorld.loadedEntityList;
|
||||
for (Entity entity : entities) {
|
||||
mc.getConnection().getNetworkManager().processReceivedPackets();
|
||||
for (Entity entity : mc.theWorld.loadedEntityList) {
|
||||
if (entity instanceof EntityOtherPlayerMP) {
|
||||
EntityOtherPlayerMP e = (EntityOtherPlayerMP) entity;
|
||||
e.setPosition(e.otherPlayerMPX, e.otherPlayerMPY, e.otherPlayerMPZ);
|
||||
|
||||
@@ -12,17 +12,22 @@ import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityOtherPlayerMP;
|
||||
import net.minecraft.client.gui.GuiDownloadTerrain;
|
||||
import net.minecraft.client.gui.GuiErrorScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.network.*;
|
||||
import net.minecraft.network.play.server.*;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.world.EnumDifficulty;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldSettings.GameType;
|
||||
import net.minecraft.world.WorldType;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
@@ -39,30 +44,22 @@ import java.util.concurrent.Callable;
|
||||
*/
|
||||
@Sharable
|
||||
public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
/**
|
||||
* Previously packets for the client player were inserted using one fixed entity id (this one).
|
||||
* This is no longer the case however to provide backwards compatibility, we have to convert
|
||||
* these old packets to use the normal entity id.
|
||||
* Need to punch someone? -> CrushedPixel
|
||||
*/
|
||||
public static final int LEGACY_ENTITY_ID = Integer.MIN_VALUE + 9001;
|
||||
|
||||
/**
|
||||
* These packets are ignored completely during replay.
|
||||
*/
|
||||
private static final List<Class> BAD_PACKETS = Arrays.<Class>asList(
|
||||
S06PacketUpdateHealth.class,
|
||||
S2DPacketOpenWindow.class,
|
||||
S2EPacketCloseWindow.class,
|
||||
S2FPacketSetSlot.class,
|
||||
S30PacketWindowItems.class,
|
||||
S36PacketSignEditorOpen.class,
|
||||
S37PacketStatistics.class,
|
||||
S1FPacketSetExperience.class,
|
||||
S43PacketCamera.class,
|
||||
S39PacketPlayerAbilities.class,
|
||||
S45PacketTitle.class);
|
||||
// TODO Update possibly more?
|
||||
SPacketUpdateHealth.class,
|
||||
SPacketOpenWindow.class,
|
||||
SPacketCloseWindow.class,
|
||||
SPacketSetSlot.class,
|
||||
SPacketWindowItems.class,
|
||||
SPacketSignEditorOpen.class,
|
||||
SPacketStatistics.class,
|
||||
SPacketSetExperience.class,
|
||||
SPacketCamera.class,
|
||||
SPacketPlayerAbilities.class,
|
||||
SPacketTitle.class);
|
||||
|
||||
private static int TP_DISTANCE_LIMIT = 128;
|
||||
|
||||
@@ -171,6 +168,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
this.asyncMode = asyncMode;
|
||||
this.replayLength = file.getMetaData().getDuration();
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
if (asyncMode) {
|
||||
new Thread(asyncSender, "replaymod-async-sender").start();
|
||||
}
|
||||
@@ -239,6 +238,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
*/
|
||||
public void terminateReplay() {
|
||||
terminate = true;
|
||||
MinecraftForge.EVENT_BUS.unregister(this);
|
||||
try {
|
||||
channelInactive(ctx);
|
||||
ctx.channel().pipeline().close();
|
||||
@@ -247,6 +247,25 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onWorldTick(TickEvent.ClientTickEvent event) {
|
||||
// Unfortunately the WorldTickEvent doesn't seem to be emitted on the CLIENT side
|
||||
if (event.phase != TickEvent.Phase.START) return;
|
||||
|
||||
// Spawning a player into an empty chunk (which we might do with the recording player)
|
||||
// prevents it from being moved by teleport packets (it essentially gets stuck) because
|
||||
// Entity#addedToChunk is not set and it is therefore not updated every tick.
|
||||
// To counteract this, we need to manually update it's position if it hasn't been added
|
||||
// to any chunk yet.
|
||||
if (mc.theWorld != null) {
|
||||
for (EntityPlayer playerEntity : mc.theWorld.playerEntities) {
|
||||
if (!playerEntity.addedToChunk && playerEntity instanceof EntityOtherPlayerMP) {
|
||||
playerEntity.onLivingUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg)
|
||||
throws Exception {
|
||||
@@ -274,21 +293,21 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
// Therefore we have to remove all loaded, dead entities manually if we are in sync mode.
|
||||
// We do this after every SpawnX packet and after the destroy entities packet.
|
||||
if (!asyncMode && mc.theWorld != null) {
|
||||
if (p instanceof S0CPacketSpawnPlayer
|
||||
|| p instanceof S0EPacketSpawnObject
|
||||
|| p instanceof S0FPacketSpawnMob
|
||||
|| p instanceof S2CPacketSpawnGlobalEntity
|
||||
|| p instanceof S10PacketSpawnPainting
|
||||
|| p instanceof S11PacketSpawnExperienceOrb
|
||||
|| p instanceof S13PacketDestroyEntities) {
|
||||
if (p instanceof SPacketSpawnPlayer
|
||||
|| p instanceof SPacketSpawnObject
|
||||
|| p instanceof SPacketSpawnMob
|
||||
|| p instanceof SPacketSpawnGlobalEntity
|
||||
|| p instanceof SPacketSpawnPainting
|
||||
|| p instanceof SPacketSpawnExperienceOrb
|
||||
|| p instanceof SPacketDestroyEntities) {
|
||||
World world = mc.theWorld;
|
||||
for (int i = 0; i < world.loadedEntityList.size(); ++i) {
|
||||
Entity entity = (Entity) world.loadedEntityList.get(i);
|
||||
Entity entity = world.loadedEntityList.get(i);
|
||||
if (entity.isDead) {
|
||||
int chunkX = entity.chunkCoordX;
|
||||
int chunkY = entity.chunkCoordZ;
|
||||
|
||||
if (entity.addedToChunk && world.getChunkProvider().chunkExists(chunkX, chunkY)) {
|
||||
if (entity.addedToChunk && world.getChunkProvider().getLoadedChunk(chunkX, chunkY) != null) {
|
||||
world.getChunkFromChunkCoords(chunkX, chunkY).removeEntity(entity);
|
||||
}
|
||||
|
||||
@@ -326,8 +345,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
* @return The processed packet or {@code null} if no packet shall be sent
|
||||
*/
|
||||
protected Packet processPacket(Packet p) throws Exception {
|
||||
if (p instanceof S3FPacketCustomPayload) {
|
||||
S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p;
|
||||
if (p instanceof SPacketCustomPayload) {
|
||||
SPacketCustomPayload packet = (SPacketCustomPayload) p;
|
||||
if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannelName())) {
|
||||
final String unknown = replayHandler.getRestrictions().handle(packet);
|
||||
if (unknown == null) {
|
||||
@@ -353,8 +372,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p instanceof S40PacketDisconnect) {
|
||||
IChatComponent reason = ((S40PacketDisconnect) p).func_149165_c();
|
||||
if (p instanceof SPacketDisconnect) {
|
||||
ITextComponent reason = ((SPacketDisconnect) p).getReason();
|
||||
if ("Please update to view this replay.".equals(reason.getUnformattedText())) {
|
||||
// This version of the mod supports replay restrictions so we are allowed
|
||||
// to remove this packet.
|
||||
@@ -364,11 +383,9 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
if(BAD_PACKETS.contains(p.getClass())) return null;
|
||||
|
||||
convertLegacyEntityIds(p);
|
||||
|
||||
if(p instanceof S48PacketResourcePackSend) {
|
||||
S48PacketResourcePackSend packet = (S48PacketResourcePackSend) p;
|
||||
String url = packet.func_179783_a();
|
||||
if(p instanceof SPacketResourcePackSend) {
|
||||
SPacketResourcePackSend packet = (SPacketResourcePackSend) p;
|
||||
String url = packet.getURL();
|
||||
if (url.startsWith("replay://")) {
|
||||
int id = Integer.parseInt(url.substring("replay://".length()));
|
||||
Map<Integer, String> index = replayFile.getResourcePackIndex();
|
||||
@@ -379,17 +396,17 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
if (!file.exists()) {
|
||||
IOUtils.copy(replayFile.getResourcePack(hash).get(), new FileOutputStream(file));
|
||||
}
|
||||
mc.getResourcePackRepository().func_177319_a(file);
|
||||
mc.getResourcePackRepository().setResourcePackInstance(file);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if(p instanceof S01PacketJoinGame) {
|
||||
S01PacketJoinGame packet = (S01PacketJoinGame) p;
|
||||
if(p instanceof SPacketJoinGame) {
|
||||
SPacketJoinGame packet = (SPacketJoinGame) p;
|
||||
allowMovement = true;
|
||||
int entId = packet.getEntityId();
|
||||
int entId = packet.getPlayerId();
|
||||
actualID = entId;
|
||||
entId = -1789435; // Camera entity id should be negative which is an invalid id and can't be used by servers
|
||||
int dimension = packet.getDimension();
|
||||
@@ -397,21 +414,21 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
int maxPlayers = packet.getMaxPlayers();
|
||||
WorldType worldType = packet.getWorldType();
|
||||
|
||||
p = new S01PacketJoinGame(entId, GameType.SPECTATOR, false, dimension,
|
||||
p = new SPacketJoinGame(entId, GameType.SPECTATOR, false, dimension,
|
||||
difficulty, maxPlayers, worldType, false);
|
||||
}
|
||||
|
||||
if(p instanceof S07PacketRespawn) {
|
||||
S07PacketRespawn respawn = (S07PacketRespawn) p;
|
||||
p = new S07PacketRespawn(respawn.func_149082_c(),
|
||||
respawn.func_149081_d(), respawn.func_149080_f(), GameType.SPECTATOR);
|
||||
if(p instanceof SPacketRespawn) {
|
||||
SPacketRespawn respawn = (SPacketRespawn) p;
|
||||
p = new SPacketRespawn(respawn.getDimensionID(),
|
||||
respawn.getDifficulty(), respawn.getWorldType(), GameType.SPECTATOR);
|
||||
|
||||
allowMovement = true;
|
||||
}
|
||||
|
||||
if(p instanceof S08PacketPlayerPosLook) {
|
||||
if(p instanceof SPacketPlayerPosLook) {
|
||||
if(!hasWorldLoaded) hasWorldLoaded = true;
|
||||
final S08PacketPlayerPosLook ppl = (S08PacketPlayerPosLook) p;
|
||||
final SPacketPlayerPosLook ppl = (SPacketPlayerPosLook) p;
|
||||
|
||||
if (mc.currentScreen instanceof GuiDownloadTerrain) {
|
||||
// Close the world loading screen manually in case we swallow the packet
|
||||
@@ -422,17 +439,17 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
CameraEntity cent = replayHandler.getCameraEntity();
|
||||
|
||||
for (Object relative : ppl.func_179834_f()) {
|
||||
if (relative == S08PacketPlayerPosLook.EnumFlags.X
|
||||
|| relative == S08PacketPlayerPosLook.EnumFlags.Y
|
||||
|| relative == S08PacketPlayerPosLook.EnumFlags.Z) {
|
||||
for (SPacketPlayerPosLook.EnumFlags relative : ppl.getFlags()) {
|
||||
if (relative == SPacketPlayerPosLook.EnumFlags.X
|
||||
|| relative == SPacketPlayerPosLook.EnumFlags.Y
|
||||
|| relative == SPacketPlayerPosLook.EnumFlags.Z) {
|
||||
return null; // At least one of the coordinates is relative, so we don't care
|
||||
}
|
||||
}
|
||||
|
||||
if(cent != null) {
|
||||
if(!allowMovement && !((Math.abs(cent.posX - ppl.func_148932_c()) > TP_DISTANCE_LIMIT) ||
|
||||
(Math.abs(cent.posZ - ppl.func_148933_e()) > TP_DISTANCE_LIMIT))) {
|
||||
if(!allowMovement && !((Math.abs(cent.posX - ppl.getX()) > TP_DISTANCE_LIMIT) ||
|
||||
(Math.abs(cent.posZ - ppl.getZ()) > TP_DISTANCE_LIMIT))) {
|
||||
return null;
|
||||
} else {
|
||||
allowMovement = false;
|
||||
@@ -451,15 +468,15 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
CameraEntity cent = replayHandler.getCameraEntity();
|
||||
cent.setCameraPosition(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e());
|
||||
cent.setCameraPosition(ppl.getX(), ppl.getY(), ppl.getZ());
|
||||
return null;
|
||||
}
|
||||
}.call();
|
||||
}
|
||||
|
||||
if(p instanceof S2BPacketChangeGameState) {
|
||||
S2BPacketChangeGameState pg = (S2BPacketChangeGameState)p;
|
||||
int reason = pg.func_149138_c();
|
||||
if(p instanceof SPacketChangeGameState) {
|
||||
SPacketChangeGameState pg = (SPacketChangeGameState)p;
|
||||
int reason = pg.getGameState();
|
||||
|
||||
// only allow the following packets:
|
||||
// 1 - End raining
|
||||
@@ -473,7 +490,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
if (p instanceof S02PacketChat) {
|
||||
if (p instanceof SPacketChat) {
|
||||
if (!ReplayModReplay.instance.getCore().getSettingsRegistry().get(Setting.SHOW_CHAT)) {
|
||||
return null;
|
||||
}
|
||||
@@ -486,7 +503,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
this.ctx = ctx;
|
||||
ctx.attr(NetworkManager.attrKeyConnectionState).set(EnumConnectionState.PLAY);
|
||||
ctx.attr(NetworkManager.PROTOCOL_ATTRIBUTE_KEY).set(EnumConnectionState.PLAY);
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@@ -691,11 +708,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
protected Packet processPacketAsync(Packet p) {
|
||||
//If hurrying, ignore some packets, except for short durations
|
||||
if(desiredTimeStamp - lastTimeStamp > 1000) {
|
||||
if(p instanceof S2APacketParticles) return null;
|
||||
if(p instanceof SPacketParticles) return null;
|
||||
|
||||
if(p instanceof S0EPacketSpawnObject) {
|
||||
S0EPacketSpawnObject pso = (S0EPacketSpawnObject)p;
|
||||
int type = pso.func_148993_l();
|
||||
if(p instanceof SPacketSpawnObject) {
|
||||
SPacketSpawnObject pso = (SPacketSpawnObject)p;
|
||||
int type = pso.getType();
|
||||
if(type == 76) { // Firework rocket
|
||||
return null;
|
||||
}
|
||||
@@ -781,68 +798,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
return p; // During synchronous playback everything is sent normally
|
||||
}
|
||||
|
||||
/**
|
||||
* This is necessary to convert packets from old replays to new replays.
|
||||
* @param packet The packet to be transformed.
|
||||
* @see #LEGACY_ENTITY_ID
|
||||
*/
|
||||
private void convertLegacyEntityIds(Packet packet) {
|
||||
if (packet instanceof S0CPacketSpawnPlayer) {
|
||||
S0CPacketSpawnPlayer p = (S0CPacketSpawnPlayer) packet;
|
||||
if (p.field_148957_a == LEGACY_ENTITY_ID) {
|
||||
p.field_148957_a = actualID;
|
||||
}
|
||||
} else if (packet instanceof S18PacketEntityTeleport) {
|
||||
S18PacketEntityTeleport p = (S18PacketEntityTeleport) packet;
|
||||
if (p.field_149458_a == LEGACY_ENTITY_ID) {
|
||||
p.field_149458_a = actualID;
|
||||
}
|
||||
} else if (packet instanceof S14PacketEntity.S17PacketEntityLookMove) {
|
||||
S14PacketEntity.S17PacketEntityLookMove p = (S14PacketEntity.S17PacketEntityLookMove) packet;
|
||||
if (p.field_149074_a == LEGACY_ENTITY_ID) {
|
||||
p.field_149074_a = actualID;
|
||||
}
|
||||
} else if (packet instanceof S19PacketEntityHeadLook) {
|
||||
S19PacketEntityHeadLook p = (S19PacketEntityHeadLook) packet;
|
||||
if (p.field_149384_a == LEGACY_ENTITY_ID) {
|
||||
p.field_149384_a = actualID;
|
||||
}
|
||||
} else if (packet instanceof S12PacketEntityVelocity) {
|
||||
S12PacketEntityVelocity p = (S12PacketEntityVelocity) packet;
|
||||
if (p.field_149417_a == LEGACY_ENTITY_ID) {
|
||||
p.field_149417_a = actualID;
|
||||
}
|
||||
} else if (packet instanceof S0BPacketAnimation) {
|
||||
S0BPacketAnimation p = (S0BPacketAnimation) packet;
|
||||
if (p.entityId == LEGACY_ENTITY_ID) {
|
||||
p.entityId = actualID;
|
||||
}
|
||||
} else if (packet instanceof S04PacketEntityEquipment) {
|
||||
S04PacketEntityEquipment p = (S04PacketEntityEquipment) packet;
|
||||
if (p.field_149394_a == LEGACY_ENTITY_ID) {
|
||||
p.field_149394_a = actualID;
|
||||
}
|
||||
} else if (packet instanceof S1BPacketEntityAttach) {
|
||||
S1BPacketEntityAttach p = (S1BPacketEntityAttach) packet;
|
||||
if (p.field_149408_a == LEGACY_ENTITY_ID) {
|
||||
p.field_149408_a = actualID;
|
||||
}
|
||||
if (p.field_149406_b == LEGACY_ENTITY_ID) {
|
||||
p.field_149406_b = actualID;
|
||||
}
|
||||
} else if (packet instanceof S0DPacketCollectItem) {
|
||||
S0DPacketCollectItem p = (S0DPacketCollectItem) packet;
|
||||
if (p.field_149356_b == LEGACY_ENTITY_ID) {
|
||||
p.field_149356_b = actualID;
|
||||
}
|
||||
} else if (packet instanceof S13PacketDestroyEntities) {
|
||||
S13PacketDestroyEntities p = (S13PacketDestroyEntities) packet;
|
||||
if (p.field_149100_a.length == 1 && p.field_149100_a[0] == LEGACY_ENTITY_ID) {
|
||||
p.field_149100_a[0] = actualID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PacketData {
|
||||
private final int timestamp;
|
||||
private final byte[] bytes;
|
||||
|
||||
@@ -17,10 +17,12 @@ import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.item.EntityItemFrame;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.stats.StatFileWriter;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.inventory.EntityEquipmentSlot;
|
||||
import net.minecraft.stats.StatisticsManager;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.EntityViewRenderEvent;
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
@@ -64,8 +66,8 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
*/
|
||||
private final EventHandler eventHandler = new EventHandler();
|
||||
|
||||
public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) {
|
||||
super(mcIn, worldIn, netHandlerPlayClient, statFileWriter);
|
||||
public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatisticsManager statisticsManager) {
|
||||
super(mcIn, worldIn, netHandlerPlayClient, statisticsManager);
|
||||
FMLCommonHandler.instance().bus().register(eventHandler);
|
||||
MinecraftForge.EVENT_BUS.register(eventHandler);
|
||||
cameraController = ReplayModReplay.instance.createCameraController(this);
|
||||
@@ -256,12 +258,49 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovingObjectPosition rayTrace(double p_174822_1_, float p_174822_3_) {
|
||||
MovingObjectPosition pos = super.rayTrace(p_174822_1_, 1f);
|
||||
public float getCooldownPeriod() {
|
||||
Entity view = mc.getRenderViewEntity();
|
||||
if (view != this && view instanceof EntityPlayer) {
|
||||
return ((EntityPlayer) view).getCooldownPeriod();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCooledAttackStrength(float adjustTicks) {
|
||||
Entity view = mc.getRenderViewEntity();
|
||||
if (view != this && view instanceof EntityPlayer) {
|
||||
return ((EntityPlayer) view).getCooledAttackStrength(adjustTicks);
|
||||
}
|
||||
// Default to 1 as to not render the cooldown indicator (renders for < 1)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumHand getActiveHand() {
|
||||
Entity view = mc.getRenderViewEntity();
|
||||
if (view != this && view instanceof EntityPlayer) {
|
||||
return ((EntityPlayer) view).getActiveHand();
|
||||
}
|
||||
return super.getActiveHand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHandActive() {
|
||||
Entity view = mc.getRenderViewEntity();
|
||||
if (view != this && view instanceof EntityPlayer) {
|
||||
return ((EntityPlayer) view).isHandActive();
|
||||
}
|
||||
return super.isHandActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RayTraceResult rayTrace(double p_174822_1_, float p_174822_3_) {
|
||||
RayTraceResult pos = super.rayTrace(p_174822_1_, 1f);
|
||||
|
||||
// Make sure we can never look at blocks (-> no outline)
|
||||
if(pos != null && pos.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
|
||||
pos.typeOfHit = MovingObjectPosition.MovingObjectType.MISS;
|
||||
if(pos != null && pos.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
pos.typeOfHit = RayTraceResult.Type.MISS;
|
||||
}
|
||||
|
||||
return pos;
|
||||
@@ -328,9 +367,13 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
@SubscribeEvent
|
||||
public void preCrosshairRender(RenderGameOverlayEvent.Pre event) {
|
||||
// The crosshair should only render if targeted entity can actually be spectated
|
||||
if (event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS) {
|
||||
if (event.getType() == RenderGameOverlayEvent.ElementType.CROSSHAIRS) {
|
||||
event.setCanceled(!canSpectate(mc.pointedEntity));
|
||||
}
|
||||
// Hotbar should never be rendered
|
||||
if (event.getType() == RenderGameOverlayEvent.ElementType.HOTBAR) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -357,10 +400,13 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
if (lastHandRendered != player) {
|
||||
lastHandRendered = player;
|
||||
|
||||
mc.entityRenderer.itemRenderer.prevEquippedProgress = 1;
|
||||
mc.entityRenderer.itemRenderer.equippedProgress = 1;
|
||||
mc.entityRenderer.itemRenderer.itemToRender = player.inventory.getCurrentItem();
|
||||
mc.entityRenderer.itemRenderer.equippedItemSlot = player.inventory.currentItem;
|
||||
mc.entityRenderer.itemRenderer.prevEquippedProgressMainHand = 1;
|
||||
mc.entityRenderer.itemRenderer.prevEquippedProgressOffHand = 1;
|
||||
mc.entityRenderer.itemRenderer.equippedProgressMainHand = 1;
|
||||
mc.entityRenderer.itemRenderer.equippedProgressOffHand = 1;
|
||||
mc.entityRenderer.itemRenderer.itemStackMainHand = player.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND);
|
||||
mc.entityRenderer.itemRenderer.itemStackOffHand = player.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND);
|
||||
|
||||
|
||||
mc.thePlayer.renderArmYaw = mc.thePlayer.prevRenderArmYaw = player.rotationYaw;
|
||||
mc.thePlayer.renderArmPitch = mc.thePlayer.prevRenderArmPitch = player.rotationPitch;
|
||||
@@ -371,7 +417,7 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
@SubscribeEvent
|
||||
public void onEntityViewRenderEvent(EntityViewRenderEvent.CameraSetup event) {
|
||||
if (mc.getRenderViewEntity() == CameraEntity.this) {
|
||||
event.roll = roll;
|
||||
event.setRoll(roll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.replaymod.replay.camera;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.lwjgl.Sys;
|
||||
|
||||
// TODO: Marius is responsible for this. Please, someone clean it up.
|
||||
@@ -18,8 +18,8 @@ public class ClassicCameraController implements CameraController {
|
||||
private double THRESHOLD = MAX_SPEED / 20;
|
||||
private double DECAY = MAX_SPEED/3;
|
||||
|
||||
private Vec3 direction;
|
||||
private Vec3 dirBefore;
|
||||
private Vec3d direction;
|
||||
private Vec3d dirBefore;
|
||||
private double motion;
|
||||
private long lastCall = Sys.getTime();
|
||||
|
||||
@@ -129,7 +129,7 @@ public class ClassicCameraController implements CameraController {
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 movement = direction.normalize();
|
||||
Vec3d movement = direction.normalize();
|
||||
double factor = motion * (frac / 1000D);
|
||||
|
||||
camera.moveCamera(movement.xCoord * factor, movement.yCoord * factor, movement.zCoord * factor);
|
||||
@@ -158,7 +158,7 @@ public class ClassicCameraController implements CameraController {
|
||||
break;
|
||||
}
|
||||
|
||||
Vec3 dbf = direction;
|
||||
Vec3d dbf = direction;
|
||||
|
||||
if(dirBefore != null) {
|
||||
direction = dirBefore.normalize().add(direction);
|
||||
@@ -169,12 +169,12 @@ public class ClassicCameraController implements CameraController {
|
||||
updateMovement();
|
||||
}
|
||||
|
||||
private Vec3 getVectorForRotation(float pitch, float yaw) {
|
||||
private Vec3d getVectorForRotation(float pitch, float yaw) {
|
||||
float f2 = MathHelper.cos(-yaw * 0.017453292F - (float) Math.PI);
|
||||
float f3 = MathHelper.sin(-yaw * 0.017453292F - (float)Math.PI);
|
||||
float f4 = -MathHelper.cos(-pitch * 0.017453292F);
|
||||
float f5 = MathHelper.sin(-pitch * 0.017453292F);
|
||||
return new Vec3((double)(f3 * f4), (double)f5, (double)(f2 * f4));
|
||||
return new Vec3d((double)(f3 * f4), (double)f5, (double)(f2 * f4));
|
||||
}
|
||||
|
||||
public enum MoveDirection {
|
||||
|
||||
@@ -41,8 +41,9 @@ public class SpectatorCameraController implements CameraController {
|
||||
if (view instanceof EntityPlayer) {
|
||||
EntityPlayer viewPlayer = (EntityPlayer) view;
|
||||
camera.inventory = viewPlayer.inventory;
|
||||
camera.itemInUse = viewPlayer.itemInUse;
|
||||
camera.itemInUseCount = viewPlayer.itemInUseCount;
|
||||
camera.itemStackMainHand = viewPlayer.itemStackMainHand;
|
||||
camera.swingingHand = viewPlayer.swingingHand;
|
||||
camera.activeItemStackUseCount = viewPlayer.activeItemStackUseCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@ package com.replaymod.replay.gui.overlay;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.replay.ReplayHandler;
|
||||
import com.replaymod.replaystudio.data.Marker;
|
||||
import com.replaymod.replaystudio.util.Location;
|
||||
import de.johni0702.minecraft.gui.GuiRenderer;
|
||||
import de.johni0702.minecraft.gui.RenderInfo;
|
||||
import de.johni0702.minecraft.gui.element.advanced.AbstractGuiTimeline;
|
||||
import de.johni0702.minecraft.gui.function.Draggable;
|
||||
import com.replaymod.replaystudio.data.Marker;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.lwjgl.util.Point;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
import org.lwjgl.util.ReadablePoint;
|
||||
|
||||
@@ -14,7 +14,6 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GuiHandler {
|
||||
private static final int BUTTON_EXIT_SERVER = 1;
|
||||
@@ -41,7 +40,7 @@ public class GuiHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void injectIntoIngameMenu(GuiScreenEvent.InitGuiEvent.Post event) {
|
||||
if (!(event.gui instanceof GuiIngameMenu)) {
|
||||
if (!(event.getGui() instanceof GuiIngameMenu)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -49,9 +48,7 @@ public class GuiHandler {
|
||||
// Pause replay when menu is opened
|
||||
mod.getReplayHandler().getReplaySender().setReplaySpeed(0);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<GuiButton> buttonList = event.buttonList;
|
||||
for(GuiButton b : new ArrayList<>(buttonList)) {
|
||||
for(GuiButton b : new ArrayList<>(event.getButtonList())) {
|
||||
switch (b.id) {
|
||||
// Replace "Exit Server" button with "Exit Replay" button
|
||||
case BUTTON_EXIT_SERVER:
|
||||
@@ -62,7 +59,7 @@ public class GuiHandler {
|
||||
case BUTTON_ACHIEVEMENTS:
|
||||
case BUTTON_STATS:
|
||||
case BUTTON_OPEN_TO_LAN:
|
||||
buttonList.remove(b);
|
||||
event.getButtonList().remove(b);
|
||||
}
|
||||
// Move all buttons except the "Return to game" button upwards
|
||||
if (b.id != BUTTON_RETURN_TO_GAME) {
|
||||
@@ -74,31 +71,29 @@ public class GuiHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void injectIntoMainMenu(GuiScreenEvent.InitGuiEvent event) {
|
||||
if (!(event.gui instanceof GuiMainMenu)) {
|
||||
if (!(event.getGui() instanceof GuiMainMenu)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<GuiButton> buttonList = event.buttonList;
|
||||
GuiButton button = new GuiButton(BUTTON_REPLAY_VIEWER, event.gui.width / 2 - 100,
|
||||
event.gui.height / 4 + 10 + 3 * 24, I18n.format("replaymod.gui.replayviewer"));
|
||||
GuiButton button = new GuiButton(BUTTON_REPLAY_VIEWER, event.getGui().width / 2 - 100,
|
||||
event.getGui().height / 4 + 10 + 3 * 24, I18n.format("replaymod.gui.replayviewer"));
|
||||
button.width = button.width / 2 - 2;
|
||||
buttonList.add(button);
|
||||
event.getButtonList().add(button);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onButton(GuiScreenEvent.ActionPerformedEvent.Pre event) {
|
||||
if(!event.button.enabled) return;
|
||||
if(!event.getButton().enabled) return;
|
||||
|
||||
if (event.gui instanceof GuiMainMenu) {
|
||||
if (event.button.id == BUTTON_REPLAY_VIEWER) {
|
||||
if (event.getGui() instanceof GuiMainMenu) {
|
||||
if (event.getButton().id == BUTTON_REPLAY_VIEWER) {
|
||||
new GuiReplayViewer(mod).display();
|
||||
}
|
||||
}
|
||||
|
||||
if (event.gui instanceof GuiIngameMenu && mod.getReplayHandler() != null) {
|
||||
if (event.button.id == BUTTON_EXIT_REPLAY) {
|
||||
event.button.enabled = false;
|
||||
if (event.getGui() instanceof GuiIngameMenu && mod.getReplayHandler() != null) {
|
||||
if (event.getButton().id == BUTTON_EXIT_REPLAY) {
|
||||
event.getButton().enabled = false;
|
||||
mc.displayGuiScreen(new GuiMainMenu());
|
||||
try {
|
||||
mod.getReplayHandler().endReplay();
|
||||
|
||||
@@ -12,12 +12,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(GuiSpectator.class)
|
||||
public abstract class MixinGuiSpectator {
|
||||
@Shadow
|
||||
private Minecraft field_175268_g;
|
||||
private Minecraft mc;
|
||||
|
||||
@Inject(method = "func_175260_a", at = @At("HEAD"), cancellable = true)
|
||||
@Inject(method = "onHotbarSelected", at = @At("HEAD"), cancellable = true)
|
||||
public void isInReplay(int i, CallbackInfo ci) {
|
||||
// Prevent spectator gui from opening while in a replay
|
||||
if (field_175268_g.thePlayer instanceof CameraEntity) {
|
||||
if (mc.thePlayer instanceof CameraEntity) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.replaymod.replay.mixin;
|
||||
|
||||
import com.replaymod.replay.camera.CameraEntity;
|
||||
import com.replaymod.replay.ReplayModReplay;
|
||||
import com.replaymod.replay.camera.CameraEntity;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.multiplayer.PlayerControllerMP;
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.stats.StatFileWriter;
|
||||
import net.minecraft.stats.StatisticsManager;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -21,12 +21,12 @@ public abstract class MixinPlayerControllerMP {
|
||||
private Minecraft mc;
|
||||
|
||||
@Shadow
|
||||
private NetHandlerPlayClient netClientHandler;
|
||||
private NetHandlerPlayClient connection;
|
||||
|
||||
@Inject(method = "func_178892_a", at=@At("HEAD"), cancellable = true)
|
||||
private void replayModReplay_createReplayCamera(World worldIn, StatFileWriter statFileWriter, CallbackInfoReturnable<EntityPlayerSP> ci) {
|
||||
@Inject(method = "createClientPlayer", at=@At("HEAD"), cancellable = true)
|
||||
private void replayModReplay_createReplayCamera(World worldIn, StatisticsManager statisticsManager, CallbackInfoReturnable<EntityPlayerSP> ci) {
|
||||
if (ReplayModReplay.instance.getReplayHandler() != null) {
|
||||
ci.setReturnValue(new CameraEntity(mc, worldIn, netClientHandler, statFileWriter));
|
||||
ci.setReturnValue(new CameraEntity(mc, worldIn, connection, statisticsManager));
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.replaymod.replay.mixin;
|
||||
|
||||
import com.replaymod.replay.camera.CameraEntity;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.entity.ArmorStandRenderer;
|
||||
import net.minecraft.client.renderer.entity.RenderArmorStand;
|
||||
import net.minecraft.entity.item.EntityArmorStand;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -10,9 +10,9 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ArmorStandRenderer.class)
|
||||
public abstract class MixinArmorStandRenderer {
|
||||
@Inject(method = "func_177099_b", at = @At("HEAD"), cancellable = true)
|
||||
@Mixin(RenderArmorStand.class)
|
||||
public abstract class MixinRenderArmorStand {
|
||||
@Inject(method = "canRenderName", at = @At("HEAD"), cancellable = true)
|
||||
private void replayModReplay_canRenderInvisibleName(EntityArmorStand entity, CallbackInfoReturnable<Boolean> ci) {
|
||||
EntityPlayer thePlayer = Minecraft.getMinecraft().thePlayer;
|
||||
if (thePlayer instanceof CameraEntity && entity.isInvisible()) {
|
||||
@@ -14,6 +14,7 @@ public abstract class MixinRenderArrow extends Render {
|
||||
super(renderManager);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) {
|
||||
// Force arrows to always render, otherwise they stop rendering when you get close to them
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.replaymod.replay.mixin;
|
||||
import com.replaymod.replay.ReplayHandler;
|
||||
import com.replaymod.replay.ReplayModReplay;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.entity.RenderItem;
|
||||
import net.minecraft.client.renderer.RenderItem;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.replaymod.replay.mixin;
|
||||
|
||||
import com.replaymod.replay.camera.CameraEntity;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.entity.RendererLivingEntity;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -11,8 +11,8 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(RendererLivingEntity.class)
|
||||
public abstract class MixinRendererLivingEntity {
|
||||
@Mixin(RenderLivingBase.class)
|
||||
public abstract class MixinRenderLivingBase {
|
||||
@Inject(method = "canRenderName", at = @At("HEAD"), cancellable = true)
|
||||
private void replayModReplay_canRenderInvisibleName(EntityLivingBase entity, CallbackInfoReturnable<Boolean> ci) {
|
||||
EntityPlayer thePlayer = Minecraft.getMinecraft().thePlayer;
|
||||
@@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(TileEntityEndPortalRenderer.class)
|
||||
public class MixinTileEntityEndPortalRenderer {
|
||||
@Redirect(method = "func_180544_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getSystemTime()J"))
|
||||
@Redirect(method = "renderTileEntityAt", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getSystemTime()J"))
|
||||
private long replayModReplay_getEnchantmentTime() {
|
||||
ReplayHandler replayHandler = ReplayModReplay.instance.getReplayHandler();
|
||||
if (replayHandler != null) {
|
||||
|
||||
@@ -5,8 +5,8 @@ import net.minecraft.client.renderer.RenderGlobal;
|
||||
import net.minecraft.client.renderer.ViewFrustum;
|
||||
import net.minecraft.client.renderer.chunk.IRenderChunkFactory;
|
||||
import net.minecraft.client.renderer.chunk.RenderChunk;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -31,7 +31,7 @@ public abstract class MixinViewFrustum {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instead of calling {@link RenderChunk#setPosition(BlockPos)} we recreate the render chunk
|
||||
* Instead of calling {@link RenderChunk#setOrigin(int, int, int)} we recreate the render chunk
|
||||
* which seems to solve the problem that chunks are invisible when you leave an area and return
|
||||
* to it.
|
||||
* Any better fixes are welcome.
|
||||
@@ -48,17 +48,18 @@ public abstract class MixinViewFrustum {
|
||||
int k = this.countChunksX * 16;
|
||||
|
||||
for (int l = 0; l < this.countChunksX; ++l) {
|
||||
int i1 = this.func_178157_a(i, k, l);
|
||||
int i1 = this.getBaseCoordinate(i, k, l);
|
||||
for (int j1 = 0; j1 < this.countChunksZ; ++j1) {
|
||||
int k1 = this.func_178157_a(j, k, j1);
|
||||
int k1 = this.getBaseCoordinate(j, k, j1);
|
||||
for (int l1 = 0; l1 < this.countChunksY; ++l1) {
|
||||
int i2 = l1 * 16;
|
||||
RenderChunk renderchunk = this.renderChunks[(j1 * this.countChunksY + l1) * this.countChunksX + l];
|
||||
BlockPos blockpos = new BlockPos(i1, i2, k1);
|
||||
if (!blockpos.equals(renderchunk.getPosition())) {
|
||||
// Recreate render chunk instead of setting its position
|
||||
renderChunks[(j1 * this.countChunksY + l1) * this.countChunksX + l] =
|
||||
renderChunkFactory.makeRenderChunk(world, renderGlobal, blockpos, 0);
|
||||
(renderChunks[(j1 * this.countChunksY + l1) * this.countChunksX + l] =
|
||||
renderChunkFactory.create(world, renderGlobal, 0)
|
||||
).setOrigin(blockpos.getX(), blockpos.getY(), blockpos.getZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,5 +67,5 @@ public abstract class MixinViewFrustum {
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@Shadow abstract int func_178157_a(int p_178157_1_, int p_178157_2_, int p_178157_3_);
|
||||
@Shadow abstract int getBaseCoordinate(int p_178157_1_, int p_178157_2_, int p_178157_3_);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user