Skip to content

Commit

Permalink
Implement some of the semantics that the client implemented manually
Browse files Browse the repository at this point in the history
  • Loading branch information
Garanas committed Jun 3, 2024
1 parent 9c1978d commit 96332c9
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.faforever.commons.replay;

import com.faforever.commons.replay.body.Event;
import com.faforever.commons.replay.header.GameMod;
import com.faforever.commons.replay.header.Source;
import com.faforever.commons.replay.shared.LuaData;

Expand All @@ -12,12 +13,19 @@

public class ReplaySemantics {

/**
* Small utility function to convert a tick to the equivalent game time.
*
* @param tick
* @return
*/
public static Duration tickToDuration(int tick) {
return Duration.ofSeconds(tick / 10);
}

/**
* Registers the events by attaching a tick and a source to them.
*
* @param sources All input sources of the replay
* @param events All events of the replay
* @return All events with the tick and input source attached
Expand All @@ -42,12 +50,39 @@ public static List<RegisteredEvent> registerEvents(List<Source> sources, List<Ev
}

/**
* Retrieves all events that are chat messages
* Retrieves the UID of all mods.
*
* @param replayContainer The replay to retrieve the UIDs from
* @return A list of UIDs
*/
public static List<String> getModUIDs(ReplayContainer replayContainer) {
return replayContainer.header().mods().stream().map(GameMod::uid).toList();
}

/**
* Retrieves the directory that contains the scenario file.
*
* @param replayContainer The replay to retrieve the folder from
* @return The directory that contains the scenario file
*/
public static String getMapFolder (ReplayContainer replayContainer) {
// /maps/SCMP_026/SCMP_026_script.lua
String pathToScenario = replayContainer.header().pathToScenario();
if (pathToScenario == null) {
return null;
}

// SCMP_026
return pathToScenario.split("/")[2];
}

/**
* Retrieves all events that are chat messages.
*
* @param events A list of events
* @return A list of events that are chat messages
*/
public static List<ChatMessage> findChatMessages(List<Source> sources, List<RegisteredEvent> events) {
public static List<ChatMessage> getChatMessages(List<Source> sources, List<RegisteredEvent> events) {
return events.stream().map((registeredEvent) -> switch (registeredEvent.event()) {

// TODO: the fact that we piggy-back on the 'GiveResourcesToPlayer' callback to embed chat messages is all wrong! We should instead introduce an alternative callback with the sole purpose to send messages.
Expand Down Expand Up @@ -100,12 +135,12 @@ public static List<ChatMessage> findChatMessages(List<Source> sources, List<Regi
}

/**
* Retrieves all events that are moderator related
* Retrieves all events that are related to moderation.
*
* @param events A list of events
* @return A list of events that are moderator related
* @return A list of events that are related to moderation
*/
public static List<ModeratorEvent> findModeratorMessages(List<Source> sources, List<RegisteredEvent> events) {
public static List<ModeratorEvent> getModeratorMessages(List<Source> sources, List<RegisteredEvent> events) {
return events.stream().map((registeredEvent) -> switch (registeredEvent.event()) {

// TODO: also read other interesting events, such as:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,28 @@

import java.util.Map;

public record GameScenario(String mapPath, Integer mapVersion, String mapDescription, String mapScript, String mapSave,
String mapName, Integer mapSizeX, Integer mapSizeZ, Integer reclaimMassValue,
Integer reclaimEnergyValue, GameOptions gameOptions,
Map<String, String> modOptions) {
/**
* @param mapScenarioPath "/maps/scmp_026/scmp_026_scenario.lua" , as defined in the game options
* @param mapBinaryPath "/maps/SCMP_026/SCMP_026.scmap" , as defined by the `map` field in `_scenario.lua`
* @param mapVersion Can be null for maps with no versioning (gpg maps)
* @param mapDescription Description of the map
* @param mapScriptPath "/maps/SCMP_026/SCMP_026_script.lua", as defined by the `script` field in `_scenario.lua`
* @param mapSavePath "/maps/SCMP_026/SCMP_026_save.lua", as defined by the `save` field in `_scenario.lua`
* @param mapName Name of the map
* @param mapSizeX Width of the (height)map, does not take into account reductions of playable area via map script
* @param mapSizeZ Height of the (height)map, does not take into account reductions of playable area via map script
* @param reclaimMassValue Total initial mass reclaim value of props, does not take into account wrecks
* @param reclaimEnergyValue Total initial energy reclaim value of props
* @param gameOptions Standard game options
* @param modOptions Options that originate from mods
*/
public record GameScenario(
String mapScenarioPath,
String mapBinaryPath,
Integer mapVersion,
String mapDescription,
String mapScriptPath, String mapSavePath,
String mapName, Integer mapSizeX, Integer mapSizeZ, Integer reclaimMassValue,
Integer reclaimEnergyValue, GameOptions gameOptions,
Map<String, String> modOptions) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,12 @@ public static ReplayHeader parse(LittleEndianDataInputStream dataStream) throws
if (gameScenario instanceof LuaData.Table table) {

// retrieve and manage the game options
String scenarioFile = null;
GameOptions gameOptions = null;
Map<String, String> modOptions = null;
if (table.value().get("Options") instanceof LuaData.Table optionsTable) {

scenarioFile = optionsTable.getString("ScenarioFile");
gameOptions = new GameOptions(
GameOptions.AutoTeams.findByKey(optionsTable.getString("AutoTeams")),
GameOptions.TeamLock.findByKey(optionsTable.getString("TeamLock")),
Expand Down Expand Up @@ -151,6 +153,7 @@ public static ReplayHeader parse(LittleEndianDataInputStream dataStream) throws
}

return new GameScenario(
scenarioFile,
table.getString("map"),
table.getInteger("map_version"),
table.getString("description"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void parseBinary01() throws CompressorException, IOException {
assertNoUnprocessedTokens(fafReplayContainer);
assertNoErrorTokens(fafReplayContainer);

List<ChatMessage> chatMessages = ReplaySemantics.findChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
List<ChatMessage> chatMessages = ReplaySemantics.getChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
assertEquals(106, chatMessages.size());
}
);
Expand All @@ -59,7 +59,7 @@ public void parseBinary02() throws CompressorException, IOException {
assertNoUnprocessedTokens(fafReplayContainer);
assertNoErrorTokens(fafReplayContainer);

List<ChatMessage> chatMessages = ReplaySemantics.findChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
List<ChatMessage> chatMessages = ReplaySemantics.getChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
assertEquals(2, chatMessages.size());
}
);
Expand All @@ -76,7 +76,7 @@ public void parseBinary03() throws CompressorException, IOException {
assertNoUnprocessedTokens(fafReplayContainer);
assertNoErrorTokens(fafReplayContainer);

List<ChatMessage> chatMessages = ReplaySemantics.findChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
List<ChatMessage> chatMessages = ReplaySemantics.getChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
assertEquals(1, chatMessages.size());
}
);
Expand All @@ -93,7 +93,7 @@ public void parseBinary04() throws CompressorException, IOException {
assertNoUnprocessedTokens(fafReplayContainer);
assertNoErrorTokens(fafReplayContainer);

List<ChatMessage> chatMessages = ReplaySemantics.findChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
List<ChatMessage> chatMessages = ReplaySemantics.getChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
assertEquals(7, chatMessages.size());
}
);
Expand All @@ -110,7 +110,7 @@ public void parseBinary05() throws CompressorException, IOException {
assertNoUnprocessedTokens(fafReplayContainer);
assertNoErrorTokens(fafReplayContainer);

List<ChatMessage> chatMessages = ReplaySemantics.findChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
List<ChatMessage> chatMessages = ReplaySemantics.getChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
assertEquals(0, chatMessages.size());
}
);
Expand All @@ -127,7 +127,7 @@ public void parseBinary06() throws CompressorException, IOException {
assertNoUnprocessedTokens(fafReplayContainer);
assertNoErrorTokens(fafReplayContainer);

List<ChatMessage> chatMessages = ReplaySemantics.findChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
List<ChatMessage> chatMessages = ReplaySemantics.getChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
assertEquals(0, chatMessages.size());
}
);
Expand All @@ -144,7 +144,7 @@ public void parseBinary07() throws CompressorException, IOException {
assertNoUnprocessedTokens(fafReplayContainer);
assertNoErrorTokens(fafReplayContainer);

List<ChatMessage> chatMessages = ReplaySemantics.findChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
List<ChatMessage> chatMessages = ReplaySemantics.getChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
assertEquals(3, chatMessages.size());
}
);
Expand All @@ -163,7 +163,7 @@ public void parseBinary08() throws CompressorException, IOException {
assertNoUnprocessedTokens(fafReplayContainer);
assertNoErrorTokens(fafReplayContainer);

List<ChatMessage> chatMessages = ReplaySemantics.findChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
List<ChatMessage> chatMessages = ReplaySemantics.getChatMessages(fafReplayContainer.header().sources(), fafReplayContainer.registeredEvents());
assertEquals(0, chatMessages.size());
}
);
Expand Down

0 comments on commit 96332c9

Please sign in to comment.