Compare commits

...

3 commits

Author SHA1 Message Date
53572b6e84
update template
moved a lot of files and updated build scripts
2025-04-25 06:12:06 +02:00
4792caa473
patch prefix color, reformat project, publish as release
Some checks failed
Run Gradle Build / gradle (push) Has been cancelled
Validate Gradle Wrapper / Validation (push) Has been cancelled
2024-12-13 00:44:38 +01:00
263308e4a1
fix crash 2024-12-12 21:30:00 +01:00
66 changed files with 465 additions and 212 deletions

View file

@ -0,0 +1,38 @@
on:
push:
tags:
- '*'
jobs:
build:
runs-on: docker
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: make gradle wrapper executable
run: chmod +x ./gradlew
- name: set up jdk
run: |
INSTALL_DIR="/opt/java"
mkdir -p "$INSTALL_DIR"
JDK8_URL="https://cdn.azul.com/zulu/bin/zulu8.84.0.15-ca-jdk8.0.442-linux_x64.tar.gz"
JRE17_URL="https://cdn.azul.com/zulu/bin/zulu17.56.15-ca-jre17.0.14-linux_x64.tar.gz"
echo "Downloading JDK8 from $JDK8_URL"
curl -L "$JDK8_URL" | tar -xz -C "$INSTALL_DIR"
echo "Downloading JRE17 from $JRE17_URL"
curl -L "$JRE17_URL" | tar -xz -C "$INSTALL_DIR"
- name: build
run: JDK8=/opt/java/zulu8.84.0.15-ca-jdk8.0.442-linux_x64 JAVA_HOME=/opt/java/zulu17.56.15-ca-jre17.0.14-linux_x64 ./gradlew build
- name: capture build artifacts
uses: https://code.forgejo.org/forgejo/upload-artifact@v3
with:
name: Artifacts
path: 'build/libs'

4
.gitattributes vendored Normal file
View file

