Introduce minimal mode (allows RM to run on unsupported MC versions)

by disabling various version-specific features (i.e. everything which
requires the ReplayStudio).
This commit is contained in:
Jonas Herzig
2019-06-20 16:50:33 +02:00
parent 357501e5db
commit af55951f42
13 changed files with 195 additions and 36 deletions

View File

@@ -83,6 +83,7 @@ import java.util.List;
import java.util.Map;
import static com.replaymod.core.versions.MCVer.*;
import static com.replaymod.replaystudio.util.Utils.readInt;
/**
* Sends replay packets to netty channels.
@@ -1102,26 +1103,37 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
private final byte[] bytes;
PacketData(ReplayInputStream in, boolean loginPhase) throws IOException {
com.replaymod.replaystudio.PacketData data = in.readPacket();
timestamp = (int) data.getTime();
// We need to re-encode MCProtocolLib packets, so we can later decode them as NMS packets
// The main reason we aren't reading them as NMS packets is that we want ReplayStudio to be able
// to apply ViaVersion (and potentially other magic) to it.
synchronized (byteBuf) {
byteBuf.markReaderIndex(); // Mark the current reader and writer index (should be at start)
byteBuf.markWriterIndex();
try {
(loginPhase ? codecLoginPhase : codecPlayPhase).encode(null, data.getPacket(), byteBuf);
} catch (Exception e) {
throw new IOException(e);
if (ReplayMod.isMinimalMode()) {
// Minimal mode, we can only read our exact protocol version and cannot use ReplayStudio
timestamp = readInt(in);
int length = readInt(in);
if (timestamp == -1 || length == -1) {
throw new EOFException();
}
bytes = new byte[length];
IOUtils.readFully(in, bytes);
} else {
com.replaymod.replaystudio.PacketData data = in.readPacket();
timestamp = (int) data.getTime();
// We need to re-encode MCProtocolLib packets, so we can later decode them as NMS packets
// The main reason we aren't reading them as NMS packets is that we want ReplayStudio to be able
// to apply ViaVersion (and potentially other magic) to it.
synchronized (byteBuf) {
byteBuf.markReaderIndex(); // Mark the current reader and writer index (should be at start)
byteBuf.markWriterIndex();
bytes = new byte[byteBuf.readableBytes()]; // Create bytes array of sufficient size
byteBuf.readBytes(bytes); // Read all data into bytes
try {
(loginPhase ? codecLoginPhase : codecPlayPhase).encode(null, data.getPacket(), byteBuf);
} catch (Exception e) {
throw new IOException(e);
}
byteBuf.resetReaderIndex(); // Reset reader & writer index for next use
byteBuf.resetWriterIndex();
bytes = new byte[byteBuf.readableBytes()]; // Create bytes array of sufficient size
byteBuf.readBytes(bytes); // Read all data into bytes
byteBuf.resetReaderIndex(); // Reset reader & writer index for next use
byteBuf.resetWriterIndex();
}
}
}
}

View File

@@ -314,6 +314,7 @@ public class ReplayHandler {
//#if MC>=10904
public void ensureQuickModeInitialized(Runnable andThen) {
if (Utils.ifMinimalModeDoPopup(overlay, () -> {})) return;
ListenableFuture<Void> future = quickReplaySender.getInitializationPromise();
if (future == null) {
InitializingQuickModePopup popup = new InitializingQuickModePopup(overlay);
@@ -365,6 +366,9 @@ public class ReplayHandler {
}
public void setQuickMode(boolean quickMode) {
if (ReplayMod.isMinimalMode()) {
throw new UnsupportedOperationException("Quick Mode not supported in minimal mode.");
}
if (quickMode == this.quickMode) return;
if (quickMode && fullReplaySender.isAsyncMode()) {
// If this method is called via runLater, then it cannot switch to sync mode by itself as there might be

View File

@@ -411,7 +411,7 @@ public class GuiReplayViewer extends GuiScreen {
} else {
server.setText(metaData.getServerName());
}
incompatible = !new ReplayStudio().isCompatible(metaData.getFileFormatVersion(), metaData.getProtocolVersion());
incompatible = !ReplayMod.isCompatible(metaData.getFileFormatVersion(), metaData.getProtocolVersion());
if (incompatible) {
version.setText("Minecraft " + metaData.getMcVersion());
}