Compare commits
8 commits
b2b8542604
...
84a7a1cf66
Author | SHA1 | Date | |
---|---|---|---|
84a7a1cf66 | |||
cc7c711bb7 | |||
![]() |
fdb9acb04a | ||
![]() |
3f065e114f | ||
![]() |
a118708202 | ||
![]() |
c7af5d198f | ||
![]() |
047dfcab72 | ||
![]() |
207a43135b |
30 changed files with 909 additions and 84 deletions
11
build.gradle
11
build.gradle
|
@ -12,15 +12,17 @@ base {
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven { url 'https://repo.hypixel.net/repository/Hypixel/' }
|
maven { url 'https://repo.hypixel.net/repository/Hypixel/' }
|
||||||
|
maven {
|
||||||
|
name 'Xander Maven'
|
||||||
|
url 'https://maven.isxander.dev/releases'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
splitEnvironmentSourceSets()
|
|
||||||
|
|
||||||
mods {
|
mods {
|
||||||
"zombies-utils" {
|
"zombies-utils" {
|
||||||
sourceSet sourceSets.main
|
sourceSet sourceSets.main
|
||||||
sourceSet sourceSets.client
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +36,10 @@ dependencies {
|
||||||
|
|
||||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||||
modImplementation 'net.hypixel:mod-api:1.0.1'
|
|
||||||
|
// other deps
|
||||||
|
modImplementation 'net.hypixel:mod-api:1.0.1'
|
||||||
|
modImplementation "dev.isxander:yet-another-config-lib:${project.yacl_version}"
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
|
|
@ -16,3 +16,4 @@ archives_base_name=zombies-utils
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
fabric_version=0.123.2+1.21.5
|
fabric_version=0.123.2+1.21.5
|
||||||
|
yacl_version=3.6.6+1.21.5-fabric
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package xyz.stachel.zombiesutils;
|
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
|
||||||
import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback;
|
|
||||||
import net.hypixel.modapi.HypixelModAPI;
|
|
||||||
import net.hypixel.modapi.packet.impl.clientbound.event.ClientboundLocationPacket;
|
|
||||||
import xyz.stachel.zombiesutils.handlers.Location;
|
|
||||||
import xyz.stachel.zombiesutils.handlers.Renderer;
|
|
||||||
|
|
||||||
public class ZombiesUtilsClient implements ClientModInitializer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInitializeClient() {
|
|
||||||
HypixelModAPI.getInstance().subscribeToEventPacket(ClientboundLocationPacket.class);
|
|
||||||
HypixelModAPI.getInstance().createHandler(ClientboundLocationPacket.class, Location::onLocation);
|
|
||||||
ZombiesUtils.LOGGER.info("initializing...");
|
|
||||||
HudLayerRegistrationCallback.EVENT.register(new Renderer());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"required": true,
|
|
||||||
"package": "xyz.stachel.zombiesutils.mixin.client",
|
|
||||||
"compatibilityLevel": "JAVA_21",
|
|
||||||
"client": [
|
|
||||||
"ClientPlayNetworkHandlerMixin"
|
|
||||||
],
|
|
||||||
"injectors": {
|
|
||||||
"defaultRequire": 1
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +1,33 @@
|
||||||
package xyz.stachel.zombiesutils;
|
package xyz.stachel.zombiesutils;
|
||||||
|
|
||||||
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback;
|
||||||
|
import net.hypixel.modapi.HypixelModAPI;
|
||||||
|
import net.hypixel.modapi.packet.impl.clientbound.event.ClientboundLocationPacket;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import xyz.stachel.zombiesutils.config.Config;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import xyz.stachel.zombiesutils.game.GameManager;
|
||||||
|
import xyz.stachel.zombiesutils.handlers.Location;
|
||||||
|
import xyz.stachel.zombiesutils.handlers.Renderer;
|
||||||
|
|
||||||
public class ZombiesUtils implements ModInitializer {
|
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 String MOD_ID = "zombies-utils";
|
||||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
|
HypixelModAPI.getInstance().subscribeToEventPacket(ClientboundLocationPacket.class);
|
||||||
|
HypixelModAPI.getInstance().createHandler(ClientboundLocationPacket.class, Location::onLocation);
|
||||||
|
ZombiesUtils.LOGGER.info("initializing...");
|
||||||
|
HudLayerRegistrationCallback.EVENT.register(new Renderer());
|
||||||
|
Config.readFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
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.util.Formatting;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package xyz.stachel.zombiesutils.config;
|
||||||
|
|
||||||
|
import dev.isxander.yacl3.api.ConfigCategory;
|
||||||
|
import dev.isxander.yacl3.api.Option;
|
||||||
|
import dev.isxander.yacl3.api.OptionDescription;
|
||||||
|
import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder;
|
||||||
|
import dev.isxander.yacl3.config.v2.api.SerialEntry;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public class PlayerVisibilityConfig {
|
||||||
|
|
||||||
|
|
||||||
|
@SerialEntry
|
||||||
|
private float range;
|
||||||
|
|
||||||
|
ConfigCategory category(PlayerVisibilityConfig defaults) {
|
||||||
|
return ConfigCategory.createBuilder()
|
||||||
|
.name(Text.translatable("zombies-utils.config.player-visibility.name"))
|
||||||
|
.tooltip(Text.translatable("zombies-utils.config.player-visibility.tooltip"))
|
||||||
|
|
||||||
|
.option(Option.<Float>createBuilder()
|
||||||
|
.name(Text.translatable("zombies-utils.config.player-visibility.range.name"))
|
||||||
|
.description(OptionDescription.of(Text.translatable("zombies-utils.config.player-visibility.range.tooltip")))
|
||||||
|
.binding(defaults.range, () -> this.range, n -> {this.range = n;})
|
||||||
|
.controller( o -> FloatSliderControllerBuilder.create(o).range(0f, 10f).step(0.01f))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
).build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package xyz.stachel.zombiesutils.config;
|
||||||
|
|
||||||
|
import dev.isxander.yacl3.api.YetAnotherConfigLib;
|
||||||
|
import dev.isxander.yacl3.config.v2.api.ConfigClassHandler;
|
||||||
|
import dev.isxander.yacl3.config.v2.api.SerialEntry;
|
||||||
|
import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import xyz.stachel.zombiesutils.ZombiesUtils;
|
||||||
|
|
||||||
|
public class ZombiesUtilsConfig {
|
||||||
|
private static final ConfigClassHandler<ZombiesUtilsConfig> configHandler = ConfigClassHandler
|
||||||
|
.createBuilder(ZombiesUtilsConfig.class)
|
||||||
|
.serializer(cfg -> GsonConfigSerializerBuilder.create(cfg).setPath(FabricLoader.getInstance().getConfigDir().resolve(ZombiesUtils.MOD_ID).resolve("config.json")).build()).build();
|
||||||
|
|
||||||
|
public ZombiesUtilsConfig() {
|
||||||
|
this.playerVis = new PlayerVisibilityConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SerialEntry
|
||||||
|
PlayerVisibilityConfig playerVis;
|
||||||
|
|
||||||
|
public void display() {
|
||||||
|
Screen screen = YetAnotherConfigLib.create(configHandler, (defaults, current, b) -> b
|
||||||
|
.category(current.playerVis.category(defaults.playerVis)))
|
||||||
|
.generateScreen(null);
|
||||||
|
MinecraftClient.getInstance().setScreen(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
ZombiesUtilsConfig.configHandler.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ZombiesUtilsConfig getConfig() {
|
||||||
|
return ZombiesUtilsConfig.configHandler.instance();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,24 @@
|
||||||
package xyz.stachel.zombiesutils.game;
|
package xyz.stachel.zombiesutils.game;
|
||||||
|
|
||||||
import java.io.File;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.text.Style;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import xyz.stachel.zombiesutils.ZombiesUtils;
|
||||||
|
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 {
|
class Game extends Timer {
|
||||||
private final boolean joinedRoundOne;
|
private final boolean joinedRoundOne;
|
||||||
private int round;
|
private int round;
|
||||||
private final File gameFile;
|
private final GameFile gameFile;
|
||||||
private String category;
|
private final boolean roundOneRecorded;
|
||||||
|
private Category category;
|
||||||
public final GameMode mode;
|
public final GameMode mode;
|
||||||
|
private boolean escaping;
|
||||||
|
|
||||||
public Game(@NotNull final GameFile gameFile, @NotNull final GameMode mode) {
|
public Game(@NotNull final GameFile gameFile, @NotNull final GameMode mode) {
|
||||||
super();
|
super();
|
||||||
|
@ -17,6 +26,7 @@ class Game extends Timer {
|
||||||
this.round = 1;
|
this.round = 1;
|
||||||
this.joinedRoundOne = true;
|
this.joinedRoundOne = true;
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
this.roundOneRecorded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Game(@NotNull final GameFile gameFile, @NotNull final GameMode mode, final int round) {
|
public Game(@NotNull final GameFile gameFile, @NotNull final GameMode mode, final int round) {
|
||||||
|
@ -25,10 +35,75 @@ class Game extends Timer {
|
||||||
this.round = round;
|
this.round = round;
|
||||||
this.joinedRoundOne = round == 1;
|
this.joinedRoundOne = round == 1;
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
this.roundOneRecorded = round == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategory(Category category) {
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pass(int round) {
|
||||||
|
if ((round == 0) || (this.round == round + 1) || (this.roundTime() < 100)) {
|
||||||
|
ZombiesUtils.LOGGER.debug("SPLIT CANCELLED");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.record();
|
||||||
|
} catch (Exception e) {
|
||||||
|
ZombiesUtils.LOGGER.error(ExceptionUtils.getStackTrace(e));
|
||||||
|
MinecraftClient.getInstance().player.sendMessage(Text.literal("Error recording splits").setStyle(Style.EMPTY.withColor(Formatting.RED)), false);
|
||||||
|
}
|
||||||
|
this.split();
|
||||||
|
this.round = round + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long split(final int round) {
|
public long split(final int round) {
|
||||||
if (round )
|
if (round == 1) {
|
||||||
|
|
||||||
|
}
|
||||||
return super.split();
|
return super.split();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void helicopter() {
|
||||||
|
if (!this.mode.isMap(GameMode.Map.PRISON)) {
|
||||||
|
MinecraftClient.getInstance().player.sendMessage(Text.literal("You are not imprisoned. Yet.").setStyle(Style.EMPTY.withColor(Formatting.RED)), 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
package xyz.stachel.zombiesutils.game;
|
package xyz.stachel.zombiesutils.game;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.text.Style;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
|
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.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -7,13 +17,15 @@ import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
class GameFile extends File {
|
class GameFile extends File {
|
||||||
private FileWriter writer;
|
private final GameData data;
|
||||||
|
|
||||||
|
private FileWriter writer;
|
||||||
|
|
||||||
GameFile(@NotNull final String serverNumber) {
|
GameFile(@NotNull final String serverNumber, @NotNull final GameMode mode) {
|
||||||
super(new File("zombies", "runs"), formattedTime() + "_" + serverNumber + ".seg2");
|
super(new File("zombies", "runs"), formattedTime() + "_" + serverNumber + ".seg2");
|
||||||
|
this.data = new GameData(mode.getMap());
|
||||||
|
FileManager.createDataFile(this, this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formattedTime() {
|
private static String formattedTime() {
|
||||||
|
@ -39,4 +51,15 @@ class GameFile extends File {
|
||||||
void clean() throws IOException {
|
void clean() throws IOException {
|
||||||
this.writer.close();
|
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.literal("Error saving segment to run-file. Please Contact Stachelbeere1248.").setStyle(Style.EMPTY.withColor(Formatting.RED)), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,83 @@
|
||||||
package xyz.stachel.zombiesutils.game;
|
package xyz.stachel.zombiesutils.game;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import xyz.stachel.zombiesutils.game.GameMode.Map;
|
|
||||||
import xyz.stachel.zombiesutils.handlers.Location;
|
import xyz.stachel.zombiesutils.handlers.Location;
|
||||||
|
import xyz.stachel.zombiesutils.game.GameMode.Map;
|
||||||
|
import xyz.stachel.zombiesutils.util.Utils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class GameManager {
|
public class GameManager {
|
||||||
private final HashMap<String, Game> games = new HashMap<>();
|
private final HashMap<String, Game> games = new HashMap<>();
|
||||||
|
private Optional<GameMode.Difficulty> queuedDifficulty = Optional.empty();
|
||||||
|
private String queuedDifficultyServer = "INVALID";
|
||||||
|
|
||||||
private void addGame(final String serverNumber, final GameMode mode, final int round) {
|
private void addGame(final String serverNumber, final GameMode mode, final int round) {
|
||||||
this.games.put(serverNumber, new Game(new GameFile(serverNumber), mode));
|
if (serverNumber.equals(queuedDifficultyServer)) {
|
||||||
|
this.queuedDifficulty.ifPresent(mode::changeDifficulty);
|
||||||
|
}
|
||||||
|
this.queuedDifficulty = Optional.empty();
|
||||||
|
this.games.put(serverNumber, new Game(new GameFile(serverNumber, mode), mode, round));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onRound(final int round) {
|
public void onRound(final int round) {
|
||||||
final String sn = Location.getServerNumber();
|
final String sn = Location.getServerNumber();
|
||||||
final String mode = Location.getMode();
|
final String mode = Location.getMode();
|
||||||
if (sn == null || mode == null || !mode.startsWith("ZOMBIES")) return;
|
if (sn == null || mode == null || !Utils.isZombies()) return;
|
||||||
|
|
||||||
if (!games.containsKey(sn)) addGame(sn, new GameMode(Map.DEAD_END), round);
|
if (this.getGame(sn) == null) {
|
||||||
else games.get(sn).split(round);
|
this.addGame(sn, new GameMode(Utils.getMap(mode)), round);
|
||||||
|
} else {
|
||||||
|
this.getGame(sn).split(round);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Game getGame() {
|
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 = this.getGame(serverNumber);
|
||||||
|
if (isWin) {
|
||||||
|
switch (game.mode.getMap()) {
|
||||||
|
case DEAD_END:
|
||||||
|
case BAD_BLOOD:
|
||||||
|
case PRISON:
|
||||||
|
game.pass(30);
|
||||||
|
break;
|
||||||
|
case ALIEN_ARCADIUM:
|
||||||
|
game.pass(105);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
games.remove(serverNumber);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void splitOrNew(GameMode mode, int round) {
|
||||||
|
final String serverNumber = Location.getServerNumber();
|
||||||
|
if (games.containsKey(serverNumber)) {
|
||||||
|
if (round == 0) addGame(serverNumber, mode, 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.getGame(this.queuedDifficultyServer).mode.changeDifficulty(difficulty);
|
||||||
|
} else this.queuedDifficulty = Optional.of(difficulty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getGames() {
|
||||||
|
return this.games.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void killAll() {
|
||||||
|
games.clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package xyz.stachel.zombiesutils.game;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
class GameMode {
|
public class GameMode {
|
||||||
private final Map map;
|
private final Map map;
|
||||||
private Difficulty difficulty;
|
private Difficulty difficulty;
|
||||||
|
|
||||||
|
@ -19,11 +19,23 @@ class GameMode {
|
||||||
this.difficulty = map != Map.ALIEN_ARCADIUM ? difficulty : Difficulty.NORMAL;
|
this.difficulty = map != Map.ALIEN_ARCADIUM ? difficulty : Difficulty.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Map {
|
public Map getMap() {
|
||||||
|
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;
|
DEAD_END, BAD_BLOOD, PRISON, ALIEN_ARCADIUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Difficulty {
|
public enum Difficulty {
|
||||||
NORMAL, HARD, RIP;
|
NORMAL, HARD, RIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
36
src/main/java/xyz/stachel/zombiesutils/game/Prefix.java
Normal file
36
src/main/java/xyz/stachel/zombiesutils/game/Prefix.java
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
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];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package xyz.stachel.zombiesutils.game.recorder;
|
||||||
|
|
||||||
|
public interface ISplitsData {
|
||||||
|
String toJSON();
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package xyz.stachel.zombiesutils.game.recorder.files;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.text.Style;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
|
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.literal("Error saving segment to splits-file. Please Contact Stachelbeere1248.").setStyle(Style.EMPTY.withColor(Formatting.RED)), 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.literal("Error saving pb to splits-file. Please Contact Stachelbeere1248.").setStyle(Style.EMPTY.withColor(Formatting.RED)), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameMode.Map getMap() {
|
||||||
|
return this.map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameMode.Difficulty getDifficulty() {
|
||||||
|
return this.difficulty;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,18 @@
|
||||||
package xyz.stachel.zombiesutils.handlers;
|
package xyz.stachel.zombiesutils.handlers;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import net.hypixel.modapi.packet.impl.clientbound.event.ClientboundLocationPacket;
|
import net.hypixel.modapi.packet.impl.clientbound.event.ClientboundLocationPacket;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class Location {
|
public class Location {
|
||||||
|
|
||||||
private static String serverNumber;
|
private static String serverNumber;
|
||||||
private static String mode;
|
private static String mode;
|
||||||
|
|
||||||
public static void onLocation(ClientboundLocationPacket p) {
|
public static void onLocation(ClientboundLocationPacket p) {
|
||||||
Location.serverNumber = p.getServerName();
|
serverNumber = p.getServerName();
|
||||||
Optional<String> m = p.getMode();
|
Optional<String> m = p.getMode();
|
||||||
if (m.isPresent()) Location.mode = m.get();
|
m.ifPresent(s -> mode = s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getServerNumber() {
|
public static String getServerNumber() {
|
|
@ -1,30 +1,32 @@
|
||||||
package xyz.stachel.zombiesutils.mixin.client;
|
package xyz.stachel.zombiesutils.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
|
import net.minecraft.network.packet.s2c.play.TitleS2CPacket;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
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;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
|
||||||
import net.minecraft.network.packet.s2c.play.TitleS2CPacket;
|
|
||||||
import xyz.stachel.zombiesutils.game.GameManager;
|
|
||||||
|
|
||||||
@Mixin(ClientPlayNetworkHandler.class)
|
@Mixin(ClientPlayNetworkHandler.class)
|
||||||
public class ClientPlayNetworkHandlerMixin {
|
public abstract class ClientPlayNetworkHandlerMixin {
|
||||||
|
@Unique
|
||||||
private static final Pattern pattern = Pattern.compile("Round (\\d{1,3})");
|
private static final Pattern pattern = Pattern.compile("Round (\\d{1,3})");
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "onTitle")
|
@Inject(at = @At("HEAD"), method = "onTitle")
|
||||||
private void zombiesUtils_onTitle(TitleS2CPacket p, CallbackInfo info) {
|
private void zombiesUtils_onTitle(TitleS2CPacket p, CallbackInfo info) {
|
||||||
final String msg = p.text().getString();
|
final String msg = p.text().getString();
|
||||||
final Matcher matcher = pattern.matcher(msg);
|
final Matcher matcher = pattern.matcher(msg);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
int number = Integer.parseInt(matcher.group(1));
|
int number = Integer.parseInt(matcher.group(1));
|
||||||
if (number >= 1 && number <= 105) {
|
if (number >= 1 && number <= 105) {
|
||||||
GameManager.onRound(number);
|
ZombiesUtils.getGameManager().onRound(number);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package xyz.stachel.zombiesutils.mixin;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||||
|
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)
|
||||||
|
public abstract class OtherClientPlayerEntityMixin extends AbstractClientPlayerEntity {
|
||||||
|
|
||||||
|
public OtherClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
|
||||||
|
super(world, profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModifyReturnValue(method = "shouldRender", at = @At(value = "RETURN"))
|
||||||
|
public boolean shouldRender(boolean original, double distance) {
|
||||||
|
if (ZombiesUtilsClient.PLAYER_VISIBILITY_SWITCH) {
|
||||||
|
double dist = Configs.playerVisibleDistance.getValue();
|
||||||
|
double d = this.getBoundingBox().getAverageSideLength() + dist;
|
||||||
|
|
||||||
|
return (distance >= d * d) && original;
|
||||||
|
} else {
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
package xyz.stachel.zombiesutils.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@SuppressWarnings("SpellCheckingInspection")
|
||||||
|
public class LanguageSupport {
|
||||||
|
private static final String[] LANGUAGES = {
|
||||||
|
"EN",
|
||||||
|
"FR",
|
||||||
|
"DE"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static boolean isLoss(@NotNull String input) {
|
||||||
|
final String[] words = {
|
||||||
|
"§cGame Over!",
|
||||||
|
"§cPartie terminée!",
|
||||||
|
"§cDas Spiel ist vorbei!"
|
||||||
|
};
|
||||||
|
return Arrays.asList(words).contains(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isWin(@NotNull String input) {
|
||||||
|
final String[] words = {
|
||||||
|
"§aYou Win!",
|
||||||
|
"§aVous avez gagné!",
|
||||||
|
"§aDu gewinnst!"
|
||||||
|
};
|
||||||
|
return Arrays.asList(words).contains(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean containsHard(@NotNull String input) {
|
||||||
|
final String[] words = {
|
||||||
|
"Hard Difficulty",
|
||||||
|
"Difficulté Hard",
|
||||||
|
"Hard Schwierigkeitsgrad",
|
||||||
|
"困难",
|
||||||
|
"困難"
|
||||||
|
};
|
||||||
|
return Arrays.stream(words).anyMatch(input::contains);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean containsRIP(@NotNull String input) {
|
||||||
|
final String[] words = {
|
||||||
|
"RIP Difficulty",
|
||||||
|
"Difficulté RIP",
|
||||||
|
"RIP Schwierigkeitsgrad",
|
||||||
|
"安息"
|
||||||
|
};
|
||||||
|
return Arrays.stream(words).anyMatch(input::contains);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isHelicopterIncoming(@NotNull String input) {
|
||||||
|
final String[] words = {
|
||||||
|
"The Helicopter is on its way! Hold out for 120 more seconds!"
|
||||||
|
};
|
||||||
|
return Arrays.stream(words).anyMatch(input::contains);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull Pattern roundPattern(@NotNull String language) {
|
||||||
|
switch (language) {
|
||||||
|
case "EN":
|
||||||
|
return Pattern.compile("Round ([0-9]{1,3})");
|
||||||
|
case "FR":
|
||||||
|
return Pattern.compile("Manche ([0-9]{1,3})");
|
||||||
|
case "DE":
|
||||||
|
return Pattern.compile("Runde ([0-9]{1,3})");
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("Unexpected value: " + language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] getLanguages() {
|
||||||
|
return LANGUAGES;
|
||||||
|
}
|
||||||
|
}
|
30
src/main/java/xyz/stachel/zombiesutils/util/Utils.java
Normal file
30
src/main/java/xyz/stachel/zombiesutils/util/Utils.java
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package xyz.stachel.zombiesutils.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import xyz.stachel.zombiesutils.game.GameMode;
|
||||||
|
import xyz.stachel.zombiesutils.handlers.Location;
|
||||||
|
|
||||||
|
import static xyz.stachel.zombiesutils.game.GameMode.Map.*;
|
||||||
|
|
||||||
|
public class Utils {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static GameMode.Map getMap(String mode) {
|
||||||
|
return switch (mode) {
|
||||||
|
case "ZOMBIES_DEAD_END" -> DEAD_END;
|
||||||
|
case "ZOMBIES_BAD_BLOOD" -> BAD_BLOOD;
|
||||||
|
case "ZOMBIES_ALIEN_ARCADIUM" -> ALIEN_ARCADIUM;
|
||||||
|
case "ZOMBIES_PRISON" -> PRISON;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isZombies() {
|
||||||
|
return Location.getMode().startsWith("ZOMBIES");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isHypixel() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
6
src/main/resources/assets/zombies-utils/lang/en_us.json
Normal file
6
src/main/resources/assets/zombies-utils/lang/en_us.json
Normal file
|
@ -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"
|
||||||
|
}
|
6
src/main/resources/assets/zombies-utils/lang/ru_ru.json
Normal file
6
src/main/resources/assets/zombies-utils/lang/ru_ru.json
Normal file
|
@ -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": "Ближайшие игроки к вам теперь видимы."
|
||||||
|
}
|
|
@ -24,7 +24,7 @@
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
{
|
{
|
||||||
"config": "zombies-utils.client.mixins.json",
|
"config": "zombies-utils.mixins.json",
|
||||||
"environment": "client"
|
"environment": "client"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -33,7 +33,8 @@
|
||||||
"minecraft": "~1.21.5",
|
"minecraft": "~1.21.5",
|
||||||
"java": ">=21",
|
"java": ">=21",
|
||||||
"fabric-api": "*",
|
"fabric-api": "*",
|
||||||
"hypixel-mod-api": ">=1.0.1"
|
"hypixel-mod-api": ">=1.0.1",
|
||||||
|
"yet_another_config_lib_v3": ">=3.6.6"
|
||||||
},
|
},
|
||||||
"suggests": {}
|
"suggests": {}
|
||||||
}
|
}
|
||||||
|
|
13
src/main/resources/zombies-utils.mixins.json
Normal file
13
src/main/resources/zombies-utils.mixins.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"package": "xyz.stachel.zombiesutils.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_21",
|
||||||
|
"client": [
|
||||||
|
"ClientPlayNetworkHandlerMixin",
|
||||||
|
"OtherClientPlayerEntityMixin"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
},
|
||||||
|
"mixins": []
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue