Split mod into core, recording, replay, render[todo], paths[todo] and extras[wip] modules

Move everything to com.replaymod package
Add KeyBindingRegistry and SettingsRegistry
Recreate settings GUI with new GUI API and dynamically from SettingsRegistry
Use ReplayFile from ReplayStudio
ReplayHandler is now object oriented
Add GuiOverlay, GuiSlider and GuiTexturedButton to GUI API
Rewrite both overlays to use new GUI API
Fix size capping in vertical and horizontal layout
Allow CustomLayouts to have parents
Fix tooltip rendering when close to screen border
Allow changing of columns in GridLayout
This commit is contained in:
johni0702
2015-10-03 17:36:03 +02:00
parent 8bd051eb27
commit f925d56ca2
141 changed files with 6294 additions and 5582 deletions

View File

@@ -1,7 +1,7 @@
package eu.crushedpixel.replaymod.mixin;
import com.replaymod.replay.CameraEntity;
import eu.crushedpixel.replaymod.renderer.SpectatorRenderer;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.settings.RenderOptions;
import eu.crushedpixel.replaymod.video.EntityRendererHandler;
import eu.crushedpixel.replaymod.video.capturer.CubicOpenGlFrameCapturer;
@@ -18,6 +18,7 @@ import net.minecraft.util.MovingObjectPosition;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.Project;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
@@ -25,6 +26,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(EntityRenderer.class)
public abstract class MixinEntityRenderer implements EntityRendererHandler.IEntityRenderer, EntityRendererHandler.GluPerspective {
@Shadow
public Minecraft mc;
private EntityRendererHandler handler;
private SpectatorRenderer spectatorRenderer = new SpectatorRenderer();
@@ -65,8 +69,8 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
if (options.getIgnoreCameraRotation()[1]) {
entity.prevRotationPitch = entity.rotationPitch = 0;
}
if (options.getIgnoreCameraRotation()[2]) {
ReplayHandler.setCameraTilt(0);
if (options.getIgnoreCameraRotation()[2] && entity instanceof CameraEntity) {
((CameraEntity) entity).roll = 0;
}
}
}
@@ -85,7 +89,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
orgPitch = entity.rotationPitch;
orgPrevYaw = entity.prevRotationYaw;
orgPrevPitch = entity.prevRotationPitch;
orgRoll = ReplayHandler.getCameraTilt();
orgRoll = entity instanceof CameraEntity ? ((CameraEntity) entity).roll : 0;
}
}
@@ -97,28 +101,31 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
entity.rotationPitch = orgPitch;
entity.prevRotationYaw = orgPrevYaw;
entity.prevRotationPitch = orgPrevPitch;
ReplayHandler.setCameraTilt(orgRoll);
if (entity instanceof CameraEntity) {
((CameraEntity) entity).roll = orgRoll;
}
}
}
@Inject(method = "renderHand", at = @At("HEAD"), cancellable = true)
private void renderSpectatorHand(float partialTicks, int renderPass, CallbackInfo ci) {
if (handler != null) {
if (handler.data instanceof CubicOpenGlFrameCapturer.Data) {
ci.cancel();
return; // No spectator hands during 360° view, we wouldn't even know where to put it
}
Entity currentEntity = Minecraft.getMinecraft().getRenderViewEntity();
if (!ReplayHandler.isCamera() && currentEntity instanceof EntityPlayer) {
renderPass = handler.data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0;
spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass);
}
} else if (ReplayHandler.isInReplay() && !ReplayHandler.isCamera()) {
Entity currentEntity = Minecraft.getMinecraft().getRenderViewEntity();
if (!ReplayHandler.isCamera() && currentEntity instanceof EntityPlayer) {
spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass);
}
}
// TODO
// if (handler != null) {
// if (handler.data instanceof CubicOpenGlFrameCapturer.Data) {
// ci.cancel();
// return; // No spectator hands during 360° view, we wouldn't even know where to put it
// }
// Entity currentEntity = Minecraft.getMinecraft().getRenderViewEntity();
// if (!ReplayHandler.isCameraView() && currentEntity instanceof EntityPlayer) {
// renderPass = handler.data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0;
// spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass);
// }
// } else if (ReplayHandler.isInReplay() && !ReplayHandler.isCameraView()) {
// Entity currentEntity = Minecraft.getMinecraft().getRenderViewEntity();
// if (!ReplayHandler.isCameraView() && currentEntity instanceof EntityPlayer) {
// spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass);
// }
// }
}
@Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/MovingObjectPosition;IF)V"))
@@ -242,8 +249,8 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
@Inject(method = "orientCamera", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;translate(FFF)V", shift = At.Shift.AFTER, ordinal = 3))
private void setupCameraRoll(float partialTicks, CallbackInfo ci) {
if (ReplayHandler.isInReplay()) {
GL11.glRotated(ReplayHandler.getCameraTilt(), 0D, 0D, 1D);
if (mc.getRenderViewEntity() instanceof CameraEntity) {
GL11.glRotated(((CameraEntity) mc.getRenderViewEntity()).roll, 0D, 0D, 1D);
}
}
}

View File

@@ -1,17 +1,22 @@
package eu.crushedpixel.replaymod.mixin;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import com.replaymod.replay.CameraEntity;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiSpectator;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(GuiSpectator.class)
public abstract class MixinGuiSpectator {
@Shadow
private Minecraft field_175268_g;
@Inject(method = "func_175260_a", at = @At("HEAD"), cancellable = true)
public void isInReplay(int i, CallbackInfo ci) {
if (ReplayHandler.isInReplay()) {
if (field_175268_g.thePlayer instanceof CameraEntity) {
ci.cancel();
}
}

View File

@@ -1,6 +1,5 @@
package eu.crushedpixel.replaymod.mixin;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SoundHandler;
import net.minecraft.entity.player.EntityPlayer;
@@ -12,6 +11,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
public class MixinMinecraft {
@Redirect(method = "runGameLoop", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/audio/SoundHandler;setListener(Lnet/minecraft/entity/player/EntityPlayer;F)V"))
public void setSoundSystemListener(SoundHandler soundHandler, EntityPlayer listener, float renderPartialTicks) {
soundHandler.setListener(ReplayHandler.isInReplay() ? ReplayHandler.getCameraEntity() : listener, renderPartialTicks);
//TODO might no longer be necessary?
// soundHandler.setListener(ReplayHandler.isInReplay() ? ReplayHandler.getCameraEntity() : listener, renderPartialTicks);
}
}

View File

@@ -1,52 +0,0 @@
package eu.crushedpixel.replaymod.mixin;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.play.server.S07PacketRespawn;
import net.minecraft.network.play.server.S38PacketPlayerListItem;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
@Mixin(NetHandlerPlayClient.class)
public abstract class MixinNetHandlerPlayClient {
/**
* Record the own player entity joining the world.
* We cannot use the {@link net.minecraftforge.event.entity.EntityJoinWorldEvent} because the entity id
* of the player is set afterwards and the tablist entry might not yet be sent.
* @param packet The packet
* @param ci Callback info
*/
@Inject(method = "handlePlayerListItem", at=@At("RETURN"))
public void recordOwnJoin(S38PacketPlayerListItem packet, CallbackInfo ci) {
if (ConnectionEventHandler.isRecording() && packet.func_179768_b() == S38PacketPlayerListItem.Action.ADD_PLAYER) {
@SuppressWarnings("unchecked")
List<S38PacketPlayerListItem.AddPlayerData> dataList = packet.func_179767_a();
for (S38PacketPlayerListItem.AddPlayerData data : dataList) {
if (data.func_179962_a().getId().equals(Minecraft.getMinecraft().thePlayer.getGameProfile().getId())) {
ReplayMod.recordingHandler.onPlayerJoin();
}
}
}
}
/**
* Record the own player entity respawning.
* We cannot use the {@link net.minecraftforge.event.entity.EntityJoinWorldEvent} because that would also include
* the first spawn which is already handled by {@link #recordOwnJoin(S38PacketPlayerListItem, CallbackInfo)}.
* @param packet The packet
* @param ci Callback info
*/
@Inject(method = "handleRespawn", at=@At("RETURN"))
public void recordOwnRespawn(S07PacketRespawn packet, CallbackInfo ci) {
if (ConnectionEventHandler.isRecording()) {
ReplayMod.recordingHandler.onPlayerRespawn();
}
}
}

View File

@@ -1,7 +1,7 @@
package eu.crushedpixel.replaymod.mixin;
import eu.crushedpixel.replaymod.entities.CameraEntity;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import com.replaymod.replay.CameraEntity;
import com.replaymod.replay.ReplayModReplay;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.PlayerControllerMP;
@@ -25,7 +25,7 @@ public abstract class MixinPlayerControllerMP {
@Inject(method = "func_178892_a", at=@At("HEAD"), cancellable = true)
public void createReplayCamera(World worldIn, StatFileWriter statFileWriter, CallbackInfoReturnable<EntityPlayerSP> ci) {
if (ReplayHandler.isInReplay()) {
if (ReplayModReplay.instance.getReplayHandler() != null) {
ci.setReturnValue(new CameraEntity(mc, worldIn, netClientHandler, statFileWriter));
ci.cancel();
}

View File

@@ -1,11 +1,8 @@
package eu.crushedpixel.replaymod.mixin;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import net.minecraft.client.renderer.culling.ICamera;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderArrow;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(RenderArrow.class)
@@ -14,8 +11,9 @@ public abstract class MixinRenderArrow extends Render {
super(renderManager);
}
@Override
public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) {
return ReplayHandler.isInReplay() || super.shouldRender(entity, camera, camX, camY, camZ);
}
// TODO
// @Override
// public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) {
// return ReplayHandler.isInReplay() || super.shouldRender(entity, camera, camX, camY, camZ);
// }
}

View File

@@ -1,32 +0,0 @@
package eu.crushedpixel.replaymod.mixin;
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
import eu.crushedpixel.replaymod.timer.EnchantmentTimer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.play.server.S25PacketBlockBreakAnim;
import net.minecraft.util.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(RenderGlobal.class)
public abstract class MixinRenderGlobal {
@Inject(method = "sendBlockBreakProgress", at = @At("HEAD"))
public void saveBlockBreakProgressPacket(int breakerId, BlockPos pos, int progress, CallbackInfo info) {
if(ConnectionEventHandler.isRecording()) {
EntityPlayer thePlayer = Minecraft.getMinecraft().thePlayer;
if(thePlayer != null && breakerId == thePlayer.getEntityId()) {
ConnectionEventHandler.insertPacket(new S25PacketBlockBreakAnim(breakerId, pos, progress));
}
}
}
@Redirect(method = "renderWorldBorder", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getSystemTime()J"))
private long getEnchantmentTime() {
return EnchantmentTimer.getEnchantmentTime();
}
}

View File

@@ -1,7 +1,5 @@
package eu.crushedpixel.replaymod.mixin;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.settings.ReplaySettings;
import eu.crushedpixel.replaymod.video.EntityRendererHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.RendererLivingEntity;
@@ -22,17 +20,19 @@ public abstract class MixinRendererLivingEntity {
ci.setReturnValue(false); //this calls the cancel method
}
if(ReplayHandler.isInReplay() && entity.isInvisible()
&& ReplaySettings.ReplayOptions.renderInvisible.getValue() == Boolean.FALSE) {
ci.setReturnValue(false);
}
// TODO
// if(ReplayHandler.isInReplay() && entity.isInvisible()
// && ReplaySettings.ReplayOptions.renderInvisible.getValue() == Boolean.FALSE) {
// ci.setReturnValue(false);
// }
}
@Redirect(method = "renderModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/EntityLivingBase;isInvisibleToPlayer(Lnet/minecraft/entity/player/EntityPlayer;)Z"))
private boolean shouldInvisibleNotBeRendered(EntityLivingBase entity, EntityPlayer thePlayer) {
if(ReplaySettings.ReplayOptions.renderInvisible.getValue() == Boolean.TRUE|| !ReplayHandler.isInReplay()) {
return entity.isInvisibleToPlayer(thePlayer);
}
// TODO
// if(ReplaySettings.ReplayOptions.renderInvisible.getValue() == Boolean.TRUE|| !ReplayHandler.isInReplay()) {
// return entity.isInvisibleToPlayer(thePlayer);
// }
return true; //the original method inverts the return value
}
}

View File

@@ -1,6 +1,5 @@
package eu.crushedpixel.replaymod.mixin;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.ViewFrustum;
import net.minecraft.client.renderer.chunk.IRenderChunkFactory;
@@ -39,9 +38,10 @@ public abstract class MixinViewFrustum {
*/
@Inject(method = "updateChunkPositions", at = @At("HEAD"), cancellable = true)
public void fixedUpdateChunkPositions(double viewEntityX, double viewEntityZ, CallbackInfo ci) {
if (!ReplayHandler.isInReplay()) {
return;
}
// TODO
// if (!ReplayHandler.isInReplay()) {
// return;
// }
int i = MathHelper.floor_double(viewEntityX) - 8;
int j = MathHelper.floor_double(viewEntityZ) - 8;