Skip to content

Commit

Permalink
Restructure the project, process feedback by Sheikah in #142
Browse files Browse the repository at this point in the history
  • Loading branch information
Garanas committed May 7, 2024
1 parent a8e7303 commit 43c0572
Show file tree
Hide file tree
Showing 24 changed files with 240 additions and 251 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.faforever.commons.replay;

import com.faforever.commons.replay.body.Body;
import com.faforever.commons.replay.header.Header;
import com.faforever.commons.replay.body.ReplayBody;
import com.faforever.commons.replay.header.ReplayHeader;

public record ReplayContainer(ReplayMetadata metadata, Header header, Body body, byte[] bytes) {
public record ReplayContainer(ReplayMetadata metadata, ReplayHeader header, ReplayBody body, byte[] bytes) {
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.faforever.commons.replay;

import com.faforever.commons.replay.body.parse.Event;
import com.faforever.commons.replay.body.ReplayBodyEvent;
import com.faforever.commons.replay.semantics.ChatMessage;
import com.faforever.commons.replay.semantics.ModeratorEvent;
import com.faforever.commons.replay.shared.LuaTable;
import com.faforever.commons.replay.body.parse.Parser;
import com.faforever.commons.replay.body.token.Token;
import com.faforever.commons.replay.body.token.Tokenizer;
import com.faforever.commons.replay.body.ReplayBodyParser;
import com.faforever.commons.replay.body.ReplayBodyToken;
import com.faforever.commons.replay.body.ReplayBodyTokenizer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.BaseEncoding;
Expand Down Expand Up @@ -67,10 +69,10 @@ public class ReplayDataParser {
private List<GameOption> gameOptions;

@Getter
private List<Token> tokens;
private List<ReplayBodyToken> tokens;

@Getter
private List<Event> events;
private List<ReplayBodyEvent> events;

public ReplayDataParser(Path path, ObjectMapper objectMapper) throws IOException, CompressorException {
this.path = path;
Expand Down Expand Up @@ -212,38 +214,38 @@ private void parseHeader(LittleEndianDataInputStream dataStream) throws IOExcept
randomSeed = dataStream.readInt();
}

private void interpretEvents(List<Event> events) {
private void interpretEvents(List<ReplayBodyEvent> events) {
Integer player = -1;
boolean desync = false;
String previousChecksum = null;
int previousTick = -1;

Map<Integer, Integer> lastTicks = new HashMap<>();

for (Event event : events) {
for (ReplayBodyEvent event : events) {

switch (event) {
case Event.Unprocessed(Token token, String reason) -> {
case ReplayBodyEvent.Unprocessed(ReplayBodyToken token, String reason) -> {

}

case Event.ProcessingError(Token token, Exception exception) -> {
case ReplayBodyEvent.ProcessingError(ReplayBodyToken token, Exception exception) -> {

}

case Event.Advance(int ticksToAdvance) -> {
case ReplayBodyEvent.Advance(int ticksToAdvance) -> {
ticks += ticksToAdvance;
}

case Event.SetCommandSource(int playerIndex) -> {
case ReplayBodyEvent.SetCommandSource(int playerIndex) -> {
player = playerIndex;
}

case Event.CommandSourceTerminated() -> {
case ReplayBodyEvent.CommandSourceTerminated() -> {
lastTicks.put(player, ticks);
}

case Event.VerifyChecksum(String hash, int tick) -> {
case ReplayBodyEvent.VerifyChecksum(String hash, int tick) -> {
desync = tick == previousTick && !Objects.equals(previousChecksum, hash);
previousChecksum = hash;
previousTick = ticks;
Expand All @@ -254,105 +256,105 @@ private void interpretEvents(List<Event> events) {
}
}

case Event.RequestPause() -> {
case ReplayBodyEvent.RequestPause() -> {

}

case Event.RequestResume() -> {
case ReplayBodyEvent.RequestResume() -> {

}

case Event.SingleStep() -> {
case ReplayBodyEvent.SingleStep() -> {

}

case Event.CreateUnit(int playerIndex, String blueprintId, float px, float pz, float heading) -> {
case ReplayBodyEvent.CreateUnit(int playerIndex, String blueprintId, float px, float pz, float heading) -> {

}

case Event.CreateProp(String blueprintId, float px, float pz, float heading) -> {
case ReplayBodyEvent.CreateProp(String blueprintId, float px, float pz, float heading) -> {

}

case Event.DestroyEntity(int entityId) -> {
case ReplayBodyEvent.DestroyEntity(int entityId) -> {

}

case Event.WarpEntity(int entityId, float px, float py, float pz) -> {
case ReplayBodyEvent.WarpEntity(int entityId, float px, float py, float pz) -> {

}

case Event.ProcessInfoPair(int entityId, String arg1, String arg2) -> {
case ReplayBodyEvent.ProcessInfoPair(int entityId, String arg1, String arg2) -> {

}

case Event.IssueCommand(Event.CommandUnits commandUnits, Event.CommandData commandData) -> {
case ReplayBodyEvent.IssueCommand(ReplayBodyEvent.CommandUnits commandUnits, ReplayBodyEvent.CommandData commandData) -> {
commandsPerMinuteByPlayer
.computeIfAbsent(player, p -> new HashMap<>())
.computeIfAbsent(ticks, t -> new AtomicInteger())
.incrementAndGet();
}

case Event.IssueFactoryCommand(
Event.CommandUnits commandUnits, Event.CommandData commandData
case ReplayBodyEvent.IssueFactoryCommand(
ReplayBodyEvent.CommandUnits commandUnits, ReplayBodyEvent.CommandData commandData
) -> {
commandsPerMinuteByPlayer
.computeIfAbsent(player, p -> new HashMap<>())
.computeIfAbsent(ticks, t -> new AtomicInteger())
.incrementAndGet();
}

case Event.IncreaseCommandCount(int commandId, int delta) -> {
case ReplayBodyEvent.IncreaseCommandCount(int commandId, int delta) -> {

}

case Event.DecreaseCommandCount(int commandId, int delta) -> {
case ReplayBodyEvent.DecreaseCommandCount(int commandId, int delta) -> {

}

case Event.SetCommandTarget(int commandId, Event.CommandTarget commandTarget) -> {
case ReplayBodyEvent.SetCommandTarget(int commandId, ReplayBodyEvent.CommandTarget commandTarget) -> {

}

case Event.SetCommandType(int commandId, int targetId) -> {
case ReplayBodyEvent.SetCommandType(int commandId, int targetId) -> {

}

case Event.SetCommandCells(int commandId, Object parametersLua, float px, float py, float pz) -> {
case ReplayBodyEvent.SetCommandCells(int commandId, Object parametersLua, float px, float py, float pz) -> {

}

case Event.RemoveCommandFromQueue(int commandId, int unitId) -> {
case ReplayBodyEvent.RemoveCommandFromQueue(int commandId, int unitId) -> {

}

case Event.DebugCommand() -> {
case ReplayBodyEvent.DebugCommand() -> {

}

case Event.ExecuteLuaInSim(String luaCode) -> {
case ReplayBodyEvent.ExecuteLuaInSim(String luaCode) -> {

}

case Event.LuaSimCallback(
String func, LuaTable.Table parametersLua, Event.CommandUnits commandUnits
case ReplayBodyEvent.LuaSimCallback(
String func, LuaTable.Table parametersLua, ReplayBodyEvent.CommandUnits commandUnits
) when func.equals("GiveResourcesToPlayer") -> {
parseGiveResourcesToPlayer(parametersLua);
}

case Event.LuaSimCallback(
String func, LuaTable.Table parametersLua, Event.CommandUnits commandUnits
case ReplayBodyEvent.LuaSimCallback(
String func, LuaTable.Table parametersLua, ReplayBodyEvent.CommandUnits commandUnits
) when func.equals("ModeratorEvent") -> {
parseModeratorEvent(parametersLua, player);
}

case Event.LuaSimCallback(
String func, LuaTable parametersLua, Event.CommandUnits commandUnits
case ReplayBodyEvent.LuaSimCallback(
String func, LuaTable parametersLua, ReplayBodyEvent.CommandUnits commandUnits
) -> {

}

case Event.EndGame() -> {
case ReplayBodyEvent.EndGame() -> {

}

Expand Down Expand Up @@ -443,9 +445,9 @@ private void parse() throws IOException, CompressorException {
readReplayData(path);
try (LittleEndianDataInputStream dataStream = new LittleEndianDataInputStream(new ByteArrayInputStream(data))) {
parseHeader(dataStream);
tokens = Tokenizer.tokenize(dataStream);
tokens = ReplayBodyTokenizer.tokenize(dataStream);
}
events = Parser.parseTokens(tokens);
events = ReplayBodyParser.parseTokens(tokens);
interpretEvents(events);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.faforever.commons.replay;

import com.faforever.commons.replay.body.Body;
import com.faforever.commons.replay.header.Header;
import com.faforever.commons.replay.header.parse.Parser;
import com.faforever.commons.replay.header.token.Token;
import com.faforever.commons.replay.header.token.Tokenizer;
import com.faforever.commons.replay.body.ReplayBody;
import com.faforever.commons.replay.body.ReplayBodyParser;
import com.faforever.commons.replay.body.ReplayBodyToken;
import com.faforever.commons.replay.body.ReplayBodyTokenizer;
import com.faforever.commons.replay.header.ReplayHeader;
import com.faforever.commons.replay.header.ReplayHeaderParser;
import com.faforever.commons.replay.header.ReplayHeaderToken;
import com.faforever.commons.replay.header.ReplayHeaderTokenizer;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.google.common.io.BaseEncoding;
import com.google.common.io.LittleEndianDataInputStream;
Expand All @@ -25,23 +28,23 @@
import java.util.List;
import java.util.Objects;

public class Replay {
public class ReplayLoader {

private static Header loadSCFAReplayHeader(LittleEndianDataInputStream stream) throws IOException{
Token headerToken = Tokenizer.tokenize(stream);
return Parser.parseHeader(headerToken);
private static ReplayHeader loadSCFAReplayHeader(LittleEndianDataInputStream stream) throws IOException{
ReplayHeaderToken headerToken = ReplayHeaderTokenizer.tokenize(stream);
return ReplayHeaderParser.parseHeader(headerToken);
}

private static Body loadSCFAReplayBody(LittleEndianDataInputStream stream) throws IOException{
List<com.faforever.commons.replay.body.token.Token> bodyTokens = com.faforever.commons.replay.body.token.Tokenizer.tokenize(stream);
return new Body(com.faforever.commons.replay.body.parse.Parser.parseTokens(bodyTokens));
private static ReplayBody loadSCFAReplayBody(LittleEndianDataInputStream stream) throws IOException{
List<ReplayBodyToken> bodyTokens = ReplayBodyTokenizer.tokenize(stream);
return new ReplayBody(ReplayBodyParser.parseTokens(bodyTokens));
}

private static ReplayContainer loadSCFAReplayFromMemory(ReplayMetadata metadata, ReplayBinaryFormat.BinarySCFA bytes) throws IOException {
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream((new ByteArrayInputStream(bytes.bytes())))) {
Header replayHead = loadSCFAReplayHeader(stream);
Body replayBody = loadSCFAReplayBody(stream);
return new ReplayContainer(metadata, replayHead, replayBody, bytes.bytes());
private static ReplayContainer loadSCFAReplayFromMemory(ReplayMetadata metadata, byte[] scfaReplayBytes) throws IOException {
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream((new ByteArrayInputStream(scfaReplayBytes)))) {
ReplayHeader replayHeader = loadSCFAReplayHeader(stream);
ReplayBody replayBody = loadSCFAReplayBody(stream);
return new ReplayContainer(metadata, replayHeader, replayBody, scfaReplayBytes);
}
}

Expand All @@ -51,30 +54,30 @@ public static ReplayContainer loadSCFAReplayFromDisk(Path scfaReplayFile) throw
}

byte[] bytes = Files.readAllBytes(scfaReplayFile);
return loadSCFAReplayFromMemory(null, new ReplayBinaryFormat.BinarySCFA(bytes));
return loadSCFAReplayFromMemory(null, bytes);
}

private static ReplayContainer loadFAFReplayFromMemory(ReplayBinaryFormat.WithContext fafReplayBytes) throws IOException, CompressorException {
int separator = findSeparatorIndex(fafReplayBytes.bytes());
byte[] metadataBytes = Arrays.copyOfRange(fafReplayBytes.bytes(), 0, separator);
private static ReplayContainer loadFAFReplayFromMemory(byte[] fafReplayBytes) throws IOException, CompressorException {
int separator = findSeparatorIndex(fafReplayBytes);
byte[] metadataBytes = Arrays.copyOfRange(fafReplayBytes, 0, separator);
String metadataString = new String(metadataBytes, StandardCharsets.UTF_8);

ObjectMapper parsedMetadata = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ReplayMetadata replayMetadata = parsedMetadata.readValue(metadataString, ReplayMetadata.class);

byte[] compressedReplayBytes = Arrays.copyOfRange(fafReplayBytes.bytes(), separator + 1, fafReplayBytes.bytes().length);
byte[] replayBytes = decompress(compressedReplayBytes, replayMetadata);
byte[] compressedReplayBytes = Arrays.copyOfRange(fafReplayBytes, separator + 1, fafReplayBytes.length);
byte[] scfaReplayBytes = decompress(compressedReplayBytes, replayMetadata);

return loadSCFAReplayFromMemory(replayMetadata, new ReplayBinaryFormat.BinarySCFA(replayBytes));
return loadSCFAReplayFromMemory(replayMetadata, scfaReplayBytes);
}

public static ReplayContainer loadFAFReplayFromDisk(Path fafReplayFile) throws IOException, CompressorException, IllegalArgumentException {
if (!fafReplayFile.toString().toLowerCase().endsWith("fafreplay")) {
throw new IllegalArgumentException ("Unknown file format: " + fafReplayFile.getFileName());
}

byte[] replayBytes = Files.readAllBytes(fafReplayFile);
return loadFAFReplayFromMemory(new ReplayBinaryFormat.WithContext(replayBytes));
byte[] fafReplayBytes = Files.readAllBytes(fafReplayFile);
return loadFAFReplayFromMemory(fafReplayBytes);
}

private static int findSeparatorIndex(byte[] replayData) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.faforever.commons.replay.body;

import java.util.List;

public record ReplayBody(List<ReplayBodyEvent> events) {
}
Loading

0 comments on commit 43c0572

Please sign in to comment.