Merge branch '1.9.4' into 1.10.2
4a1cceaMerge branch '1.8' into 1.9.4fb39a06Add drone ci config030c71cAutomatically disable and re-enable Optifine's Fast Render setting before rendering a video1fef12dInclude FML handshake in recordinge86c66dMove README.md, LICENSE.md and user docs from master branch to 1.8
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.replaymod.compat;
|
||||
|
||||
import com.replaymod.compat.optifine.DisableFastRender;
|
||||
import com.replaymod.compat.shaders.ShaderBeginRender;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
@@ -18,6 +19,7 @@ public class ReplayModCompat {
|
||||
public void init(FMLInitializationEvent event) {
|
||||
EventBus bus = MinecraftForge.EVENT_BUS;
|
||||
bus.register(new ShaderBeginRender());
|
||||
bus.register(new DisableFastRender());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.replaymod.compat.optifine;
|
||||
|
||||
import com.replaymod.render.events.ReplayRenderEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.fml.client.FMLClientHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
public class DisableFastRender {
|
||||
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private boolean wasFastRender = false;
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRenderBegin(ReplayRenderEvent.Pre event) {
|
||||
if (!FMLClientHandler.instance().hasOptifine()) return;
|
||||
|
||||
try {
|
||||
wasFastRender = (boolean) OptifineReflection.gameSettings_ofFastRender.get(mc.gameSettings);
|
||||
OptifineReflection.gameSettings_ofFastRender.set(mc.gameSettings, false);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRenderEnd(ReplayRenderEvent.Post event){
|
||||
if (!FMLClientHandler.instance().hasOptifine()) return;
|
||||
|
||||
try {
|
||||
OptifineReflection.gameSettings_ofFastRender.set(mc.gameSettings, wasFastRender);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.replaymod.compat.optifine;
|
||||
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class OptifineReflection {
|
||||
|
||||
// GameSettings.ofFastRender
|
||||
public static Field gameSettings_ofFastRender;
|
||||
|
||||
static {
|
||||
try {
|
||||
// this throws an ignored ClassNotFoundException if Optifine isn't installed
|
||||
Class.forName("Config");
|
||||
|
||||
gameSettings_ofFastRender = GameSettings.class.getDeclaredField("ofFastRender");
|
||||
gameSettings_ofFastRender.setAccessible(true);
|
||||
} catch (ClassNotFoundException ignore) {
|
||||
// no optifine installed
|
||||
} catch (NoSuchFieldException e) {
|
||||
// the field wasn't found. Has it been renamed?
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.replaymod.core.utils.Restrictions;
|
||||
import com.replaymod.recording.handler.ConnectionEventHandler;
|
||||
import com.replaymod.recording.packet.PacketListener;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
@@ -17,6 +18,9 @@ import org.lwjgl.input.Keyboard;
|
||||
public class ReplayModRecording {
|
||||
public static final String MOD_ID = "replaymod-recording";
|
||||
|
||||
@Mod.Instance(MOD_ID)
|
||||
public static ReplayModRecording instance;
|
||||
|
||||
@Mod.Instance(ReplayMod.MOD_ID)
|
||||
private static ReplayMod core;
|
||||
|
||||
@@ -49,4 +53,8 @@ public class ReplayModRecording {
|
||||
|
||||
NetworkRegistry.INSTANCE.newSimpleChannel(Restrictions.PLUGIN_CHANNEL);
|
||||
}
|
||||
|
||||
public void initiateRecording(NetworkManager networkManager) {
|
||||
connectionEventHandler.onConnectedToServerEvent(networkManager);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,10 @@ import com.replaymod.replaystudio.replay.ReplayFile;
|
||||
import com.replaymod.replaystudio.replay.ReplayMetaData;
|
||||
import com.replaymod.replaystudio.replay.ZipReplayFile;
|
||||
import com.replaymod.replaystudio.studio.ReplayStudio;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.world.WorldType;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent;
|
||||
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -45,10 +42,10 @@ public class ConnectionEventHandler {
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onConnectedToServerEvent(ClientConnectedToServerEvent event) {
|
||||
public void onConnectedToServerEvent(NetworkManager networkManager) {
|
||||
try {
|
||||
if(event.isLocal()) {
|
||||
boolean local = networkManager.isLocalChannel();
|
||||
if (local) {
|
||||
if (mc.getIntegratedServer().getEntityWorld().getWorldType() == WorldType.DEBUG_WORLD) {
|
||||
logger.info("Debug World recording is not supported.");
|
||||
return;
|
||||
@@ -64,9 +61,8 @@ public class ConnectionEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
NetworkManager nm = event.getManager();
|
||||
String worldName;
|
||||
if(event.isLocal()) {
|
||||
if (local) {
|
||||
worldName = mc.getIntegratedServer().getWorldName();
|
||||
} else if (Minecraft.getMinecraft().getCurrentServerData() != null) {
|
||||
worldName = Minecraft.getMinecraft().getCurrentServerData().serverIP;
|
||||
@@ -75,9 +71,6 @@ public class ConnectionEventHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
Channel channel = nm.channel();
|
||||
ChannelPipeline pipeline = channel.pipeline();
|
||||
|
||||
File folder = core.getReplayFolder();
|
||||
|
||||
String name = sdf.format(Calendar.getInstance().getTime());
|
||||
@@ -87,13 +80,13 @@ public class ConnectionEventHandler {
|
||||
replayFile.writeModInfo(ModCompat.getInstalledNetworkMods());
|
||||
|
||||
ReplayMetaData metaData = new ReplayMetaData();
|
||||
metaData.setSingleplayer(event.isLocal());
|
||||
metaData.setSingleplayer(local);
|
||||
metaData.setServerName(worldName);
|
||||
metaData.setGenerator("ReplayMod v" + ReplayMod.getContainer().getVersion());
|
||||
metaData.setDate(System.currentTimeMillis());
|
||||
metaData.setMcVersion(ReplayMod.getMinecraftVersion());
|
||||
packetListener = new PacketListener(replayFile, metaData);
|
||||
pipeline.addBefore(packetHandlerKey, "replay_recorder", packetListener);
|
||||
networkManager.channel().pipeline().addBefore(packetHandlerKey, "replay_recorder", packetListener);
|
||||
|
||||
recordingEventHandler = new RecordingEventHandler(packetListener);
|
||||
recordingEventHandler.register();
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.replaymod.recording.mixin;
|
||||
|
||||
import com.replaymod.recording.ReplayModRecording;
|
||||
import net.minecraft.client.network.NetHandlerLoginClient;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
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(NetHandlerLoginClient.class)
|
||||
public abstract class MixinNetHandlerLoginClient {
|
||||
|
||||
@Shadow
|
||||
private NetworkManager networkManager;
|
||||
|
||||
/**
|
||||
* Starts the recording right before switching into PLAY state.
|
||||
* We cannot use the {@link net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent}
|
||||
* as it only fires after the forge handshake.
|
||||
*/
|
||||
@Inject(method = "handleLoginSuccess", at=@At("HEAD"))
|
||||
public void replayModRecording_initiateRecording(CallbackInfo cb) {
|
||||
ReplayModRecording.instance.initiateRecording(networkManager);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.replaymod.recording.mixin;
|
||||
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
|
||||
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(value = NetworkDispatcher.class, remap = false)
|
||||
public abstract class MixinNetworkDispatcher {
|
||||
|
||||
@Shadow
|
||||
private EmbeddedChannel handshakeChannel;
|
||||
|
||||
/**
|
||||
* Always sets fml:isLocal to false.
|
||||
* This effectively removes the difference in the FML handshake between SP and MP
|
||||
* and forces the block/item ids, etc. to always be send.
|
||||
* This might have undesired side effects but at least it works at all.
|
||||
*/
|
||||
@Inject(method = "insertIntoChannel", at=@At("HEAD"))
|
||||
public void replayModRecording_forceIsLocalToFalse(CallbackInfo cb) {
|
||||
handshakeChannel.attr(NetworkDispatcher.IS_LOCAL).set(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.replaymod.render.events;
|
||||
|
||||
import com.replaymod.render.rendering.VideoRenderer;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ReplayRenderEvent extends Event {
|
||||
@Getter
|
||||
private final VideoRenderer videoRenderer;
|
||||
|
||||
public static class Pre extends ReplayRenderEvent {
|
||||
public Pre(VideoRenderer videoRenderer) {
|
||||
super(videoRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Post extends ReplayRenderEvent {
|
||||
public Post(VideoRenderer videoRenderer) {
|
||||
super(videoRenderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.replaymod.render.RenderSettings;
|
||||
import com.replaymod.render.ReplayModRender;
|
||||
import com.replaymod.render.VideoWriter;
|
||||
import com.replaymod.render.capturer.RenderInfo;
|
||||
import com.replaymod.render.events.ReplayRenderEvent;
|
||||
import com.replaymod.render.frame.RGBFrame;
|
||||
import com.replaymod.render.gui.GuiRenderingDone;
|
||||
import com.replaymod.render.gui.GuiVideoRenderer;
|
||||
@@ -22,6 +23,7 @@ import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.shader.Framebuffer;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.Timer;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.util.Dimension;
|
||||
@@ -86,6 +88,8 @@ public class VideoRenderer implements RenderInfo {
|
||||
* @return {@code true} if rendering was successful, {@code false} if the user aborted rendering (or the window was closed)
|
||||
*/
|
||||
public boolean renderVideo() {
|
||||
MinecraftForge.EVENT_BUS.post(new ReplayRenderEvent.Pre(this));
|
||||
|
||||
setup();
|
||||
|
||||
// Because this might take some time to prepare we'll render the GUI at least once to not confuse the user
|
||||
@@ -129,6 +133,9 @@ public class VideoRenderer implements RenderInfo {
|
||||
}
|
||||
|
||||
finish();
|
||||
|
||||
MinecraftForge.EVENT_BUS.post(new ReplayRenderEvent.Post(this));
|
||||
|
||||
return !cancelled;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user