diff --git a/src/main/java/xyz/stachel/zombiesutils/ZombiesUtils.java b/src/main/java/xyz/stachel/zombiesutils/ZombiesUtils.java index 67ae4ff..0e7201a 100644 --- a/src/main/java/xyz/stachel/zombiesutils/ZombiesUtils.java +++ b/src/main/java/xyz/stachel/zombiesutils/ZombiesUtils.java @@ -7,11 +7,18 @@ import net.hypixel.modapi.packet.impl.clientbound.event.ClientboundLocationPacke import org.slf4j.Logger; import org.slf4j.LoggerFactory; import xyz.stachel.zombiesutils.config.Config; +import xyz.stachel.zombiesutils.game.GameManager; import xyz.stachel.zombiesutils.handlers.Location; import xyz.stachel.zombiesutils.handlers.Renderer; public class ZombiesUtils implements ModInitializer { + private static final GameManager gameManager = new GameManager(); + + public static GameManager getGameManager() { + return gameManager; + } + public static final String MOD_ID = "zombies-utils"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); diff --git a/src/main/java/xyz/stachel/zombiesutils/ZombiesUtilsClient.java b/src/main/java/xyz/stachel/zombiesutils/ZombiesUtilsClient.java new file mode 100644 index 0000000..b44b6de --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/ZombiesUtilsClient.java @@ -0,0 +1,39 @@ +package xyz.stachel.zombiesutils; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import net.minecraft.text.MutableText; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.text.TextColor; +import net.minecraft.util.Formatting; +import org.lwjgl.glfw.GLFW; +import xyz.stachel.zombiesutils.config.Configs; + +public class ZombiesUtilsClient implements ClientModInitializer { + public static boolean PLAYER_VISIBILITY_SWITCH; + + private static KeyBinding PLAYER_VISIBILITY_KEY; + + @Override + public void onInitializeClient() { + PLAYER_VISIBILITY_KEY = KeyBindingHelper.registerKeyBinding(new KeyBinding( + "key.zombies-utils.toggle_player_visibility", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_V, + "category.zombies-utils" + )); + ClientTickEvents.END_CLIENT_TICK.register(client -> { + while (PLAYER_VISIBILITY_KEY.wasPressed()) { + PLAYER_VISIBILITY_SWITCH = !PLAYER_VISIBILITY_SWITCH; + MutableText message = PLAYER_VISIBILITY_SWITCH ? + Text.translatable("key.zombies-utils.toggle_player_visibility.toggle_on").setStyle(Style.EMPTY.withColor(Formatting.GREEN).withBold(true)) : + Text.translatable("key.zombies-utils.toggle_player_visibility.toggle_off").setStyle(Style.EMPTY.withColor(Formatting.RED).withBold(true)); + client.player.sendMessage(message, false); + } + }); + } +} diff --git a/src/main/java/xyz/stachel/zombiesutils/config/Config.java b/src/main/java/xyz/stachel/zombiesutils/config/Config.java index ef298f6..2432c0b 100644 --- a/src/main/java/xyz/stachel/zombiesutils/config/Config.java +++ b/src/main/java/xyz/stachel/zombiesutils/config/Config.java @@ -13,6 +13,7 @@ import java.nio.file.Path; public final class Config { private static final Gson GSON = new GsonBuilder() .registerTypeAdapter(IntConfig.class, new IntConfig.Serializer()) + .registerTypeAdapter(DoubleConfig.class, new DoubleConfig.Serializer()) .excludeFieldsWithModifiers(Modifier.TRANSIENT) .setPrettyPrinting() .create(); @@ -33,6 +34,11 @@ public final class Config { var intValue = value.getAsInt(); ((IntConfig) field.get(null)).setValue(intValue); } + + if (DoubleConfig.class.isAssignableFrom(fieldType)) { + var doubleValue = value.getAsDouble(); + ((DoubleConfig) field.get(null)).setValue(doubleValue); + } } } } catch (Exception exception) { diff --git a/src/main/java/xyz/stachel/zombiesutils/config/Configs.java b/src/main/java/xyz/stachel/zombiesutils/config/Configs.java index bf72d08..65d3856 100644 --- a/src/main/java/xyz/stachel/zombiesutils/config/Configs.java +++ b/src/main/java/xyz/stachel/zombiesutils/config/Configs.java @@ -1,5 +1,5 @@ package xyz.stachel.zombiesutils.config; public class Configs { - public static final IntConfig playerVisibleDistance = IntConfig.of("playerVisibilityDistance", 0); + public static final DoubleConfig playerVisibleDistance = DoubleConfig.of("playerInvisibilityDistance", 0.8D); } diff --git a/src/main/java/xyz/stachel/zombiesutils/config/DoubleConfig.java b/src/main/java/xyz/stachel/zombiesutils/config/DoubleConfig.java new file mode 100644 index 0000000..74e6421 --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/config/DoubleConfig.java @@ -0,0 +1,39 @@ +package xyz.stachel.zombiesutils.config; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.client.gui.widget.CyclingButtonWidget; +import net.minecraft.text.Text; + +import java.lang.reflect.Type; + +public class DoubleConfig extends AbstractConfig { + + public DoubleConfig(String key, Double defaultValue) { + super(key, defaultValue); + } + + public static DoubleConfig of(String key, double defaultValue) { + return new DoubleConfig(key, defaultValue); + } + + @Override + public ClickableWidget createWidget(Runnable callback) { + return CyclingButtonWidget.builder((value) -> Text.of(getValue().toString())).initially(getValue()) + .tooltip(value -> getTooltip()) + .build(getMessage(), (button, value) -> { + setValue(value); + callback.run(); + }); + } + + public static class Serializer implements JsonSerializer { + @Override + public JsonElement serialize(DoubleConfig value, Type type, JsonSerializationContext context) { + return new JsonPrimitive(value.getValue()); + } + } +} diff --git a/src/main/java/xyz/stachel/zombiesutils/game/Game.java b/src/main/java/xyz/stachel/zombiesutils/game/Game.java index 52f7714..53575b1 100644 --- a/src/main/java/xyz/stachel/zombiesutils/game/Game.java +++ b/src/main/java/xyz/stachel/zombiesutils/game/Game.java @@ -5,15 +5,18 @@ import net.minecraft.text.Text; import org.apache.commons.lang3.exception.ExceptionUtils; import org.jetbrains.annotations.NotNull; import xyz.stachel.zombiesutils.ZombiesUtils; - -import java.io.File; +import xyz.stachel.zombiesutils.game.recorder.Category; +import xyz.stachel.zombiesutils.game.recorder.RecordMessageSender; +import xyz.stachel.zombiesutils.game.recorder.files.CategoryFile; class Game extends Timer { private final boolean joinedRoundOne; private int round; - private final File gameFile; - private String category; + private final GameFile gameFile; + private final boolean roundOneRecorded; + private Category category; public final GameMode mode; + private boolean escaping; public Game(@NotNull final GameFile gameFile, @NotNull final GameMode mode) { super(); @@ -21,6 +24,7 @@ class Game extends Timer { this.round = 1; this.joinedRoundOne = true; this.mode = mode; + this.roundOneRecorded = true; } public Game(@NotNull final GameFile gameFile, @NotNull final GameMode mode, final int round) { @@ -29,6 +33,11 @@ class Game extends Timer { this.round = round; this.joinedRoundOne = round == 1; this.mode = mode; + this.roundOneRecorded = round == 1; + } + + public void setCategory(Category category) { + this.category = category; } public void pass(int round) { @@ -37,7 +46,7 @@ class Game extends Timer { return; } try { -// record(); + this.record(); } catch (Exception e) { ZombiesUtils.LOGGER.error(ExceptionUtils.getStackTrace(e)); MinecraftClient.getInstance().player.sendMessage(Text.of("Error recording splits"), false); @@ -52,4 +61,47 @@ class Game extends Timer { } return super.split(); } + + public void helicopter() { + if (!this.mode.isMap(GameMode.Map.PRISON)) { + MinecraftClient.getInstance().player.sendMessage(Text.of("You are not imprisoned. Yet."), false); + ZombiesUtils.LOGGER.error(Thread.currentThread().getStackTrace().toString()); + return; + } + this.escaping = true; + this.pass(30); + } + + private void record() { + this.compareSegment(); + if (this.roundOneRecorded) this.compareBest(); + this.gameFile.setSegment(this.round, (int) this.roundTime()); + } + + public void compareSegment() throws IndexOutOfBoundsException { + if (this.escaping) return; + final CategoryFile categoryFile = this.category.getByGameMode(this.mode); + final short bestSegment = categoryFile.getBestSegment(round); + final int roundTime = (int) this.roundTime(); + + if (bestSegment == (short) 0) categoryFile.setBestSegment(round, roundTime); + else if (roundTime < bestSegment) categoryFile.setBestSegment(round, roundTime); + final RecordMessageSender recordMessageSender = new RecordMessageSender(this.category.getName(), round, roundTime, bestSegment); + recordMessageSender.roundSplit(); + recordMessageSender.sendRecordMessage(); + } + + public void compareBest() throws IndexOutOfBoundsException { + final CategoryFile categoryFile = this.category.getByGameMode(this.mode); + final int round = this.escaping ? 31 : this.round; + final int personalBest = categoryFile.getPersonalBest(round); + final int gameTime = (int) this.gameTime(); + + if (personalBest == 0) categoryFile.setPersonalBest(round, gameTime); + else if (gameTime < personalBest) categoryFile.setPersonalBest(round, gameTime); + final RecordMessageSender recordMessageSender = new RecordMessageSender(category.getName(), round, gameTime, personalBest); + if (!escaping) recordMessageSender.gameSplit(); + else recordMessageSender.helicopterSplit(); + recordMessageSender.sendRecordMessage(); + } } diff --git a/src/main/java/xyz/stachel/zombiesutils/game/GameFile.java b/src/main/java/xyz/stachel/zombiesutils/game/GameFile.java index c1088a1..d055473 100644 --- a/src/main/java/xyz/stachel/zombiesutils/game/GameFile.java +++ b/src/main/java/xyz/stachel/zombiesutils/game/GameFile.java @@ -1,6 +1,12 @@ package xyz.stachel.zombiesutils.game; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.Text; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.jetbrains.annotations.NotNull; +import xyz.stachel.zombiesutils.ZombiesUtils; +import xyz.stachel.zombiesutils.game.recorder.FileManager; +import xyz.stachel.zombiesutils.game.recorder.data.GameData; import java.io.File; import java.io.FileWriter; @@ -10,10 +16,14 @@ import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; class GameFile extends File { - private FileWriter writer; + private final GameData data; + + private FileWriter writer; GameFile(@NotNull final String serverNumber) { super(new File("zombies", "runs"), formattedTime() + "_" + serverNumber + ".seg2"); + this.data = new GameData(ZombiesUtils.getGameManager().getGame(serverNumber).mode.getMap()); + FileManager.createDataFile(this, this.data); } private static String formattedTime() { @@ -39,4 +49,15 @@ class GameFile extends File { void clean() throws IOException { this.writer.close(); } + + public void setSegment(int round, int ticks) { + this.data.setSegment(round - 1, ticks); + + try { + FileManager.writeDataToFile(this, this.data); + } catch (Exception e) { + ZombiesUtils.LOGGER.error(ExceptionUtils.getStackTrace(e)); + MinecraftClient.getInstance().player.sendMessage(Text.of("Error saving segment to run-file. Please Contact Stachelbeere1248."), false); + } + } } diff --git a/src/main/java/xyz/stachel/zombiesutils/game/GameManager.java b/src/main/java/xyz/stachel/zombiesutils/game/GameManager.java index 9356906..1c84e99 100644 --- a/src/main/java/xyz/stachel/zombiesutils/game/GameManager.java +++ b/src/main/java/xyz/stachel/zombiesutils/game/GameManager.java @@ -34,14 +34,18 @@ public class GameManager { } } - public Game getGame() { + public Optional getGame() { final String sn = Location.getServerNumber(); + return Optional.of(this.games.get(sn)); + } + + public Game getGame(String sn) { return this.games.get(sn); } public void endGame(final String serverNumber, final boolean isWin) { if (!games.containsKey(serverNumber)) return; - final Game game = games.get(serverNumber); + final Game game = this.getGame(serverNumber); if (isWin) { switch (game.mode.getMap()) { case DEAD_END: @@ -62,14 +66,14 @@ public class GameManager { final String serverNumber = Location.getServerNumber(); if (games.containsKey(serverNumber)) { if (round == 0) addGame(serverNumber, mode, round); - else games.get(serverNumber).pass(round); + else this.getGame(serverNumber).pass(round); } else addGame(serverNumber, mode, round); } public void setDifficulty(@NotNull GameMode.Difficulty difficulty) { this.queuedDifficultyServer = Location.getServerNumber(); if (this.games.containsKey(this.queuedDifficultyServer)) { - this.games.get(this.queuedDifficultyServer).mode.changeDifficulty(difficulty); + this.getGame(this.queuedDifficultyServer).mode.changeDifficulty(difficulty); } else this.queuedDifficulty = Optional.of(difficulty); } diff --git a/src/main/java/xyz/stachel/zombiesutils/game/GameMode.java b/src/main/java/xyz/stachel/zombiesutils/game/GameMode.java index 27589cc..9f665ce 100644 --- a/src/main/java/xyz/stachel/zombiesutils/game/GameMode.java +++ b/src/main/java/xyz/stachel/zombiesutils/game/GameMode.java @@ -23,6 +23,14 @@ public class GameMode { return this.map; } + public Difficulty getDifficulty() { + return this.difficulty; + } + + public boolean isMap(Map map) { + return map == this.map; + } + public enum Map { DEAD_END, BAD_BLOOD, PRISON, ALIEN_ARCADIUM; } diff --git a/src/main/java/xyz/stachel/zombiesutils/game/Prefix.java b/src/main/java/xyz/stachel/zombiesutils/game/Prefix.java new file mode 100644 index 0000000..8b25f58 --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/game/Prefix.java @@ -0,0 +1,36 @@ +package xyz.stachel.zombiesutils.game; + +public enum Prefix { + BOSS(0xCC5555, "B", 0x7A3333), + BLAZES(0xEFB61F, "BL", 0x8F6D0F), + SLIME(0x88FF88, "S", 0x51A951), + HBM(0x2A415F, "HBM", 0x193241), + WITHER_SKELETON(0x888888, "WS", 0x515151), + OLD_ONE(0x55AA55, "O1", 0x336633), + GIANT(0x00FFFF, "G", 0x009999), + POLICE(0x16537E, "P", 0x0E324D), + CELL(0xFF8234, "C", 0x99501F), + WINDOW(0xAAAAAA, "W", 0x666666); + + private final int color; + private final int fadedColor; + private final String prefix; + + Prefix(final int color, final String prefix, final int fadedColor) { + this.color = color; + this.prefix = prefix; + this.fadedColor = fadedColor; + } + + public int getColor() { + return color; + } + + public String getPrefix() { + return prefix; + } + + public int getFadedColor() { + return fadedColor; + } +} diff --git a/src/main/java/xyz/stachel/zombiesutils/game/recorder/Category.java b/src/main/java/xyz/stachel/zombiesutils/game/recorder/Category.java new file mode 100644 index 0000000..cda11a3 --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/game/recorder/Category.java @@ -0,0 +1,77 @@ +package xyz.stachel.zombiesutils.game.recorder; + +import org.jetbrains.annotations.NotNull; +import xyz.stachel.zombiesutils.ZombiesUtils; +import xyz.stachel.zombiesutils.game.GameMode; +import xyz.stachel.zombiesutils.game.recorder.files.CategoryFile; +import xyz.stachel.zombiesutils.util.Utils; + +import java.io.File; + +import static xyz.stachel.zombiesutils.game.GameMode.Map.*; + +public class Category { + private static String selectedCategory /*= ZombiesUtils.getInstance().getConfig().getDefaultCategory()*/; + public final CategoryFile[] categoryFiles = new CategoryFile[10]; + private final String name; + + public Category() { + final File category; + if (Utils.isHypixel()) category = new File(new File("zombies", "splits"), selectedCategory); + else category = new File(new File("zombies", "practise-splits"), selectedCategory); + categoryFiles[0] = new CategoryFile(category, DEAD_END, GameMode.Difficulty.NORMAL); + categoryFiles[1] = new CategoryFile(category, DEAD_END, GameMode.Difficulty.HARD); + categoryFiles[2] = new CategoryFile(category, DEAD_END, GameMode.Difficulty.RIP); + + categoryFiles[3] = new CategoryFile(category, BAD_BLOOD, GameMode.Difficulty.NORMAL); + categoryFiles[4] = new CategoryFile(category, BAD_BLOOD, GameMode.Difficulty.HARD); + categoryFiles[5] = new CategoryFile(category, BAD_BLOOD, GameMode.Difficulty.RIP); + + categoryFiles[6] = new CategoryFile(category, ALIEN_ARCADIUM, GameMode.Difficulty.NORMAL); + + categoryFiles[7] = new CategoryFile(category, PRISON, GameMode.Difficulty.NORMAL); + categoryFiles[8] = new CategoryFile(category, PRISON, GameMode.Difficulty.HARD); + categoryFiles[9] = new CategoryFile(category, PRISON, GameMode.Difficulty.RIP); + + this.name = Category.selectedCategory; + } + +// public static void setSelectedCategory(String selectedCategory) { +// Category.selectedCategory = selectedCategory; +// ZombiesUtils.getGameManager().getGame().ifPresent(game -> game.setCategory(new Category())); +// } + + public static String[] getCategories() { + File dir; + if (Utils.isHypixel()) dir = new File("zombies" + File.separator + "splits"); + else dir = new File("zombies" + File.separator + "practise-splits"); + if (dir.isDirectory()) return dir.list(); + else return new String[0]; + } + + public CategoryFile getByGameMode(@NotNull GameMode gameMode) { + return switch (gameMode.getMap()) { + case DEAD_END -> switch (gameMode.getDifficulty()) { + case NORMAL -> categoryFiles[0]; + case HARD -> categoryFiles[1]; + case RIP -> categoryFiles[2]; + }; + case BAD_BLOOD -> switch (gameMode.getDifficulty()) { + case NORMAL -> categoryFiles[3]; + case HARD -> categoryFiles[4]; + case RIP -> categoryFiles[5]; + }; + case ALIEN_ARCADIUM -> categoryFiles[6]; + case PRISON -> switch (gameMode.getDifficulty()) { + case NORMAL -> categoryFiles[7]; + case HARD -> categoryFiles[8]; + case RIP -> categoryFiles[9]; + }; + default -> throw new IllegalStateException("Unexpected value: " + gameMode); + }; + } + + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/src/main/java/xyz/stachel/zombiesutils/game/recorder/FileManager.java b/src/main/java/xyz/stachel/zombiesutils/game/recorder/FileManager.java new file mode 100644 index 0000000..fd5e184 --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/game/recorder/FileManager.java @@ -0,0 +1,58 @@ +package xyz.stachel.zombiesutils.game.recorder; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import org.apache.commons.io.FileUtils; +import org.jetbrains.annotations.NotNull; +import xyz.stachel.zombiesutils.game.recorder.data.CategoryData; +import xyz.stachel.zombiesutils.game.recorder.files.CategoryFile; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class FileManager { + private static CategoryData readDataFromFile(@NotNull File file) throws FileNotFoundException, JsonSyntaxException { + if (!file.exists()) throw new FileNotFoundException(); + + String dataJson; + Gson gson = new Gson(); + try { + dataJson = FileUtils.readFileToString(file, StandardCharsets.UTF_16); + } catch (IOException e) { + throw new RuntimeException(e); + } + if (dataJson == null || dataJson.trim().isEmpty()) throw new JsonSyntaxException("File empty"); + + return gson.fromJson(dataJson, CategoryData.class); + } + + public static void createDataFile(@NotNull File file, ISplitsData data) { + try { + //noinspection ResultOfMethodCallIgnored + file.getParentFile().mkdirs(); + //noinspection ResultOfMethodCallIgnored + file.createNewFile(); + writeDataToFile(file, data); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static void writeDataToFile(File file, @NotNull ISplitsData data) throws IOException { + FileUtils.writeStringToFile(file, data.toJSON(), StandardCharsets.UTF_16); + } + + @NotNull + public static CategoryData categoryReadOrCreate(CategoryFile file) { + CategoryData data; + try { + data = FileManager.readDataFromFile(file); + } catch (FileNotFoundException | JsonSyntaxException ignored) { + data = new CategoryData(file.getMap()); + FileManager.createDataFile(file, data); + } + return data; + } +} \ No newline at end of file diff --git a/src/main/java/xyz/stachel/zombiesutils/game/recorder/ISplitsData.java b/src/main/java/xyz/stachel/zombiesutils/game/recorder/ISplitsData.java new file mode 100644 index 0000000..28027fd --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/game/recorder/ISplitsData.java @@ -0,0 +1,5 @@ +package xyz.stachel.zombiesutils.game.recorder; + +public interface ISplitsData { + String toJSON(); +} \ No newline at end of file diff --git a/src/main/java/xyz/stachel/zombiesutils/game/recorder/RecordMessageSender.java b/src/main/java/xyz/stachel/zombiesutils/game/recorder/RecordMessageSender.java new file mode 100644 index 0000000..38dbfda --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/game/recorder/RecordMessageSender.java @@ -0,0 +1,54 @@ +package xyz.stachel.zombiesutils.game.recorder; + +import org.jetbrains.annotations.Contract; + +public class RecordMessageSender { + + private final StringBuilder recordMessage; + private final int newTime; + private final int oldTime; + private final int round; + private final String deltaString; + private final String timeString; + private String copyString; + + public RecordMessageSender(final String categoryName, final int round, final int newTime, final int oldTime) { + this.recordMessage = new StringBuilder( + "§l§a▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n§e Category: §d" + categoryName + ); + this.newTime = newTime; + this.oldTime = oldTime; + this.deltaString = oldTime != 0 ? " " + formattedDelta(newTime, oldTime) : ""; + this.timeString = formattedTime(newTime); + this.round = round; + } + + public void sendRecordMessage() { + } + + public void gameSplit() { + } + + public void roundSplit() { + } + + public void helicopterSplit() { + } + + @Contract(pure = true) + private String formattedTime(int time) { + time *= 50; + return String.format("%d:%02d.%d%d", + time / 60000, + (time % 60000) / 1000, + (time % 1000) / 100, + (time % 100) / 10 + ); + } + + @Contract(pure = true) + private String formattedDelta(int newTime, int oldTime) { + final double delta = (double) (newTime - oldTime) / 20; + return String.format("%+.2f", delta); + } +} diff --git a/src/main/java/xyz/stachel/zombiesutils/game/recorder/data/CategoryData.java b/src/main/java/xyz/stachel/zombiesutils/game/recorder/data/CategoryData.java new file mode 100644 index 0000000..10379fb --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/game/recorder/data/CategoryData.java @@ -0,0 +1,58 @@ +package xyz.stachel.zombiesutils.game.recorder.data; + +import com.google.gson.Gson; +import org.jetbrains.annotations.NotNull; +import xyz.stachel.zombiesutils.game.GameMode; +import xyz.stachel.zombiesutils.game.recorder.ISplitsData; + +import java.util.Arrays; + +public class CategoryData implements ISplitsData { + private final short[] bestSegments; //in ticks, max ~27 min + private final int[] personalBests; //in ticks, + + public CategoryData(@NotNull GameMode.Map map) throws IllegalStateException { + switch (map) { + case ALIEN_ARCADIUM: + bestSegments = new short[105]; + personalBests = new int[105]; + break; + case DEAD_END: + case BAD_BLOOD: + bestSegments = new short[30]; + personalBests = new int[30]; + break; + case PRISON: + bestSegments = new short[30]; + personalBests = new int[31]; + break; + default: + throw new IllegalStateException("Not a map: " + map); + } + Arrays.fill(bestSegments, (short) 0); + Arrays.fill(personalBests, 0); + } + + @Override + @NotNull + public String toJSON() { + Gson gson = new Gson(); + return gson.toJson(this, CategoryData.class); + } + + public short getBestSegment(int index) { + return bestSegments[index]; + } + + public int getPersonalBest(int index) { + return personalBests[index]; + } + + public void setBestSegment(int index, int ticks) { + bestSegments[index] = (short) ticks; + } + + public void setPersonalBest(int index, int ticks) { + personalBests[index] = ticks; + } +} diff --git a/src/main/java/xyz/stachel/zombiesutils/game/recorder/data/GameData.java b/src/main/java/xyz/stachel/zombiesutils/game/recorder/data/GameData.java new file mode 100644 index 0000000..ebf996f --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/game/recorder/data/GameData.java @@ -0,0 +1,41 @@ +package xyz.stachel.zombiesutils.game.recorder.data; + +import com.google.gson.Gson; +import org.jetbrains.annotations.NotNull; +import xyz.stachel.zombiesutils.game.GameMode; +import xyz.stachel.zombiesutils.game.recorder.ISplitsData; + +import java.util.Arrays; + +public class GameData implements ISplitsData { + private final short[] segments; + + public GameData(@NotNull GameMode.Map map) throws IllegalStateException { + switch (map) { + case ALIEN_ARCADIUM: + segments = new short[105]; + break; + case DEAD_END: + case BAD_BLOOD: + segments = new short[30]; + break; + case PRISON: + segments = new short[31]; + break; + default: + throw new IllegalStateException("Not a map: " + map); + } + Arrays.fill(segments, (short) 0); + } + + @Override + @NotNull + public String toJSON() { + Gson gson = new Gson(); + return gson.toJson(this.segments); + } + + public void setSegment(int index, int ticks) { + segments[index] = (short) ticks; + } +} diff --git a/src/main/java/xyz/stachel/zombiesutils/game/recorder/files/CategoryFile.java b/src/main/java/xyz/stachel/zombiesutils/game/recorder/files/CategoryFile.java new file mode 100644 index 0000000..a573c6b --- /dev/null +++ b/src/main/java/xyz/stachel/zombiesutils/game/recorder/files/CategoryFile.java @@ -0,0 +1,66 @@ +package xyz.stachel.zombiesutils.game.recorder.files; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.Text; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.jetbrains.annotations.NotNull; +import xyz.stachel.zombiesutils.ZombiesUtils; +import xyz.stachel.zombiesutils.game.GameMode; +import xyz.stachel.zombiesutils.game.recorder.FileManager; +import xyz.stachel.zombiesutils.game.recorder.data.CategoryData; + +import java.io.File; + +public class CategoryFile extends File { + private final CategoryData data; + private final GameMode.Map map; + private final GameMode.Difficulty difficulty; + + public CategoryFile(File category, @NotNull GameMode.Map map, GameMode.Difficulty difficulty) { + // Game-directory -> custom category -> file named "MAP_DIFFICULTY.times" + // Content encoded in StandardCharsets.UTF_16 + super(category, map + "_" + difficulty + ".times"); + this.map = map; + this.difficulty = difficulty; + this.data = FileManager.categoryReadOrCreate(this); + } + + public short getBestSegment(int round) { + return this.data.getBestSegment(round - 1); + } + + public void setBestSegment(int round, int ticks) { + this.data.setBestSegment(round - 1, ticks); + + try { + FileManager.writeDataToFile(this, this.data); + } catch (Exception e) { + ZombiesUtils.LOGGER.error(ExceptionUtils.getStackTrace(e)); + MinecraftClient.getInstance().player.sendMessage(Text.of("Error saving segment to splits-file. Please Contact Stachelbeere1248."), false); + } + } + + public int getPersonalBest(int round) { + return data.getPersonalBest(round - 1); + } + + public void setPersonalBest(int round, int ticks) { + this.data.setPersonalBest(round - 1, ticks); + + try { + FileManager.writeDataToFile(this, this.data); + } catch (Exception e) { + ZombiesUtils.LOGGER.error(ExceptionUtils.getStackTrace(e)); + MinecraftClient.getInstance().player.sendMessage(Text.of("Error saving pb to splits-file. Please Contact Stachelbeere1248."), false); + } + } + + public GameMode.Map getMap() { + return this.map; + } + + public GameMode.Difficulty getDifficulty() { + return this.difficulty; + } + +} \ No newline at end of file diff --git a/src/main/java/xyz/stachel/zombiesutils/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/xyz/stachel/zombiesutils/mixin/ClientPlayNetworkHandlerMixin.java index 78ddda8..a60ac8d 100644 --- a/src/main/java/xyz/stachel/zombiesutils/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/xyz/stachel/zombiesutils/mixin/ClientPlayNetworkHandlerMixin.java @@ -6,6 +6,7 @@ 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 xyz.stachel.zombiesutils.ZombiesUtils; import xyz.stachel.zombiesutils.game.GameManager; import java.util.regex.Matcher; @@ -22,7 +23,7 @@ public abstract class ClientPlayNetworkHandlerMixin { if (matcher.find()) { int number = Integer.parseInt(matcher.group(1)); if (number >= 1 && number <= 105) { - new GameManager().onRound(number); + ZombiesUtils.getGameManager().onRound(number); } } } diff --git a/src/main/java/xyz/stachel/zombiesutils/mixin/OtherClientPlayerEntityMixin.java b/src/main/java/xyz/stachel/zombiesutils/mixin/OtherClientPlayerEntityMixin.java index 556d837..5cd713a 100644 --- a/src/main/java/xyz/stachel/zombiesutils/mixin/OtherClientPlayerEntityMixin.java +++ b/src/main/java/xyz/stachel/zombiesutils/mixin/OtherClientPlayerEntityMixin.java @@ -7,6 +7,7 @@ import net.minecraft.client.network.OtherClientPlayerEntity; import net.minecraft.client.world.ClientWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import xyz.stachel.zombiesutils.ZombiesUtilsClient; import xyz.stachel.zombiesutils.config.Configs; @Mixin(OtherClientPlayerEntity.class) @@ -18,13 +19,13 @@ public abstract class OtherClientPlayerEntityMixin extends AbstractClientPlayerE @ModifyReturnValue(method = "shouldRender", at = @At(value = "RETURN")) public boolean shouldRender(boolean original, double distance) { - int dist = Configs.playerVisibleDistance.getValue(); - double d = this.getBoundingBox().getAverageSideLength() * 1.75 + (double) dist; - if (Double.isNaN(d)) { - d = 1.0; - } + if (ZombiesUtilsClient.PLAYER_VISIBILITY_SWITCH) { + double dist = Configs.playerVisibleDistance.getValue(); + double d = this.getBoundingBox().getAverageSideLength() + dist; - d *= 1.0; - return (distance >= d * d) && original; + return (distance >= d * d) && original; + } else { + return original; + } } } diff --git a/src/main/java/xyz/stachel/zombiesutils/util/Utils.java b/src/main/java/xyz/stachel/zombiesutils/util/Utils.java index 011379f..1e0df06 100644 --- a/src/main/java/xyz/stachel/zombiesutils/util/Utils.java +++ b/src/main/java/xyz/stachel/zombiesutils/util/Utils.java @@ -1,21 +1,22 @@ package xyz.stachel.zombiesutils.util; +import net.minecraft.client.MinecraftClient; +import org.jetbrains.annotations.Nullable; import xyz.stachel.zombiesutils.game.GameMode; import xyz.stachel.zombiesutils.handlers.Location; -import java.util.Optional; - import static xyz.stachel.zombiesutils.game.GameMode.Map.*; public class Utils { - public static Optional getMap() { + @Nullable + public static GameMode.Map getMap() { return switch (Location.getMode()) { - case "ZOMBIES_DEAD_END" -> Optional.of(DEAD_END); - case "ZOMBIES_BAD_BLOOD" -> Optional.of(BAD_BLOOD); - case "ZOMBIES_ALIEN_ARCADIUM" -> Optional.of(ALIEN_ARCADIUM); - case "ZOMBIES_PRISON" -> Optional.of(PRISON); - default -> Optional.empty(); + case "ZOMBIES_DEAD_END" -> DEAD_END; + case "ZOMBIES_BAD_BLOOD" -> BAD_BLOOD; + case "ZOMBIES_ALIEN_ARCADIUM" -> ALIEN_ARCADIUM; + case "ZOMBIES_PRISON" -> PRISON; + default -> null; }; } @@ -23,4 +24,8 @@ public class Utils { return Location.getMode().startsWith("ZOMBIES"); } + public static boolean isHypixel() { + return true; + } + } diff --git a/src/main/resources/assets/zombies-utils/lang/en_us.json b/src/main/resources/assets/zombies-utils/lang/en_us.json new file mode 100644 index 0000000..a407743 --- /dev/null +++ b/src/main/resources/assets/zombies-utils/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "category.zombies-utils": "Zombies Utils", + "key.zombies-utils.toggle_player_visibility": "Toggle Nearest Players", + "key.zombies-utils.toggle_player_visibility.toggle_on": "Nearest Players Are Now Invisible", + "key.zombies-utils.toggle_player_visibility.toggle_off": "Nearest Players Are Now Visible" +} \ No newline at end of file diff --git a/src/main/resources/assets/zombies-utils/lang/ru_ru.json b/src/main/resources/assets/zombies-utils/lang/ru_ru.json new file mode 100644 index 0000000..9566dab --- /dev/null +++ b/src/main/resources/assets/zombies-utils/lang/ru_ru.json @@ -0,0 +1,6 @@ +{ + "category.zombies-utils": "Zombies Utils", + "key.zombies-utils.toggle_player_visibility": "Видимость ближайших игроков", + "key.zombies-utils.toggle_player_visibility.toggle_on": "Ближайшие игроки к вам теперь невидимы.", + "key.zombies-utils.toggle_player_visibility.toggle_off": "Ближайшие игроки к вам теперь видимы." +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ca2e0a2..332d8b0 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -17,7 +17,10 @@ "entrypoints": { "main": [ "xyz.stachel.zombiesutils.ZombiesUtils" - ] + ], + "client": [ + "xyz.stachel.zombiesutils.ZombiesUtilsClient" + ] }, "mixins": [ {