@ -0,0 +1,4 @@
gradlew* linguist-vendored
gradle/wrapper/* linguist-vendored
*.bat text eol=crlf

View file

@ -1,22 +0,0 @@
name: Run Gradle Build
on: [push, pull_request]
jobs:
gradle:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v3
- uses: actions/setup-java@v3
name: Setup Java
with:
distribution: temurin
java-version: 17
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Execute Gradle build
run: ./gradlew build
- uses: actions/upload-artifact@v3
name: Upload built mod JAR
with:
name: latest-autobuild
path: build/libs/*.jar

View file

@ -1,10 +0,0 @@
name: "Validate Gradle Wrapper"
on: [push, pull_request]
jobs:
validation:
name: "Validation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: gradle/wrapper-validation-action@v1

3
.gitignore vendored
View file

@ -1,6 +1,3 @@
.idea/
.vscode/
run/
build/
.gradle/

View file

@ -1,56 +1,80 @@
# zombies-utils
##### Download the latest release [here](https://github.com/Stachelbeere1248/zombies-utils/releases/latest)
Hello, I am currently working on this mod. More features will come. For now it has:
- An accurate timer + Automatic splitting
- Tracking of splits & segment PBs (with custom categories)
- SLA hud
- A chat macro
- Spawn-times HUD: visual, auditory, RL-mode
- Player Visibility
#### Disclaimers
- If you are using a Hypixel language other than the selected one the mod may not work entirely. Check config.
## For Users
The timer automatically splits every round. The PB/Segment recorder automatically distinguishes maps and difficulties, but not player count.
The timer automatically splits every round. The PB/Segment recorder automatically distinguishes maps and difficulties,
but not player count.
### Config
- `Language`: The selected Hypixel language. Currently supports EN,FR,DE.
- ###### Timer:
- `Default Category`: The record-category to be selected when starting the game.
- `PB Announcements`: Whether to show **\*\*\*NEW PERSONAL BEST\*\*\*** on PB in summaries.
- `Default Category`: The record-category to be selected when starting the game.
- `PB Announcements`: Whether to show **\*\*\*NEW PERSONAL BEST\*\*\*** on PB in summaries.
- ###### SST:
- `Enabled`: Enables / disables this feature.
- `Auditory`: A List of tick offsets that a sound should be played. Default (-40, -20, 0) means 2s and 1s in advance, as well as on spawn.
- `RL pre-timing`: During RL mode, how much SST times sohuld be offsetted. Defaults to 1.4s earlier. Affects HUD as well as auditory.
- `Truncate`: Whether to show passed rounds in the HUD.
- `Enabled`: Enables / disables this feature.
- `Auditory`: A List of tick offsets that a sound should be played. Default (-40, -20, 0) means 2s and 1s in
advance, as well as on spawn.
- `RL pre-timing`: During RL mode, how much SST times sohuld be offsetted. Defaults to 1.4s earlier. Affects HUD as
well as auditory.
- `Truncate`: Whether to show passed rounds in the HUD.
- ###### SLA:
- `Enabled`: Whether the SLA HUD should automatically be shown when starting a game.
- `Truncate`: Whether inactive windows and rooms should be shown.
- `Enabled`: Whether the SLA HUD should automatically be shown when starting a game.
- `Truncate`: Whether inactive windows and rooms should be shown.
- ###### Player Visibility:
- `Enabled`: Whether to enable PlayerVisibility by default.
- `Range`: The range within which players are hidden while enabled.
- `Enabled`: Whether to enable PlayerVisibility by default.
- `Range`: The range within which players are hidden while enabled.
- `Macro Message`: The Message to be sent when pressing the Chat Macro Key. Do NOT use "§" as symbol.
- `CPS Counter`: A simple CPS Counter which shows the amount of clicks within the last 20 gameticks.
### Commands
- /category \<name> - Switches to the category called name. All recorded times are bound to its category. Tabcomplete suggests already existing categories, but you can insert a new (clean) one as well.
- Examples:
- /category pistol_only
- /category no_doors_solo
- note: you do NOT need to make your own categories to seperate difficulties or map
- /category \<name> - Switches to the category called name. All recorded times are bound to its category. Tabcomplete
suggests already existing categories, but you can insert a new (clean) one as well.
- Examples:
- /category pistol_only
- /category no_doors_solo
- note: you do NOT need to make your own categories to seperate difficulties or map
- /sla \<off|map|quick|rotate|mirror|offset>
- /sla off - Disables the SLA hud
- /sla map \<de|bb|aa|p> - forcefully set the map
- /sla quick \<mogi_a|ghxula|ghxula-garden>
- useless for most players:
- /sla rotate - rotates all windows around the axis (0,y,0)
- /sla mirror \<x|z> - mirrors all windows along the plane (0,y,z) or (x,y,0)
- /sla offset \<x> \<y> \<z> - set an offset, allowing you to use sla on map-recreations, such as housings
- /sla off - Disables the SLA hud
- /sla map \<de|bb|aa|p> - forcefully set the map
- /sla quick \<mogi_a|ghxula|ghxula-garden>
- useless for most players:
- /sla rotate - rotates all windows around the axis (0,y,0)
- /sla mirror \<x|z> - mirrors all windows along the plane (0,y,z) or (x,y,0)
- /sla offset \<x> \<y> \<z> - set an offset, allowing you to use sla on map-recreations, such as housings
- /zombiesutils \<timer>
- /zombiesutils timer \<kill|split>
- /zombiesutils timer kill - Stops the running timer completely
- /zombiesutils timer split \<round> - Splits as if \<round> was passed, not recommended to use as it might create impossible PBs.
- /zombiesutils timer \<kill|split>
- /zombiesutils timer kill - Stops the running timer completely
- /zombiesutils timer split \<round> - Splits as if \<round> was passed, not recommended to use as it might
create impossible PBs.
- /qz \<de|bb|aa|p> - sends you to a new game of Dead End, Bad Blood, Alien Arcadium or Prison
### Hotkeys
- Chat Macro: Sends the message specified in the config.
- RL Mode: Toggles usage of the rocket launcher mode spawn-time offset.
- Player Visibility: Toggles whether to show players that are within a 4 block radius.
### Extra
- Managing split-categories: In your game directory (aka `.minecraft`) is a folder called `zombies` which contains the folder `splits`. You can simply rename or delete the folders inside `splits`, they represent your categories. You can also edit your splits, the data is stored as a list of ticks inside the `MAP_DIFFICULTY.times` files, a simple text editor (such as Notepad on Windows) should be able to edit it (UTF-16 encoded text). The other subfolder, runs, logs all the splits for every run you play.
- Managing split-categories: In your game directory (aka `.minecraft`) is a folder called `zombies` which contains the
folder `splits`. You can simply rename or delete the folders inside `splits`, they represent your categories. You can
also edit your splits, the data is stored as a list of ticks inside the `MAP_DIFFICULTY.times` files, a simple text
editor (such as Notepad on Windows) should be able to edit it (UTF-16 encoded text). The other subfolder, runs, logs
all the splits for every run you play.

View file

@ -1 +0,0 @@
- Distinguishing Escape

View file

@ -1,3 +1,5 @@
import org.apache.commons.lang3.SystemUtils
plugins {
idea
java
@ -8,11 +10,12 @@ plugins {
//Constants:
val baseGroup = "com.github.stachelbeere1248.zombiesutils"
val baseGroup: String by project
val mcVersion: String by project
val version: String by project
val mixinGroup = "$baseGroup.mixin"
val modid: String by project
val transformerFile = file("src/main/resources/accesstransformer.cfg")
// Toolchains:
java {
@ -26,14 +29,26 @@ loom {
"client" {
// If you don't want mixins, remove these lines
property("mixin.debug", "true")
property("asmhelper.verbose", "true")
arg("--tweakClass", "org.spongepowered.asm.launch.MixinTweaker")
}
}
runConfigs {
"client" {
if (SystemUtils.IS_OS_MAC_OSX) {
// This argument causes a crash on macOS
vmArgs.remove("-XstartOnFirstThread")
}
}
remove(getByName("server"))
}
forge {
pack200Provider.set(dev.architectury.pack200.java.Pack200Adapter())
// If you don't want mixins, remove this lines
mixinConfig("mixins.$modid.json")
if (transformerFile.exists()) {
println("Installing access transformer")
accessTransformer(transformerFile)
}
}
// If you don't want mixins, remove these lines
mixin {
@ -50,8 +65,6 @@ sourceSets.main {
repositories {
mavenCentral()
maven("https://repo.spongepowered.org/maven/")
// If you don't want to log in with your real minecraft account, remove this line
maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1")
}
val shadowImpl: Configuration by configurations.creating {
@ -68,10 +81,6 @@ dependencies {
isTransitive = false
}
annotationProcessor("org.spongepowered:mixin:0.8.5-SNAPSHOT")
// If you don't want to log in with your real minecraft account, remove this line
runtimeOnly("me.djtheredstoner:DevAuth-forge-legacy:1.1.2")
}
// Tasks:
@ -80,7 +89,7 @@ tasks.withType(JavaCompile::class) {
options.encoding = "UTF-8"
}
tasks.withType(Jar::class) {
tasks.withType(org.gradle.jvm.tasks.Jar::class) {
archiveBaseName.set(modid)
manifest.attributes.run {
this["FMLCorePluginContainsFMLMod"] = "true"
@ -89,6 +98,8 @@ tasks.withType(Jar::class) {
// If you don't want mixins, remove these lines
this["TweakClass"] = "org.spongepowered.asm.launch.MixinTweaker"
this["MixinConfigs"] = "mixins.$modid.json"
if (transformerFile.exists())
this["FMLAT"] = "${modid}_at.cfg"
}
}
@ -96,13 +107,13 @@ tasks.processResources {
inputs.property("version", project.version)
inputs.property("mcversion", mcVersion)
inputs.property("modid", modid)
inputs.property("mixinGroup", mixinGroup)
inputs.property("basePackage", baseGroup)
filesMatching(listOf("mcmod.info", "mixins.$modid.json")) {
expand(inputs.properties)
}
rename("(.+_at.cfg)", "META-INF/$1")
rename("accesstransformer.cfg", "META-INF/${modid}_at.cfg")
}
@ -114,16 +125,16 @@ val remapJar by tasks.named<net.fabricmc.loom.task.RemapJarTask>("remapJar") {
tasks.jar {
archiveClassifier.set("without-deps")
destinationDirectory.set(layout.buildDirectory.dir("badjars"))
destinationDirectory.set(layout.buildDirectory.dir("intermediates"))
}
tasks.shadowJar {
destinationDirectory.set(layout.buildDirectory.dir("badjars"))
archiveClassifier.set("all-dev")
destinationDirectory.set(layout.buildDirectory.dir("intermediates"))
archiveClassifier.set("non-obfuscated-with-deps")
configurations = listOf(shadowImpl)
doLast {
configurations.forEach {
println("Copying jars into mod: ${it.files}")
println("Copying dependencies into mod: ${it.files}")
}
}

View file

@ -1,6 +1,7 @@
loom.platform=forge
org.gradle.jvmargs=-Xmx2g
baseGroup = com.github.stachelbeere1248.zombiesutils
baseGroup = xyz.stachel.zombiesutils
mcVersion = 1.8.9
modid = zombiesutils
version = 1.3.7-PRE_1
version = 1.4.0
org.gradle.java.installations.fromEnv=JDK8,JRE17

Binary file not shown.

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

19
gradlew vendored
View file

@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -83,7 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -201,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \

20
gradlew.bat vendored
View file

@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail

View file

@ -7,7 +7,7 @@ pluginManagement {
maven("https://maven.fabricmc.net")
maven("https://maven.minecraftforge.net/")
maven("https://repo.spongepowered.org/maven/")
maven("https://repo.sk1er.club/repository/maven-releases/")
maven("https://repo.essential.gg/repository/maven-releases/")
}
resolutionStrategy {
eachPlugin {

View file

@ -1,39 +0,0 @@
package com.github.stachelbeere1248.zombiesutils.game.waves;
import java.util.stream.IntStream;
public enum Prefix {
BOSS(0xCC5555, "B"),
BLAZES(0xEFB61F, "BL"),
SLIME(0x88FF88,"S"),
HBM(0x2A415F, "HBM"),
WITHER_SKELETON(0x888888, "WS"),
OLD_ONE(0x55AA55, "O1"),
GIANT(0x00FFFF,"G"),
POLICE(0x16537E,"P"),
CELL(0xFF8234,"C"),
WINDOW(0xAAAAAA,"W");
private final int color;
private final String prefix;
Prefix(final int color, final String prefix) {
this.color = color;
this.prefix = prefix;
}
public int getColor() {
return color;
}
public String getPrefix() {
return prefix;
}
public int getFadedColor(final int fact, final int div) {
final int normalColor = this.getColor();
final int B = normalColor % 0xFF;
final int G = (normalColor - B) % (0xFF * 0xFF);
final int R = (normalColor - (B + G));
return IntStream.of(R, G, B).map(i -> (i * fact) / div).sum();
}
}

View file

@ -1,8 +1,8 @@
package com.github.stachelbeere1248.zombiesutils.commands;
import com.github.stachelbeere1248.zombiesutils.game.windows.SLA;
import com.github.stachelbeere1248.zombiesutils.game.enums.Map;
import com.github.stachelbeere1248.zombiesutils.game.sla.QuickSLA;
import com.github.stachelbeere1248.zombiesutils.game.windows.SLA;
import net.minecraft.command.*;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ChatComponentText;

View file

@ -68,8 +68,7 @@ public class ZombiesUtilsCommand extends CommandBase {
default:
return Collections.emptyList();
}
}
else if (args.length == 3) {
} else if (args.length == 3) {
switch (args[0]) {
case "timer":
switch (args[1]) {

View file

@ -41,6 +41,7 @@ public class Hotkeys {
public KeyBinding getRlSpawn() {
return rlSpawn;
}
public KeyBinding getPlayerVisiblity() {
return playerVisiblity;
}

View file

@ -158,6 +158,7 @@ public class ZombiesUtilsConfig {
new CustomConfigElement("PB announcements", announcePB)
);
}
private List<IConfigElement> getPlayerVisElements() {
return Arrays.asList(
new CustomConfigElement("Enabled", playerVis),
@ -218,14 +219,17 @@ public class ZombiesUtilsConfig {
public boolean getCpsToggle() {
return cpsCounter.getBoolean();
}
public boolean getAnnouncePB() {
return announcePB.getBoolean();
}
public boolean getPlayerVis() {
return playerVis.getBoolean();
}
public int getPlayerVisRange() {
return playerVis.getInt();
return playerVisRange.getInt();
}
@SubscribeEvent

View file

@ -8,6 +8,7 @@ import org.jetbrains.annotations.NotNull;
public class GameData {
private final Round[][] roundData;
public GameData() {
roundData = new Round[10][];
roundData[0] = readFromFile("data/rounds/DEAD_END_NORMAL.json");
@ -25,25 +26,25 @@ public class GameData {
public Round getRound(@NotNull GameMode gameMode, int round) {
switch (gameMode) {
case DEAD_END:
return roundData[0][round-1];
return roundData[0][round - 1];
case DEAD_END_HARD:
return roundData[1][round-1];
return roundData[1][round - 1];
case DEAD_END_RIP:
return roundData[2][round-1];
return roundData[2][round - 1];
case BAD_BLOOD:
return roundData[3][round-1];
return roundData[3][round - 1];
case BAD_BLOOD_HARD:
return roundData[4][round-1];
return roundData[4][round - 1];
case BAD_BLOOD_RIP:
return roundData[5][round-1];
return roundData[5][round - 1];
case ALIEN_ARCADIUM:
return roundData[6][round-1];
return roundData[6][round - 1];
case PRISON:
return roundData[7][round-1];
return roundData[7][round - 1];
case PRISON_HARD:
return roundData[8][round-1];
return roundData[8][round - 1];
case PRISON_RIP:
return roundData[9][round-1];
return roundData[9][round - 1];
default:
throw new IllegalStateException("Invalid GameMode: " + gameMode);
}

View file

@ -12,11 +12,28 @@ public enum GameMode {
PRISON(Map.PRISON, Difficulty.NORMAL), PRISON_HARD(Map.PRISON, Difficulty.HARD), PRISON_RIP(Map.PRISON, Difficulty.RIP);
private final Map map;
private final Difficulty difficulty;
GameMode(final @NotNull Map map, final @NotNull Difficulty difficulty) {
this.map = map;
this.difficulty = difficulty;
}
@Contract(pure = true)
public static GameMode getNormalForMap(final @NotNull Map map) {
switch (map) {
case DEAD_END:
return DEAD_END;
case BAD_BLOOD:
return BAD_BLOOD;
case ALIEN_ARCADIUM:
return ALIEN_ARCADIUM;
case PRISON:
return PRISON;
default:
throw new IllegalStateException("Unexpected value: " + map);
}
}
public Map getMap() {
return this.map;
}
@ -24,6 +41,7 @@ public enum GameMode {
public Difficulty getDifficulty() {
return this.difficulty;
}
public GameMode appliedDifficulty(final Difficulty difficulty) {
switch (this.map) {
case DEAD_END:
@ -59,23 +77,8 @@ public enum GameMode {
throw new IllegalStateException("Invalid Map: " + this.map);
}
}
public boolean isMap(Map map) {
return this.getMap() == map;
}
@Contract(pure = true)
public static GameMode getNormalForMap(final @NotNull Map map) {
switch (map) {
case DEAD_END:
return DEAD_END;
case BAD_BLOOD:
return BAD_BLOOD;
case ALIEN_ARCADIUM:
return ALIEN_ARCADIUM;
case PRISON:
return PRISON;
default:
throw new IllegalStateException("Unexpected value: " + map);
}
}
}

View file

@ -14,7 +14,7 @@ public enum Map {
public static Optional<Map> getMap() {
World world = Minecraft.getMinecraft().theWorld;
BlockPos pos = new BlockPos(44,71,0);
BlockPos pos = new BlockPos(44, 71, 0);
if (!world.isBlockLoaded(pos) || Scoreboard.isNotZombies()) return Optional.empty();
Block block = world.getBlockState(pos).getBlock();

View file

@ -1,7 +1,7 @@
package com.github.stachelbeere1248.zombiesutils.game.sla;
import com.github.stachelbeere1248.zombiesutils.game.windows.SLA;
import com.github.stachelbeere1248.zombiesutils.game.enums.Map;
import com.github.stachelbeere1248.zombiesutils.game.windows.SLA;
@SuppressWarnings("SpellCheckingInspection")
public class QuickSLA {

View file

@ -0,0 +1,37 @@
package com.github.stachelbeere1248.zombiesutils.game.waves;
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;
}
}

View file

@ -1,8 +1,5 @@
package com.github.stachelbeere1248.zombiesutils.game.waves;
import java.util.Arrays;
import java.util.stream.Collectors;
public class Round {
private final Wave[] waves;

View file

@ -9,9 +9,10 @@ public class Wave {
this.ticks = ticks;
this.prefixes = prefixes;
}
public Wave(final short ticks) {
this.ticks = ticks;
this.prefixes = new Prefix[]{Prefix.WINDOW};
this.prefixes = new Prefix[]{ Prefix.WINDOW };
}
public short getTime() {

View file

@ -8,6 +8,7 @@ import java.util.Arrays;
public class WaveTiming {
public static int rl = 0;
public static void onTick() {
if (Scoreboard.isNotZombies()) return;
ZombiesUtils.getInstance().getGameManager().getGame().ifPresent(

View file

@ -2,10 +2,9 @@ package com.github.stachelbeere1248.zombiesutils.handlers;
import com.github.stachelbeere1248.zombiesutils.ZombiesUtils;
import com.github.stachelbeere1248.zombiesutils.game.waves.Prefix;
import com.github.stachelbeere1248.zombiesutils.game.waves.Round;
import com.github.stachelbeere1248.zombiesutils.game.waves.Wave;
import com.github.stachelbeere1248.zombiesutils.game.windows.SLA;
import com.github.stachelbeere1248.zombiesutils.game.windows.Room;
import com.github.stachelbeere1248.zombiesutils.game.windows.SLA;
import com.github.stachelbeere1248.zombiesutils.timer.Game;
import com.github.stachelbeere1248.zombiesutils.utils.Scoreboard;
import net.minecraft.client.Minecraft;
@ -52,7 +51,8 @@ public class RenderGameOverlayHandler {
}
);
if (!Minecraft.getMinecraft().gameSettings.showDebugInfo) SLA.getInstance().ifPresent(sla -> renderSla(sla.getRooms()));
if (!Minecraft.getMinecraft().gameSettings.showDebugInfo)
SLA.getInstance().ifPresent(sla -> renderSla(sla.getRooms()));
if (ZombiesUtils.getInstance().getConfig().getCpsToggle()) renderCPS();
}
@ -87,6 +87,7 @@ public class RenderGameOverlayHandler {
y++;
}
}
private void renderSpawnTime(final Game game) {
if (!ZombiesUtils.getInstance().getConfig().getSST() || Scoreboard.isNotZombies()) return;
final ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
@ -123,7 +124,7 @@ public class RenderGameOverlayHandler {
prefixString,
screenWidth - width,
screenHeight - fontRenderer.FONT_HEIGHT * (length - heightIndex),
faded ? prefix.getFadedColor(3,5) : prefix.getColor()
faded ? prefix.getFadedColor() : prefix.getColor()
);
}
if (!faded) color = 0xAAAAAA;
@ -132,7 +133,7 @@ public class RenderGameOverlayHandler {
}
public void renderCPS() {
public void renderCPS() {
final String cps = String.format("%2d", getClicks());
final ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
final int screenWidth = scaledResolution.getScaledWidth();

View file

@ -27,6 +27,7 @@ public class RenderPlayerHandler {
final int range = ZombiesUtils.getInstance().getConfig().getPlayerVisRange();
return playerOther.squareDistanceTo(Minecraft.getMinecraft().thePlayer.getPositionVector()) <= range * range;
}
public void togglePlayerVisibility() {
this.visible = !this.visible;
final String s;

View file

@ -0,0 +1,188 @@
package xyz.stachel.zombiesutils.init;
import org.spongepowered.asm.lib.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* A mixin plugin to automatically discover all mixins in the current JAR.
* <p>
* This mixin plugin automatically scans your entire JAR (or class directory, in case of an in-IDE launch) for classes inside of your
* mixin package and registers those. It does this recursively for sub packages of the mixin package as well. This means you will need
* to only have mixin classes inside of your mixin package, which is good style anyway.
*
* @author Linnea Gräf
*/
public class AutoDiscoveryMixinPlugin implements IMixinConfigPlugin {
private static final List<AutoDiscoveryMixinPlugin> mixinPlugins = new ArrayList<>();
public static List<AutoDiscoveryMixinPlugin> getMixinPlugins() {
return mixinPlugins;
}
private String mixinPackage;
@Override
public void onLoad(String mixinPackage) {
this.mixinPackage = mixinPackage;
mixinPlugins.add(this);
}
/**
* Resolves the base class root for a given class URL. This resolves either the JAR root, or the class file root.
* In either case the return value of this + the class name will resolve back to the original class url, or to other
* class urls for other classes.
*/
public URL getBaseUrlForClassUrl(URL classUrl) {
String string = classUrl.toString();
if (classUrl.getProtocol().equals("jar")) {
try {
return new URL(string.substring(4).split("!")[0]);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
if (string.endsWith(".class")) {
try {
return new URL(string.replace("\\", "/")
.replace(getClass().getCanonicalName()
.replace(".", "/") + ".class", ""));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
return classUrl;
}
/**
* Get the package that contains all the mixins. This value is set by mixin itself using {@link #onLoad}.
*/
public String getMixinPackage() {
return mixinPackage;
}
/**
* Get the path inside the class root to the mixin package
*/
public String getMixinBaseDir() {
return mixinPackage.replace(".", "/");
}
/**
* A list of all discovered mixins.
*/
private List<String> mixins = null;
/**
* Try to add mixin class ot the mixins based on the filepath inside of the class root.
* Removes the {@code .class} file suffix, as well as the base mixin package.
* <p><b>This method cannot be called after mixin initialization.</p>
*
* @param className the name or path of a class to be registered as a mixin.
*/
public void tryAddMixinClass(String className) {
String norm = (className.endsWith(".class") ? className.substring(0, className.length() - ".class".length()) : className)
.replace("\\", "/")
.replace("/", ".");
if (norm.startsWith(getMixinPackage() + ".") && !norm.endsWith(".")) {
mixins.add(norm.substring(getMixinPackage().length() + 1));
}
}
/**
* Search through the JAR or class directory to find mixins contained in {@link #getMixinPackage()}
*/
@Override
public List<String> getMixins() {
if (mixins != null) return mixins;
System.out.println("Trying to discover mixins");
mixins = new ArrayList<>();
URL classUrl = getClass().getProtectionDomain().getCodeSource().getLocation();
System.out.println("Found classes at " + classUrl);
Path file;
try {
file = Paths.get(getBaseUrlForClassUrl(classUrl).toURI());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
System.out.println("Base directory found at " + file);
if (Files.isDirectory(file)) {
walkDir(file);
} else {
walkJar(file);
}
System.out.println("Found mixins: " + mixins);
return mixins;
}
/**
* Search through directory for mixin classes based on {@link #getMixinBaseDir}.
*
* @param classRoot The root directory in which classes are stored for the default package.
*/
private void walkDir(Path classRoot) {
System.out.println("Trying to find mixins from directory");
try (Stream<Path> classes = Files.walk(classRoot.resolve(getMixinBaseDir()))) {
classes.map(it -> classRoot.relativize(it).toString())
.forEach(this::tryAddMixinClass);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Read through a JAR file, trying to find all mixins inside.
*/
private void walkJar(Path file) {
System.out.println("Trying to find mixins from jar file");
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(file))) {
ZipEntry next;
while ((next = zis.getNextEntry()) != null) {
tryAddMixinClass(next.getName());
zis.closeEntry();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return true;
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
}
}

View file

@ -39,8 +39,8 @@ public class MixinNetHandlerPlayClient {
if (!(
soundEffect.equals("mob.wither.spawn")
|| (soundEffect.equals("mob.guardian.curse")
&& !zombies_utils$alienUfoOpened)
|| (soundEffect.equals("mob.guardian.curse")
&& !zombies_utils$alienUfoOpened)
)) return;
zombies_utils$alienUfoOpened = soundEffect.equals("mob.guardian.curse");
@ -59,8 +59,8 @@ public class MixinNetHandlerPlayClient {
if (Scoreboard.isNotZombies()) return;
final String message = packet.getMessage().getUnformattedText().trim();
String serverNumber;
serverNumber = Scoreboard.getServerNumber().orElse("");
if (LanguageSupport.isWin(message)) ZombiesUtils.getInstance().getGameManager().endGame(serverNumber,true);
serverNumber = Scoreboard.getServerNumber().orElse("");
if (LanguageSupport.isWin(message)) ZombiesUtils.getInstance().getGameManager().endGame(serverNumber, true);
if (LanguageSupport.isLoss(message)) ZombiesUtils.getInstance().getGameManager().endGame(serverNumber, false);
}

View file

@ -3,8 +3,8 @@ package com.github.stachelbeere1248.zombiesutils.timer;
import com.github.stachelbeere1248.zombiesutils.ZombiesUtils;
import com.github.stachelbeere1248.zombiesutils.game.GameMode;
import com.github.stachelbeere1248.zombiesutils.game.enums.Difficulty;
import com.github.stachelbeere1248.zombiesutils.game.windows.SLA;
import com.github.stachelbeere1248.zombiesutils.game.enums.Map;
import com.github.stachelbeere1248.zombiesutils.game.windows.SLA;
import com.github.stachelbeere1248.zombiesutils.handlers.Round1Correction;
import com.github.stachelbeere1248.zombiesutils.timer.recorder.Category;
import com.github.stachelbeere1248.zombiesutils.timer.recorder.files.CategoryFile;
@ -35,6 +35,7 @@ public class Game {
MinecraftForge.EVENT_BUS.register(new Round1Correction(this.timer, serverNumber));
if (ZombiesUtils.getInstance().getConfig().isSlaToggled()) SLA.instance = new SLA(map);
}
public Game(@NotNull final Map map, final String serverNumber, final int round) {
this.gameMode = GameMode.getNormalForMap(map);
this.timer = new Timer();
@ -49,17 +50,21 @@ public class Game {
}
public Timer getTimer() {
return this.timer;
return this.timer;
}
public void setCategory(Category category) {
this.category = category;
}
public void changeDifficulty(final Difficulty difficulty) {
this.gameMode = this.gameMode.appliedDifficulty(difficulty);
}
public int getRound() {
return round;
}
public GameMode getGameMode() {
return gameMode;
}
@ -78,6 +83,7 @@ public class Game {
this.timer.split();
this.round = round + 1;
}
public void helicopter() {
if (!gameMode.isMap(Map.PRISON)) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§cEscaping without playing prison???"));
@ -89,9 +95,9 @@ public class Game {
}
private void record() {
this.compareSegment();
if (this.roundOneRecorded) this.compareBest();
this.gameFile.setSegment(this.round, this.timer.getRoundTime());
this.compareSegment();
if (this.roundOneRecorded) this.compareBest();
this.gameFile.setSegment(this.round, this.timer.getRoundTime());
}
public void compareSegment() throws IndexOutOfBoundsException {

View file

@ -29,14 +29,14 @@ public class GameManager {
final Game game = GAMES.get(serverNumber);
if (isWin) {
switch (game.getGameMode().getMap()) {
case DEAD_END:
case BAD_BLOOD:
case PRISON:
game.pass(30);
break;
case ALIEN_ARCADIUM:
game.pass(105);
break;
case DEAD_END:
case BAD_BLOOD:
case PRISON:
game.pass(30);
break;
case ALIEN_ARCADIUM:
game.pass(105);
break;
}
}
GAMES.remove(serverNumber);

View file

@ -15,13 +15,14 @@ public class RecordMessageSender {
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.deltaString = oldTime != 0 ? " " + formattedDelta(newTime, oldTime) : "";
this.timeString = formattedTime(newTime);
this.round = round;
}
@ -29,8 +30,8 @@ public class RecordMessageSender {
public void sendRecordMessage() {
final ChatComponentText message = new ChatComponentText(
this.recordMessage
.append("\n§l§a▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬")
.toString()
.append("\n§l§a▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬")
.toString()
);
message.setChatStyle(new ChatStyle().setChatClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, this.copyString)));
Minecraft.getMinecraft().thePlayer.addChatMessage(message);
@ -69,6 +70,7 @@ public class RecordMessageSender {
String.format("Round %d took %s!", round, timeString) :
String.format("Round %d took %s (%s)!", round, timeString, deltaString);
}
public void helicopterSplit() {
final String announcement = newTime < oldTime && ZombiesUtils.getInstance().getConfig().getAnnouncePB() ?
"\n§e§l***§6§l NEW PERSONAL BEST! §e§l***" : "";
@ -82,6 +84,7 @@ public class RecordMessageSender {
String.format("Helicopter called at %s!", timeString) :
String.format("Helicopter called at %s (%s)!", timeString, deltaString);
}
@Contract(pure = true)
private String formattedTime(int time) {
time *= 50;
@ -92,6 +95,7 @@ public class RecordMessageSender {
(time % 100) / 10
);
}
@Contract(pure = true)
private String formattedDelta(int newTime, int oldTime) {
final double delta = (double) (newTime - oldTime) / 20;

View file

@ -14,9 +14,11 @@ public class Timer {
public void correctStartTick() {
this.startTick = this.getCurrentTick() - 200;
}
void split() {
this.roundStart = this.getGameTime();
}
public int getGameTime() {
return (int) (getCurrentTick() - startTick);
}

View file

@ -51,6 +51,7 @@ public class LanguageSupport {
};
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!"
@ -70,6 +71,7 @@ public class LanguageSupport {
throw new IllegalStateException("Unexpected value: " + language);
}
}
public static String[] getLanguages() {
return LANGUAGES;
}

View file

@ -0,0 +1,2 @@
public net.minecraft.client.renderer.GlStateManager$Color

View file

@ -1,11 +1,8 @@
{
"package": "com.github.stachelbeere1248.zombiesutils.mixin",
"package": "${basePackage}.mixin",
"plugin": "${basePackage}.init.AutoDiscoveryMixinPlugin",
"refmap": "mixins.${modid}.refmap.json",
"minVersion": "0.7",
"compatibilityLevel": "JAVA_8",
"mixins": [
],
"client": [
"MixinNetHandlerPlayClient"
]
"__comment": "You do not need to manually register mixins in this template. Check the auto discovery mixin plugin for more info."
}

View file

@ -1,11 +1,13 @@
{
"homepage": "https://github.com/Stachelbeere1248/zombies-utils/releases",
"promos": {
"1.8.9-latest" : "1.3.7-PRE_1",
"1.8.9-recommended" : "1.3.6"
"1.8.9-latest": "1.3.7",
"1.8.9-recommended": "1.3.7"
},
"1.8.9" : {
"1.3.6" : "SST Prefixes, added update checker url",
"1.3.7-PRE_1" : "SST Prefixes, added update checker url"
"1.8.9": {
"1.3.6": "SST Prefixes, added update checker url",
"1.3.7-PRE_1": "patch: difficiluty detection",
"1.3.7-PRE_2": "fix instant crash",
"1.3.7": "mark release, fix faded prefix colors"
}
}