diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml
index 5afcc3c..a2ffc8e 100644
--- a/.forgejo/workflows/build.yml
+++ b/.forgejo/workflows/build.yml
@@ -2,30 +2,31 @@ on: [push]
jobs:
build:
runs-on: docker
- container: eclipse-temurin:21-alpine
+ container: debian:sid
steps:
- - name: Install build dependencies
- run: apk add nodejs curl tar zstd
+ - name: Install JDK and other deps
+ run: apt update && apt install --no-install-recommends -y openjdk-21-jdk-headless maven git nodejs curl zstd
- - name: Checkout
- uses: https://github.com/actions/checkout@v4
+ - name: Clone repository
+ run: git clone -b ${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} https://git.m724.eu/Minecon724/tweaks724.git .
- name: Download NMS
run: ./tools/download_nms.sh ~
- - name: Build for 1.21.4
- run: ./mvnw package -Dproject.minecraft.version=1.21.4 -Dproject.craftbukkit.version=v1_21_R3
-
- - name: Build for 1.21.3
- run: ./mvnw package -Dproject.minecraft.version=1.21.3 -Dproject.craftbukkit.version=v1_21_R2
- name: Build for 1.21.1
- run: ./mvnw package -Dproject.minecraft.version=1.21.1 -Dproject.craftbukkit.version=v1_21_R1
+ run: mvn package -Dproject.minecraft.version=1.21.1 -Dproject.nms.version=v1_21_R1
+
+ - name: Build for 1.21.3
+ run: mvn package -Dproject.minecraft.version=1.21.3 -Dproject.nms.version=v1_21_R2
+
+ - name: Build for 1.21.4
+ run: mvn package -Dproject.minecraft.version=1.21.4 -Dproject.nms.version=v1_21_R3
- name: Upload artifacts
uses: https://github.com/actions/upload-artifact@v3
with:
- path: target/tweaks-*.jar
\ No newline at end of file
+ path: target
\ No newline at end of file
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
deleted file mode 100644
index d58dfb7..0000000
--- a/.mvn/wrapper/maven-wrapper.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-wrapperVersion=3.3.2
-distributionType=only-script
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
diff --git a/README.md b/README.md
index 3f18c19..1e49879 100644
--- a/README.md
+++ b/README.md
@@ -12,37 +12,37 @@ Please report all suspicious behavior. You can do so on any of those:
Stuff not many other plugins do.
Dependencies:
-- **1.21.1 and newer**
+- **1.21.1**, recommended as the plugin uses NMS for some stuff \
+ However, it's not forced, so it's quite probable it'll work on other versions. Please test. If you get an error, it's most often because of a module using NMS. Disable that module, and report the error \
+ Why not latest? The focus is on [a widely used version](https://bstats.org/global/bukkit) that has [good mod support](https://modrinth.com/modpack/fabulously-optimized/versions?c=release)
- [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/)
-- To use modules marked N, you must use a JAR [made for the exact server version.](/Minecon724/tweaks724/src/branch/master/docs/BUILDING.md)
# Features
-N - requires a specific version \
-P - requires ProtocolLib
-
-### Expand world border N
+### Expand world border
Expands the world border to 30,000,000 (from 29,999,984)
-### Hide world border P
+### Hide world border
Hides the world border. It's still there, just invisible.
-### Server brand N P
+### Server brand
Modify the F3 brand, optionally include player's ping and server performance
### Doors
Open two doors with one click. Knock on doors.
-### MOTD N P
+### MOTD
Random MOTD for every ping
-### Chat mods N
-- Chat rooms players can freely create and join. Alerts like death and join messages are only within the player's chat room.
-- Proximity chat
+### Chat rooms
+Chat rooms players can freely create and join. Alerts like death and join messages are only within the player's chat room.
`/chat` - switch chat room \
`/chatmanage` - create, delete, modify etc. (`tweaks724.chatmanage`)
+### Proximity chat
+Self-explanatory
+
### Compass
Holding a compass shows a bar with 4 directions and stuff like beds, lodestones, death pos (TODO) etc.
@@ -52,23 +52,20 @@ Self-discipline with a pomodoro timer that's actually forced
`/pomodoro` (`tweaks724.pomodoro`)
### Updater
-Checks for updates of ALL* your plugins \
-Updates are still installed manually \
+Updates ALL* your plugins \
*Those on SpigotMC and that release updates there
`/updates` - shows available updates (`tweaks724.updates`)
-### Hardcore N P
+### Hardcore
Hardcore hearts by chance
### Sleep
Sleeping doesn't skip night, but speeds it up. The more players, the faster it goes.
- Instant sleep \
- One can instantly skip, but only a part of the night. \
- There's 5 players on the server. A night is 10 minutes long. \
- Each player can instantly skip 2 minutes of the night at any time, even if others aren't sleeping
-- Heal \
- Sleeping heals
+One can instantly skip, but only a part of the night. \
+There's 5 players on the server. A night is 10 minutes long. \
+Each player can instantly skip 2 minutes of the night at any time, even if others aren't sleeping
### Authentication
Players are given a unique subdomain like "\.example.com" and they must use it to join \
@@ -79,38 +76,21 @@ It can be enabled that new players can't join the server without a key
### Full join
Players with `tweaks724.bypass-full` can join even when the server is full
-### Emergency alerts P
+### Emergency alerts
Issue messages that the player needs to read to keep playing, and that make an attention grabbing sound
`/emergencyalerts` (`tweaks724.emergencyalerts`)
### Remote redstone
Adds a "gateway" item that are controlled over internet. \
-[RETSTONE.md for more info](/Minecon724/tweaks724/src/branch/master/docs/RETSTONE.md)
+[RETSTONE.md for more info](/Minecon724/tweaks724/src/branch/master/RETSTONE.md)
### Knockback
Control knockback dealt by entities
-### Kill switch
-Quickly kills (terminates) the server on trigger, via command or HTTP request.
-[KILLSWITCH.md for more info](/Minecon724/tweaks724/src/branch/master/docs/KILLSWITCH.md)
-
-### Swing through grass
-Self-explanatory
-
-### Durability alert
-Self-explanatory too.
-
-`/durabilityalert` (`tweaks724.durabilityalert`)
-
-### Word coords
-Convert coordinates to easier to remember words
-
-`/wordcoords` (`tweaks724.tauth`)
-
### Utility commands
-- `/ping` - displays player ping P \
+- `/ping` - displays player ping \
**Ping is calculated by the plugin**. \
That allows for more precision (decimal places) and to get the ping immediately after a player join
diff --git a/docs/BUILDING.md b/docs/BUILDING.md
deleted file mode 100644
index 7af000f..0000000
--- a/docs/BUILDING.md
+++ /dev/null
@@ -1,32 +0,0 @@
-First, download NMS. There are two ways:
-
-- Use `tools/download_nms.sh`
-- Download BuildTools, move it into an empty directory and run:
- ```
- java -jar BuildTools.jar --rev 1.21.4 --remapped
- ```
- You must run this for every version you want to build for.
-
-
-
-Then build the plugin:
-
-1. Clone this repository:
- ```
- git clone https://git.m724.eu/Minecon724/tweaks724
- cd tweaks724
- ```
- - You might want to `checkout` a release:
- ```
- git checkout tags/tweaks-0.1.12
- ```
-2. For the "native" version:
- ```
- ./mvnw package
- ```
- For another compatible version:
- ```
- ./mvnw package -Dproject.craftbukkit.version=v1_21_R3 -Dproject.minecraft.version=1.21.4
- ```
-
-Look for `tweaks-0.1.12+1.21.4.jar` in `target/`
\ No newline at end of file
diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md
new file mode 100644
index 0000000..e1404cb
--- /dev/null
+++ b/docs/DEVELOPMENT.md
@@ -0,0 +1,5 @@
+To setup NMS:
+1. Download BuildTools, move it into an empty directory and open terminal
+2. ```
+ java -jar BuildTools.jar --rev 1.21.1 --remapped
+ ```
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index c44787d..0000000
--- a/docs/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-Here's the documentation.
-
-Click above on a file to read more about a topic.
\ No newline at end of file
diff --git a/mvnw b/mvnw
deleted file mode 100755
index 19529dd..0000000
--- a/mvnw
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/bin/sh
-# ----------------------------------------------------------------------------
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-# ----------------------------------------------------------------------------
-
-# ----------------------------------------------------------------------------
-# Apache Maven Wrapper startup batch script, version 3.3.2
-#
-# Optional ENV vars
-# -----------------
-# JAVA_HOME - location of a JDK home dir, required when download maven via java source
-# MVNW_REPOURL - repo url base for downloading maven distribution
-# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
-# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
-# ----------------------------------------------------------------------------
-
-set -euf
-[ "${MVNW_VERBOSE-}" != debug ] || set -x
-
-# OS specific support.
-native_path() { printf %s\\n "$1"; }
-case "$(uname)" in
-CYGWIN* | MINGW*)
- [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
- native_path() { cygpath --path --windows "$1"; }
- ;;
-esac
-
-# set JAVACMD and JAVACCMD
-set_java_home() {
- # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
- if [ -n "${JAVA_HOME-}" ]; then
- if [ -x "$JAVA_HOME/jre/sh/java" ]; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- JAVACCMD="$JAVA_HOME/jre/sh/javac"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- JAVACCMD="$JAVA_HOME/bin/javac"
-
- if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
- echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
- echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
- return 1
- fi
- fi
- else
- JAVACMD="$(
- 'set' +e
- 'unset' -f command 2>/dev/null
- 'command' -v java
- )" || :
- JAVACCMD="$(
- 'set' +e
- 'unset' -f command 2>/dev/null
- 'command' -v javac
- )" || :
-
- if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
- echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
- return 1
- fi
- fi
-}
-
-# hash string like Java String::hashCode
-hash_string() {
- str="${1:-}" h=0
- while [ -n "$str" ]; do
- char="${str%"${str#?}"}"
- h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
- str="${str#?}"
- done
- printf %x\\n $h
-}
-
-verbose() { :; }
-[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
-
-die() {
- printf %s\\n "$1" >&2
- exit 1
-}
-
-trim() {
- # MWRAPPER-139:
- # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
- # Needed for removing poorly interpreted newline sequences when running in more
- # exotic environments such as mingw bash on Windows.
- printf "%s" "${1}" | tr -d '[:space:]'
-}
-
-# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
-while IFS="=" read -r key value; do
- case "${key-}" in
- distributionUrl) distributionUrl=$(trim "${value-}") ;;
- distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
- esac
-done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
-[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
-
-case "${distributionUrl##*/}" in
-maven-mvnd-*bin.*)
- MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
- case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
- *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
- :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
- :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
- :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
- *)
- echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
- distributionPlatform=linux-amd64
- ;;
- esac
- distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
- ;;
-maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
-*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
-esac
-
-# apply MVNW_REPOURL and calculate MAVEN_HOME
-# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
-[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
-distributionUrlName="${distributionUrl##*/}"
-distributionUrlNameMain="${distributionUrlName%.*}"
-distributionUrlNameMain="${distributionUrlNameMain%-bin}"
-MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
-MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
-
-exec_maven() {
- unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
- exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
-}
-
-if [ -d "$MAVEN_HOME" ]; then
- verbose "found existing MAVEN_HOME at $MAVEN_HOME"
- exec_maven "$@"
-fi
-
-case "${distributionUrl-}" in
-*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
-*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
-esac
-
-# prepare tmp dir
-if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
- clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
- trap clean HUP INT TERM EXIT
-else
- die "cannot create temp dir"
-fi
-
-mkdir -p -- "${MAVEN_HOME%/*}"
-
-# Download and Install Apache Maven
-verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
-verbose "Downloading from: $distributionUrl"
-verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
-
-# select .zip or .tar.gz
-if ! command -v unzip >/dev/null; then
- distributionUrl="${distributionUrl%.zip}.tar.gz"
- distributionUrlName="${distributionUrl##*/}"
-fi
-
-# verbose opt
-__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
-[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
-
-# normalize http auth
-case "${MVNW_PASSWORD:+has-password}" in
-'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
-has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
-esac
-
-if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
- verbose "Found wget ... using wget"
- wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
-elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
- verbose "Found curl ... using curl"
- curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
-elif set_java_home; then
- verbose "Falling back to use Java to download"
- javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
- targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
- cat >"$javaSource" <<-END
- public class Downloader extends java.net.Authenticator
- {
- protected java.net.PasswordAuthentication getPasswordAuthentication()
- {
- return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
- }
- public static void main( String[] args ) throws Exception
- {
- setDefault( new Downloader() );
- java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
- }
- }
- END
- # For Cygwin/MinGW, switch paths to Windows format before running javac and java
- verbose " - Compiling Downloader.java ..."
- "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
- verbose " - Running Downloader.java ..."
- "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
-fi
-
-# If specified, validate the SHA-256 sum of the Maven distribution zip file
-if [ -n "${distributionSha256Sum-}" ]; then
- distributionSha256Result=false
- if [ "$MVN_CMD" = mvnd.sh ]; then
- echo "Checksum validation is not supported for maven-mvnd." >&2
- echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
- exit 1
- elif command -v sha256sum >/dev/null; then
- if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
- distributionSha256Result=true
- fi
- elif command -v shasum >/dev/null; then
- if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
- distributionSha256Result=true
- fi
- else
- echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
- echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
- exit 1
- fi
- if [ $distributionSha256Result = false ]; then
- echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
- echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
- exit 1
- fi
-fi
-
-# unzip and move
-if command -v unzip >/dev/null; then
- unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
-else
- tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
-fi
-printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
-mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
-
-clean || :
-exec_maven "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
deleted file mode 100644
index 249bdf3..0000000
--- a/mvnw.cmd
+++ /dev/null
@@ -1,149 +0,0 @@
-<# : batch portion
-@REM ----------------------------------------------------------------------------
-@REM Licensed to the Apache Software Foundation (ASF) under one
-@REM or more contributor license agreements. See the NOTICE file
-@REM distributed with this work for additional information
-@REM regarding copyright ownership. The ASF licenses this file
-@REM to you under the Apache License, Version 2.0 (the
-@REM "License"); you may not use this file except in compliance
-@REM with the License. You may obtain a copy of the License at
-@REM
-@REM http://www.apache.org/licenses/LICENSE-2.0
-@REM
-@REM Unless required by applicable law or agreed to in writing,
-@REM software distributed under the License is distributed on an
-@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-@REM KIND, either express or implied. See the License for the
-@REM specific language governing permissions and limitations
-@REM under the License.
-@REM ----------------------------------------------------------------------------
-
-@REM ----------------------------------------------------------------------------
-@REM Apache Maven Wrapper startup batch script, version 3.3.2
-@REM
-@REM Optional ENV vars
-@REM MVNW_REPOURL - repo url base for downloading maven distribution
-@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
-@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
-@REM ----------------------------------------------------------------------------
-
-@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
-@SET __MVNW_CMD__=
-@SET __MVNW_ERROR__=
-@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
-@SET PSModulePath=
-@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
- IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
-)
-@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
-@SET __MVNW_PSMODULEP_SAVE=
-@SET __MVNW_ARG0_NAME__=
-@SET MVNW_USERNAME=
-@SET MVNW_PASSWORD=
-@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
-@echo Cannot start maven from wrapper >&2 && exit /b 1
-@GOTO :EOF
-: end batch / begin powershell #>
-
-$ErrorActionPreference = "Stop"
-if ($env:MVNW_VERBOSE -eq "true") {
- $VerbosePreference = "Continue"
-}
-
-# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
-$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
-if (!$distributionUrl) {
- Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
-}
-
-switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
- "maven-mvnd-*" {
- $USE_MVND = $true
- $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
- $MVN_CMD = "mvnd.cmd"
- break
- }
- default {
- $USE_MVND = $false
- $MVN_CMD = $script -replace '^mvnw','mvn'
- break
- }
-}
-
-# apply MVNW_REPOURL and calculate MAVEN_HOME
-# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
-if ($env:MVNW_REPOURL) {
- $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
- $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
-}
-$distributionUrlName = $distributionUrl -replace '^.*/',''
-$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
-$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
-if ($env:MAVEN_USER_HOME) {
- $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
-}
-$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
-$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
-
-if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
- Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
- Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
- exit $?
-}
-
-if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
- Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
-}
-
-# prepare tmp dir
-$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
-$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
-$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
-trap {
- if ($TMP_DOWNLOAD_DIR.Exists) {
- try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
- catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
- }
-}
-
-New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
-
-# Download and Install Apache Maven
-Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
-Write-Verbose "Downloading from: $distributionUrl"
-Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
-
-$webclient = New-Object System.Net.WebClient
-if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
- $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
-}
-[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
-$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
-
-# If specified, validate the SHA-256 sum of the Maven distribution zip file
-$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
-if ($distributionSha256Sum) {
- if ($USE_MVND) {
- Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
- }
- Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
- if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
- Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
- }
-}
-
-# unzip and move
-Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
-Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
-try {
- Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
-} catch {
- if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
- Write-Error "fail to move MAVEN_HOME"
- }
-} finally {
- try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
- catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
-}
-
-Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
diff --git a/pom.xml b/pom.xml
index 7c04e18..d4c5e48 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,6 @@
@@ -10,15 +10,15 @@
eu.m724
tweaks
- 0.1.15-SNAPSHOT
+ 0.1.11
21
21
UTF-8
- v1_21_R3
- 1.21.4
+ v1_21_R1
+ 1.21.1
${project.minecraft.version}-R0.1-SNAPSHOT
@@ -44,7 +44,7 @@
-
+
@@ -58,7 +58,7 @@
-
+
@@ -67,6 +67,37 @@
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.6.0
+
+ false
+ true
+
+
+ eu.m724:tweaks
+
+
+
+
+ *
+
+ META-INF/**
+
+
+
+
+
+
+ package
+
+ shade
+
+
+
+
+
net.md-5
specialsource-maven-plugin
@@ -80,8 +111,10 @@
remap-obf
org.spigotmc:minecraft-server:${project.spigot.version}:txt:maps-mojang
- org.spigotmc:spigot:${project.spigot.version}:jar:remapped-mojang
true
+ org.spigotmc:spigot:${project.spigot.version}:jar:remapped-mojang
+ true
+ remapped-obf-temp-dont-use
@@ -91,6 +124,7 @@
remap-spigot
+ ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf-temp-dont-use.jar
org.spigotmc:minecraft-server:${project.spigot.version}:csrg:maps-spigot
org.spigotmc:spigot:${project.spigot.version}:jar:remapped-obf
@@ -118,6 +152,11 @@
dmulloy2-repo
https://repo.dmulloy2.net/repository/public/
+
+
+ maxhenkel-repo
+ https://maven.maxhenkel.de/repository/public
+
m724-repo
https://git.m724.eu/api/packages/Minecon724/maven
@@ -128,7 +167,7 @@
org.spigotmc
spigot-api
- 1.21.1-R0.1-SNAPSHOT
+ ${project.spigot.version}
provided
@@ -144,10 +183,16 @@
5.3.0
provided
+
+ de.maxhenkel.voicechat
+ voicechat-api
+ 2.5.0
+ provided
+
eu.m724
mstats-spigot
- 0.1.2
+ 0.1.0
provided
@@ -168,6 +213,6 @@
scm:git:git@git.m724.eu:Minecon724/tweaks724.git
- HEAD
+ tweaks-0.1.11
\ No newline at end of file
diff --git a/src/main/java/eu/m724/tweaks/DebugLogger.java b/src/main/java/eu/m724/tweaks/DebugLogger.java
index 9bf66c6..2b91bee 100644
--- a/src/main/java/eu/m724/tweaks/DebugLogger.java
+++ b/src/main/java/eu/m724/tweaks/DebugLogger.java
@@ -6,58 +6,42 @@
package eu.m724.tweaks;
-import eu.m724.tweaks.module.TweaksModule;
-
import java.util.logging.Level;
import java.util.logging.Logger;
public class DebugLogger {
static Logger logger;
- public static void info(String message, Object... format) {
- log(Level.INFO, message, format);
+ public static void info(String message) {
+ log(Level.INFO, message);
}
- public static void warning(String message, Object... format) {
- log(Level.WARNING, message, format);
+ public static void warning(String message) {
+ log(Level.WARNING, message);
}
- public static void severe(String message, Object... format) {
- log(Level.SEVERE, message, format);
+ public static void severe(String message) {
+ log(Level.SEVERE, message);
}
- public static void fine(String message, Object... format) {
- log(Level.FINE, message, format);
+ public static void fine(String message) {
+ log(Level.FINE, message);
}
- public static void finer(String message, Object... format) {
- log(Level.FINER, message, format);
- }
-
- private static void log(Level level, String message, Object... format) {
+ private static void log(Level level, String message) {
if (logger.getLevel().intValue() > level.intValue()) return;
var caller = Thread.currentThread().getStackTrace()[3].getClassName();
- if (caller.equals(TweaksModule.class.getName())) {
- var pcaller = Thread.currentThread().getStackTrace()[4].getClassName();
- if (pcaller.endsWith("Module"))
- caller = pcaller;
- }
-
if (caller.startsWith("eu.m724.tweaks."))
caller = caller.substring(15);
- message = "[" + caller + "] " + message.formatted(format);
+ message = "[" + caller + "] " + message;
if (level.intValue() < Level.INFO.intValue()) { // levels below info are never logged even if set for some reason
- // colors text gray (cyan is close to gray)
- if (level == Level.FINE) {
- message = "\033[38;5;250m" + message + "\033[39m";
- } else {
- message = "\033[38;5;245m" + message + "\033[39m";
- }
level = Level.INFO;
+ // colors text gray (cyan is close to gray)
+ message = "\033[36m" + message + "\033[39m";
}
logger.log(level, message);
diff --git a/src/main/java/eu/m724/tweaks/TweaksConfig.java b/src/main/java/eu/m724/tweaks/TweaksConfig.java
new file mode 100644
index 0000000..9c54a02
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/TweaksConfig.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2025 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.plugin.Plugin;
+
+import java.util.Map;
+
+public record TweaksConfig(
+ boolean metrics,
+ boolean debug,
+ String locale,
+
+ boolean worldborderExpand,
+ boolean worldborderHide,
+
+ boolean brandEnabled,
+ String brandText,
+ boolean brandShowPing,
+ boolean brandShowMspt,
+
+ boolean doorDoubleOpen,
+ boolean doorKnocking,
+
+ boolean motdEnabled,
+ String motdSet,
+
+ boolean chatEnabled,
+ boolean chatLocalEvents,
+ String chatDefaultName,
+ int chatRadius,
+
+ boolean compassEnabled,
+ int compassWidth,
+ int compassPrecision,
+
+ boolean pomodoroEnabled,
+ boolean pomodoroForce,
+
+ boolean updaterEnabled,
+
+ boolean hardcoreEnabled,
+ float hardcoreChance,
+
+ boolean sleepEnabled,
+ boolean sleepInstant,
+
+ boolean authEnabled,
+ boolean authForce,
+ String authDomain,
+
+ boolean redstoneEnabled,
+ String redstoneListen,
+
+ Map knockbackModifiers,
+
+ boolean killswitchEnabled,
+ String killswitchListen
+) {
+ public static final int CONFIG_VERSION = 2;
+ private static TweaksConfig config;
+
+ public static TweaksConfig getConfig() {
+ return config;
+ }
+
+ public static TweaksConfig load(Plugin plugin) {
+ plugin.saveDefaultConfig();
+ FileConfiguration config = plugin.getConfig();
+
+ int configVersion = config.getInt("magic number don't modify this", 0);
+ RuntimeException exception = new RuntimeException("Config version is %d, expected %d".formatted(configVersion, CONFIG_VERSION));
+
+ if (configVersion == 0) {
+ throw exception;
+ } else if (configVersion < CONFIG_VERSION) {
+ throw new RuntimeException("Please follow update instructions https://www.spigotmc.org/resources/tweaks724.121057/updates", exception);
+ } else if (configVersion > CONFIG_VERSION) {
+ throw new RuntimeException("Did you downgrade the plugin? Remove config.yml and let the plugin re-create it", exception);
+ }
+
+ boolean metrics = config.getBoolean("metrics");
+ boolean debug = config.getBoolean("debug", false);
+ String locale = config.getString("locale", "US");
+
+ boolean worldborderExpand = config.getBoolean("worldborder.expand");
+ boolean worldborderHide = config.getBoolean("worldborder.hide");
+
+ boolean brandEnabled = config.getBoolean("brand.enabled");
+ String brandText = config.getString("brand.text");
+ boolean brandShowPing = config.getBoolean("brand.showPing");
+ boolean brandShowMspt = config.getBoolean("brand.showMspt");
+
+ boolean doorDoubleOpen = config.getBoolean("doors.doubleOpen");
+ boolean doorKnocking = config.getBoolean("doors.knocking");
+
+ String motdSet = config.getString("motd.set");
+ boolean motdEnabled = !(motdSet.equals("false") || motdSet.isBlank());
+
+ boolean chatEnabled = config.getBoolean("chat.enabled");
+ boolean chatLocalEvents = config.getBoolean("chat.localEvents");
+ String chatDefaultName = config.getString("chat.defaultName");
+ int chatRadius = config.getInt("chat.radius");
+
+ boolean compassEnabled = config.getBoolean("compass.enabled");
+ int compassWidth = config.getInt("compass.width");
+ int compassPrecision = config.getInt("compass.precision");
+
+ boolean pomodoroEnabled = config.getBoolean("pomodoro.enabled");
+ boolean pomodoroForce = config.getBoolean("pomodoro.force");
+
+ boolean updaterEnabled = config.getBoolean("updater.enabled");
+
+ boolean hardcoreEnabled = config.getBoolean("hardcore.enabled");
+ float hardcoreChance = (float) config.getDouble("hardcore.chance");
+
+ boolean sleepEnabled = config.getBoolean("sleep.enabled");
+ boolean sleepInstant = config.getBoolean("sleep.instant");
+
+ boolean authEnabled = config.getBoolean("auth.enabled");
+ boolean authForce = config.getBoolean("auth.force");
+ String authHostname = config.getString("auth.domain");
+
+ boolean redstoneEnabled = config.getBoolean("retstone.enabled");
+ String redstoneListen = config.getString("retstone.listen");
+
+ // this is processed when initing
+ Map knockbackModifiers = config.getConfigurationSection("knockback").getValues(false);
+
+ boolean killswitchEnabled = config.getBoolean("killswitch.enabled");
+ String killswitchListen = config.getString("killswitch.listen");
+
+ TweaksConfig.config = new TweaksConfig(
+ debug, metrics, locale,
+ worldborderExpand, worldborderHide,
+ brandEnabled, brandText, brandShowPing, brandShowMspt,
+ doorDoubleOpen, doorKnocking,
+ motdEnabled, motdSet,
+ chatEnabled, chatLocalEvents, chatDefaultName, chatRadius,
+ compassEnabled, compassWidth, compassPrecision,
+ pomodoroEnabled, pomodoroForce,
+ updaterEnabled,
+ hardcoreEnabled, hardcoreChance,
+ sleepEnabled, sleepInstant,
+ authEnabled, authForce, authHostname,
+ redstoneEnabled, redstoneListen,
+ knockbackModifiers,
+ killswitchEnabled, killswitchListen
+ );
+
+ return TweaksConfig.config;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/eu/m724/tweaks/TweaksPlugin.java b/src/main/java/eu/m724/tweaks/TweaksPlugin.java
index 82adee7..575b935 100644
--- a/src/main/java/eu/m724/tweaks/TweaksPlugin.java
+++ b/src/main/java/eu/m724/tweaks/TweaksPlugin.java
@@ -7,40 +7,32 @@
package eu.m724.tweaks;
import eu.m724.mstats.MStatsPlugin;
-import eu.m724.tweaks.config.TweaksConfig;
-import eu.m724.tweaks.module.TweaksModule;
-import eu.m724.tweaks.module.alert.AlertModule;
-import eu.m724.tweaks.module.auth.AuthModule;
-import eu.m724.tweaks.module.chat.ChatModule;
-import eu.m724.tweaks.module.door.DoorKnockModule;
-import eu.m724.tweaks.module.door.DoorOpenModule;
-import eu.m724.tweaks.module.durability.DurabilityModule;
-import eu.m724.tweaks.module.full.FullModule;
-import eu.m724.tweaks.module.hardcore.HardcoreModule;
-import eu.m724.tweaks.module.killswitch.KillswitchModule;
-import eu.m724.tweaks.module.knockback.KnockbackModule;
-import eu.m724.tweaks.module.motd.MotdModule;
-import eu.m724.tweaks.module.ping.F3NameListener;
-import eu.m724.tweaks.module.ping.PingChecker;
-import eu.m724.tweaks.module.pomodoro.PomodoroModule;
-import eu.m724.tweaks.module.redstone.RedstoneModule;
-import eu.m724.tweaks.module.sleep.SleepModule;
-import eu.m724.tweaks.module.swing.SwingModule;
-import eu.m724.tweaks.module.updater.UpdaterModule;
-import eu.m724.tweaks.module.wordcoords.WordCoordsModule;
-import eu.m724.tweaks.module.worldborder.WorldBorderExpandModule;
-import eu.m724.tweaks.module.worldborder.WorldBorderHideModule;
+import eu.m724.tweaks.alert.AlertManager;
+import eu.m724.tweaks.auth.AuthManager;
+import eu.m724.tweaks.chat.ChatManager;
+import eu.m724.tweaks.door.DoorKnockListener;
+import eu.m724.tweaks.door.DoorOpenListener;
+import eu.m724.tweaks.full.FullListener;
+import eu.m724.tweaks.hardcore.HardcoreManager;
+import eu.m724.tweaks.killswitch.KillswitchManager;
+import eu.m724.tweaks.knockback.KnockbackListener;
+import eu.m724.tweaks.motd.MotdManager;
+import eu.m724.tweaks.ping.F3NameListener;
+import eu.m724.tweaks.ping.PingChecker;
+import eu.m724.tweaks.pomodoro.PomodoroManager;
+import eu.m724.tweaks.redstone.RedstoneManager;
+import eu.m724.tweaks.sleep.SleepManager;
+import eu.m724.tweaks.updater.UpdaterManager;
+import eu.m724.tweaks.worldborder.WorldBorderExpander;
+import eu.m724.tweaks.worldborder.WorldBorderHider;
import java.util.Locale;
import java.util.logging.Level;
public class TweaksPlugin extends MStatsPlugin {
- private static TweaksPlugin INSTANCE;
-
@Override
public void onEnable() {
long start = System.nanoTime();
- INSTANCE = this;
if (getServer().getPluginManager().getPlugin("ProtocolLib") == null) {
getLogger().severe("ProtocolLib is required for this plugin.");
@@ -49,61 +41,41 @@ public class TweaksPlugin extends MStatsPlugin {
return;
}
- TweaksConfig config;
- try {
- config = TweaksConfig.load(this);
- } catch (Exception e) {
- throw new RuntimeException("Exception loading config", e);
- }
+ TweaksConfig config = TweaksConfig.load(this);
getLogger().setLevel(config.debug() ? Level.FINEST : Level.INFO);
DebugLogger.logger = getLogger();
+ DebugLogger.fine("Debug enabled. There may be performance issues.");
- if (config.debug()) {
- DebugLogger.warning("Debug harms performance");
- }
-
- DebugLogger.fine("Language");
+ DebugLogger.fine("Enabling Language");
new Language(Locale.of(config.locale())); // TODO
DebugLogger.fine(Language.getString("languageNotice", Language.getString("language"), Language.getString("languageEnglish")));
- var runningVersion = getServer().getBukkitVersion();
- var targetVersion = getTargetVersion();
-
- if (!runningVersion.equals(targetVersion)) {
- // the incompatibility can be between 1.21.4-R0.1-SNAPSHOT and 1.21.4-R1-SNAPSHOT
- var runningMc = runningVersion.split("-")[0];
- var targetMc = targetVersion.split("-")[0];
- if (!runningMc.equals(targetMc)) {
- targetVersion = targetMc;
- runningVersion = runningMc;
- }
-
- getLogger().warning("This plugin was built for %s. This server is running %s.".formatted(targetVersion, runningVersion));
- getLogger().warning("Some modules will not work. Disable those modules, or make a compatible build yourself:");
- getLogger().warning("https://git.m724.eu/Minecon724/tweaks724/src/branch/master/docs/BUILDING.md");
- }
-
/* start modules */
if (config.worldborderHide()) {
- TweaksModule.init(WorldBorderHideModule.class);
+ DebugLogger.fine("Enabling Worldborder hide");
+ new WorldBorderHider().init(this);
}
if (config.worldborderExpand()) {
- TweaksModule.init(WorldBorderExpandModule.class);
+ DebugLogger.fine("Enabling Worldborder expand");
+ new WorldBorderExpander().init(this);
}
if (config.chatEnabled()) {
- TweaksModule.init(ChatModule.class);
+ DebugLogger.fine("Enabling Chat");
+ new ChatManager(this).init(getCommand("chat"), getCommand("chatmanage"));
}
if (config.doorKnocking()) {
- TweaksModule.init(DoorKnockModule.class);
+ DebugLogger.fine("Enabling Door knock");
+ getServer().getPluginManager().registerEvents(new DoorKnockListener(), this);
}
if (config.doorDoubleOpen()) {
- TweaksModule.init(DoorOpenModule.class);
+ DebugLogger.fine("Enabling Door double open");
+ getServer().getPluginManager().registerEvents(new DoorOpenListener(), this);
}
if (config.brandEnabled()) {
@@ -115,51 +87,54 @@ public class TweaksPlugin extends MStatsPlugin {
new PingChecker(this).init(getCommand("ping"));
if (config.motdEnabled()) {
- TweaksModule.init(MotdModule.class);
+ DebugLogger.fine("Enabling MOTD");
+ new MotdManager(this).init();
}
if (config.pomodoroEnabled()) {
- TweaksModule.init(PomodoroModule.class);
+ DebugLogger.fine("Enabling Pomodoro");
+ new PomodoroManager(this).init(getCommand("pomodoro"));
}
if (config.updaterEnabled()) {
- TweaksModule.init(UpdaterModule.class);
+ DebugLogger.fine("Enabling Updater");
+ new UpdaterManager(this).init(getCommand("updates"));
}
if (config.hardcoreEnabled()) {
- TweaksModule.init(HardcoreModule.class);
+ DebugLogger.fine("Enabling Hardcore");
+ new HardcoreManager().init(this);
}
if (config.sleepEnabled()) {
- TweaksModule.init(SleepModule.class);
+ DebugLogger.fine("Enabling Sleep");
+ new SleepManager().init(this);
}
if (config.authEnabled()) {
- TweaksModule.init(AuthModule.class);
+ DebugLogger.fine("Enabling Auth");
+ new AuthManager(this).init(getCommand("tauth"));
}
- TweaksModule.init(AlertModule.class);
+ DebugLogger.fine("Enabling Alert");
+ new AlertManager(this).init(getCommand("emergencyalert"));
- TweaksModule.init(FullModule.class);
+ DebugLogger.fine("Enabling Full");
+ getServer().getPluginManager().registerEvents(new FullListener(), this);
if (config.redstoneEnabled()) {
- TweaksModule.init(RedstoneModule.class);
+ DebugLogger.fine("Enabling Redstone");
+ new RedstoneManager(this).init(getCommand("retstone"));
}
- TweaksModule.init(KnockbackModule.class);
+ DebugLogger.fine("Enabling Knockback");
+ new KnockbackListener(this);
if (config.killswitchEnabled()) {
- TweaksModule.init(KillswitchModule.class);
+ DebugLogger.fine("Enabling Killswitch");
+ new KillswitchManager(this).init(getCommand("servkill"));
}
- if (config.swingEnabled()) {
- TweaksModule.init(SwingModule.class);
- }
-
- TweaksModule.init(DurabilityModule.class);
-
- TweaksModule.init(WordCoordsModule.class);
-
/* end modules */
if (config.metrics()) {
@@ -167,23 +142,10 @@ public class TweaksPlugin extends MStatsPlugin {
mStats(1);
}
- DebugLogger.fine("Took %.3f milliseconds", (System.nanoTime() - start) / 1000000.0);
- }
-
- private String getTargetVersion() {
- var permission = getServer().getPluginManager().getPermission("7weaks724.ignore.this");
-
- var desc = permission.getDescription().substring("Internal, not for use. ".length()).split(",");
- var version = desc[0];
-
- return version;
+ DebugLogger.fine("Took %.3f milliseconds".formatted((System.nanoTime() - start) / 1000000.0));
}
public boolean hasResource(String resource) {
return this.getClassLoader().getResource(resource) != null;
}
-
- public static TweaksPlugin getInstance() {
- return INSTANCE;
- }
}
diff --git a/src/main/java/eu/m724/tweaks/module/alert/Alert.java b/src/main/java/eu/m724/tweaks/alert/Alert.java
similarity index 95%
rename from src/main/java/eu/m724/tweaks/module/alert/Alert.java
rename to src/main/java/eu/m724/tweaks/alert/Alert.java
index 2c802b6..be73459 100644
--- a/src/main/java/eu/m724/tweaks/module/alert/Alert.java
+++ b/src/main/java/eu/m724/tweaks/alert/Alert.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.alert;
+package eu.m724.tweaks.alert;
import org.bukkit.Bukkit;
import org.bukkit.Material;
diff --git a/src/main/java/eu/m724/tweaks/module/alert/AlertCommand.java b/src/main/java/eu/m724/tweaks/alert/AlertCommand.java
similarity index 94%
rename from src/main/java/eu/m724/tweaks/module/alert/AlertCommand.java
rename to src/main/java/eu/m724/tweaks/alert/AlertCommand.java
index 2a17c77..e5748a7 100644
--- a/src/main/java/eu/m724/tweaks/module/alert/AlertCommand.java
+++ b/src/main/java/eu/m724/tweaks/alert/AlertCommand.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.alert;
+package eu.m724.tweaks.alert;
import org.bukkit.Material;
import org.bukkit.command.Command;
@@ -20,9 +20,9 @@ public class AlertCommand implements CommandExecutor {
private List pending;
private long when;
- private final AlertModule manager;
+ private final AlertManager manager;
- public AlertCommand(AlertModule manager) {
+ public AlertCommand(AlertManager manager) {
this.manager = manager;
}
@@ -51,7 +51,7 @@ public class AlertCommand implements CommandExecutor {
} else if (args[0].equalsIgnoreCase("confirm")) {
sender.sendMessage("CONFIRM must be in all caps");
} else if (args[0].equalsIgnoreCase("cancel")) {
- if (AlertModule.current != null) {
+ if (AlertManager.current != null) {
manager.stop();
sender.sendMessage("Cancelled alert");
} else if (pending != null) {
@@ -86,7 +86,7 @@ public class AlertCommand implements CommandExecutor {
if (pending != null) {
when = System.currentTimeMillis();
- if (AlertModule.current != null) {
+ if (AlertManager.current != null) {
sender.sendMessage("Broadcasting a new alert will cancel the currently active one");
}
sender.sendMessage("Please confirm broadcast with /emergencyalert CONFIRM within 15 seconds");
diff --git a/src/main/java/eu/m724/tweaks/alert/AlertManager.java b/src/main/java/eu/m724/tweaks/alert/AlertManager.java
new file mode 100644
index 0000000..f2b72d9
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/alert/AlertManager.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.alert;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.ProtocolLibrary;
+import com.comphenix.protocol.events.ListenerPriority;
+import com.comphenix.protocol.events.PacketAdapter;
+import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.events.PacketEvent;
+import eu.m724.tweaks.TweaksPlugin;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class AlertManager {
+ private final TweaksPlugin plugin;
+
+ private BukkitTask notifyTask;
+ static Alert current;
+ static Map pages = new HashMap<>();
+
+ public AlertManager(TweaksPlugin plugin) {
+ this.plugin = plugin;
+ }
+
+ public void init(PluginCommand command) {
+ command.setExecutor(new AlertCommand(this));
+
+ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
+ plugin,
+ ListenerPriority.NORMAL,
+ PacketType.Play.Client.ENCHANT_ITEM
+ ) {
+ @Override
+ public void onPacketReceiving(PacketEvent event) {
+ if (current == null) return;
+ if (!current.isOpen(event.getPlayer())) return;
+
+ PacketContainer packet = event.getPacket();
+
+ int windowId, buttonId;
+ windowId = packet.getIntegers().read(0);
+ buttonId = packet.getIntegers().read(1);
+
+ var page = pages.getOrDefault(event.getPlayer(),1);
+
+ if (buttonId == 1) { // prev page
+ page--;
+ } else if (buttonId == 2) { // nextc page
+ page++;
+ } else {
+ return;
+ }
+
+ pages.put(event.getPlayer(), page);
+ var npacket = new PacketContainer(PacketType.Play.Server.WINDOW_DATA);
+ npacket.getIntegers().write(0, windowId);
+ npacket.getIntegers().write(1, 0);
+ npacket.getIntegers().write(2, page);
+ ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), npacket);
+ }
+ });
+ }
+
+ public Alert start(String... content) {
+ stop();
+ current = new Alert(content);
+ notifyTask = new AlertRunnable(current, v -> this.stop()).runTaskTimer(plugin, 0, 10);
+ return current;
+ }
+
+ public void stop() {
+ if (current == null) return;
+ for (Player player : plugin.getServer().getOnlinePlayers()) {
+ if (current.isOpen(player))
+ player.closeInventory();
+ }
+ pages.clear();
+ notifyTask.cancel();
+ current = null;
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/alert/AlertRunnable.java b/src/main/java/eu/m724/tweaks/alert/AlertRunnable.java
similarity index 96%
rename from src/main/java/eu/m724/tweaks/module/alert/AlertRunnable.java
rename to src/main/java/eu/m724/tweaks/alert/AlertRunnable.java
index 9ce8989..d2c3400 100644
--- a/src/main/java/eu/m724/tweaks/module/alert/AlertRunnable.java
+++ b/src/main/java/eu/m724/tweaks/alert/AlertRunnable.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.alert;
+package eu.m724.tweaks.alert;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ChatMessageType;
diff --git a/src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java b/src/main/java/eu/m724/tweaks/auth/AuthCommands.java
similarity index 96%
rename from src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java
rename to src/main/java/eu/m724/tweaks/auth/AuthCommands.java
index 5aae83f..d33767c 100644
--- a/src/main/java/eu/m724/tweaks/module/auth/AuthCommands.java
+++ b/src/main/java/eu/m724/tweaks/auth/AuthCommands.java
@@ -1,13 +1,13 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.auth;
+package eu.m724.tweaks.auth;
import eu.m724.tweaks.Language;
-import eu.m724.tweaks.config.TweaksConfig;
+import eu.m724.tweaks.TweaksConfig;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
diff --git a/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java b/src/main/java/eu/m724/tweaks/auth/AuthListener.java
similarity index 79%
rename from src/main/java/eu/m724/tweaks/module/auth/AuthListener.java
rename to src/main/java/eu/m724/tweaks/auth/AuthListener.java
index b22b677..1ed2a4f 100644
--- a/src/main/java/eu/m724/tweaks/module/auth/AuthListener.java
+++ b/src/main/java/eu/m724/tweaks/auth/AuthListener.java
@@ -1,21 +1,19 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.auth;
+package eu.m724.tweaks.auth;
-import eu.m724.tweaks.DebugLogger;
import eu.m724.tweaks.Language;
-import eu.m724.tweaks.config.TweaksConfig;
+import eu.m724.tweaks.TweaksConfig;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import java.io.FileNotFoundException;
-import java.io.IOException;
public class AuthListener implements Listener {
private final AuthStorage authStorage;
@@ -42,10 +40,6 @@ public class AuthListener implements Listener {
allowed = true; // key just assigned
} catch (FileNotFoundException | AuthStorage.AlreadyClaimedException | AuthStorage.InvalidKeyException e) {
allowed = !force; // If forced all players must have a key
- } catch (IOException e) {
- DebugLogger.severe("Error assigning key to player. " + e.getMessage());
- event.disallow(PlayerLoginEvent.Result.KICK_OTHER, Language.getString("authKickError"));
- allowed = true; // to skip the below checks
}
}
diff --git a/src/main/java/eu/m724/tweaks/auth/AuthManager.java b/src/main/java/eu/m724/tweaks/auth/AuthManager.java
new file mode 100644
index 0000000..402b376
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/auth/AuthManager.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.auth;
+
+import org.bukkit.command.PluginCommand;
+import org.bukkit.plugin.Plugin;
+
+public class AuthManager {
+ private final AuthStorage authStorage;
+ private final Plugin plugin;
+
+ public AuthManager(Plugin plugin) {
+ this.plugin = plugin;
+ this.authStorage = new AuthStorage(plugin);
+ }
+
+ public void init(PluginCommand command) {
+ plugin.getServer().getPluginManager().registerEvents(new AuthListener(authStorage), plugin);
+ command.setExecutor(new AuthCommands(authStorage));
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java b/src/main/java/eu/m724/tweaks/auth/AuthStorage.java
similarity index 82%
rename from src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java
rename to src/main/java/eu/m724/tweaks/auth/AuthStorage.java
index 6692723..85fceed 100644
--- a/src/main/java/eu/m724/tweaks/module/auth/AuthStorage.java
+++ b/src/main/java/eu/m724/tweaks/auth/AuthStorage.java
@@ -1,25 +1,20 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.auth;
+package eu.m724.tweaks.auth;
import org.bukkit.plugin.Plugin;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
-import java.security.SecureRandom;
import java.util.Random;
import java.util.UUID;
public class AuthStorage {
- private static final char[] KEY_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
- private static final int KEY_LENGTH = 10;
- private static final SecureRandom RANDOM = new SecureRandom();
-
private final File playersDirectory;
private final File keysDirectory;
@@ -76,7 +71,7 @@ public class AuthStorage {
byte[] bytes = is.readNBytes(50);
return new String(bytes, StandardCharsets.UTF_8);
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new RuntimeException(e); // TODO
}
}
@@ -126,7 +121,7 @@ public class AuthStorage {
* @throws FileNotFoundException if no such key
* @throws AlreadyClaimedException if key is claimed or user owns another key
*/
- void assignOwner(String key, UUID uuid) throws IOException, FileNotFoundException, AlreadyClaimedException {
+ void assignOwner(String key, UUID uuid) throws FileNotFoundException, AlreadyClaimedException {
if (isInvalid(key)) throw new InvalidKeyException();
if (getUserOfKey(key) != null) throw new AlreadyClaimedException();
@@ -141,25 +136,34 @@ public class AuthStorage {
try (FileOutputStream os = new FileOutputStream(file)) {
os.write(byteBuffer.array());
+ } catch (IOException e) {
+ throw new RuntimeException(e); // TODO
}
File file2 = new File(playersDirectory, uuid.toString());
try (FileOutputStream os = new FileOutputStream(file2)) {
os.write(key.getBytes(StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ throw new RuntimeException(e); // TODO
}
}
+ // TODO improve
String generateKey() {
- StringBuilder builder = new StringBuilder();
+ char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
+ Random random = new Random();
+ int length = random.nextInt(8, 10);
- for (int i=0; i 1) {
+ password = Arrays.stream(args).skip(1).collect(Collectors.joining(" "));
+ }
+
+ boolean authenticated = false;
+ BaseComponent component = null;
+ ChatRoom newRoom = manager.getById(id);
+ if (newRoom != null) {
+ if (newRoom.password != null) {
+ if (newRoom.password.equals(password)) {
+ authenticated = true;
+ } else if (password == null) {
+ component = Language.getComponent("chatPasswordProtected", ChatColor.RED);
+ } else {
+ component = Language.getComponent("chatWrongPassword", ChatColor.RED);
+ }
+ } else {
+ authenticated = true;
+ }
+ } else {
+ component = Language.getComponent("chatNoSuchRoom", ChatColor.RED, id);
+ }
+
+ if (authenticated) {
+ /*component = new ComponentBuilder(Language.getComponent("chatJoined", ChatColor.GOLD))
+ .append(" ")
+ .append(ChatFormatUtils.formatChatRoom(chatRoom)).color(newRoom.color)
+ .build();*/
+ player.sendMessage("");
+ manager.setPlayerChatRoom(newRoom, player);
+ } else {
+ player.spigot().sendMessage(component);
+ }
+
+ }
+ } else if (command.getName().equals("chatmanage")) {
+ Player player = (Player) sender;
+ ChatRoom chatRoom = manager.getPlayerChatRoom(player);
+ boolean isOwner = player.equals(chatRoom.owner);
+
+ if (args.length > 1) {
+ String action = args[0];
+ String argument = args[1];
+
+ switch (action) {
+ case "create" -> {
+ try {
+ ChatRoom newRoom = manager.createChatRoom(argument, null, player);
+ sender.sendMessage("Created a chat room. Join it: /c " + newRoom.id);
+ sender.sendMessage("You might also want to protect it with a password: /cm setpassword");
+ } catch (ChatManager.InvalidIdException e) {
+ sender.sendMessage("ID is invalid: " + e.getMessage());
+ } catch (ChatManager.ChatRoomExistsException e) {
+ sender.sendMessage("Room %s already exists".formatted(argument));
+ } catch (IOException e) {
+ sender.sendMessage("Failed to create room");
+ e.printStackTrace();
+ }
+ }
+ case "delete" -> {
+ if (argument.equals(chatRoom.id)) {
+ if (isOwner) {
+ manager.deleteChatRoom(chatRoom);
+ sender.sendMessage("Room %s deleted".formatted(chatRoom.id));
+ } else {
+ sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id));
+ }
+ } else {
+ sender.sendMessage("Pass %s as an argument to confirm".formatted(chatRoom.id));
+ }
+ }
+ case "setowner" -> {
+ if (isOwner) {
+ Player newOwner = Bukkit.getPlayer(argument);
+ if (newOwner != null && newOwner.isOnline()) {
+ chatRoom.owner = newOwner;
+ try {
+ manager.saveChatRoom(chatRoom);
+ sender.sendMessage("Owner changed to " + newOwner.getName());
+ } catch (IOException e) {
+ sender.sendMessage("Failed to change owner");
+ e.printStackTrace();
+ }
+ } else {
+ sender.sendMessage("Player must be online");
+ }
+ } else {
+ sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id));
+ }
+ }
+ case "setpassword" -> {
+ if (isOwner) {
+ chatRoom.password = Arrays.stream(args).skip(1).collect(Collectors.joining(" "));
+ try {
+ manager.saveChatRoom(chatRoom);
+ sender.sendMessage("Password changed");
+ } catch (IOException e) {
+ sender.sendMessage("Failed to change password");
+ e.printStackTrace();
+ }
+ } else {
+ sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id));
+ }
+ }
+ case "setcolor" -> {
+ if (isOwner) {
+ ChatColor newColor = ChatColor.of(argument);
+ if (newColor != null) {
+ chatRoom.color = newColor;
+ try {
+ manager.saveChatRoom(chatRoom);
+ sender.sendMessage("Message color changed to " + newColor.getName());
+ } catch (IOException e) {
+ sender.sendMessage("Failed to change color");
+ e.printStackTrace();
+ }
+ } else {
+ sender.sendMessage("Invalid color");
+ }
+ } else {
+ sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id));
+ }
+ }
+ default -> {
+ sender.sendMessage("Actions: create, delete, setowner, setpassword, setcolor");
+ }
+ }
+ } else if (args.length > 0) {
+ switch (args[0]) {
+ case "create" ->
+ sender.sendMessage("Please pass a room name as an argument. The room name must be of characters and digits.");
+ case "delete" ->
+ sender.sendMessage("You want to delete room %s. Confirm by passing its name as an argument for this action.".formatted(chatRoom.id));
+ case "setowner" ->
+ sender.sendMessage("To transfer ownership of room %s, pass the new owner name as an argument for this action.".formatted(chatRoom.id));
+ case "setpassword" ->
+ sender.sendMessage("To change the password of room %s, pass the new password as an argument for this action.".formatted(chatRoom.id));
+ case "setcolor" ->
+ sender.sendMessage("To change the message color of room %s, pass the new color as an argument for this action. #hex or color name.".formatted(chatRoom.id));
+ default ->
+ sender.sendMessage("Actions: create, delete, setowner, setpassword, setcolor");
+ }
+ } else {
+ sender.sendMessage("Actions: create, delete, setowner, setpassword, setcolor");
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatFormatUtils.java b/src/main/java/eu/m724/tweaks/chat/ChatFormatUtils.java
similarity index 96%
rename from src/main/java/eu/m724/tweaks/module/chat/ChatFormatUtils.java
rename to src/main/java/eu/m724/tweaks/chat/ChatFormatUtils.java
index 016beeb..b152f9e 100644
--- a/src/main/java/eu/m724/tweaks/module/chat/ChatFormatUtils.java
+++ b/src/main/java/eu/m724/tweaks/chat/ChatFormatUtils.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.chat;
+package eu.m724.tweaks.chat;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatListener.java b/src/main/java/eu/m724/tweaks/chat/ChatListener.java
similarity index 88%
rename from src/main/java/eu/m724/tweaks/module/chat/ChatListener.java
rename to src/main/java/eu/m724/tweaks/chat/ChatListener.java
index 21b65f9..f114e58 100644
--- a/src/main/java/eu/m724/tweaks/module/chat/ChatListener.java
+++ b/src/main/java/eu/m724/tweaks/chat/ChatListener.java
@@ -1,12 +1,12 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.chat;
+package eu.m724.tweaks.chat;
-import eu.m724.tweaks.config.TweaksConfig;
+import eu.m724.tweaks.TweaksConfig;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
@@ -14,8 +14,8 @@ import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.TranslatableComponent;
import net.md_5.bungee.chat.ComponentSerializer;
import net.minecraft.network.chat.Component;
-import org.bukkit.craftbukkit.v1_21_R3.CraftRegistry;
-import org.bukkit.craftbukkit.v1_21_R3.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R1.CraftRegistry;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -25,14 +25,13 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class ChatListener implements Listener {
- private final ChatModule chatModule;
+ private final ChatManager chatManager;
private final String defaultRoom = TweaksConfig.getConfig().chatDefaultName();
private final boolean localEvents = TweaksConfig.getConfig().chatLocalEvents();
private final int radius;
- public ChatListener(ChatModule chatModule) {
- this.chatModule = chatModule;
-
+ public ChatListener(ChatManager chatManager) {
+ this.chatManager = chatManager;
if (TweaksConfig.getConfig().chatRadius() < 0) {
radius = 0;
} else {
@@ -53,7 +52,7 @@ public class ChatListener implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
- ChatRoom chatRoom = chatModule.getPlayerChatRoom(player);
+ ChatRoom chatRoom = chatManager.getPlayerChatRoom(player);
if (localEvents) {
var cb = new ComponentBuilder()
@@ -78,7 +77,7 @@ public class ChatListener implements Listener {
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
- ChatRoom chatRoom = chatModule.removePlayer(player);
+ ChatRoom chatRoom = chatManager.removePlayer(player);
if (localEvents) {
var cb = new ComponentBuilder()
@@ -104,7 +103,7 @@ public class ChatListener implements Listener {
public void onPlayerDeath(PlayerDeathEvent event) {
if (localEvents) {
Player player = event.getEntity();
- ChatRoom chatRoom = chatModule.getPlayerChatRoom(player);
+ ChatRoom chatRoom = chatManager.getPlayerChatRoom(player);
// would be easier on Paper but this is not Paper
BaseComponent deathMessage = ComponentSerializer.deserialize(Component.Serializer.toJson(((CraftPlayer)player).getHandle().getCombatTracker().getDeathMessage(), CraftRegistry.getMinecraftRegistry()));
@@ -125,7 +124,7 @@ public class ChatListener implements Listener {
// broadcast to killer if available
if (player.getLastDamageCause().getDamageSource().getCausingEntity() instanceof Player killer) {
- ChatRoom chatRoom2 = chatModule.getPlayerChatRoom(killer);
+ ChatRoom chatRoom2 = chatManager.getPlayerChatRoom(killer);
if (chatRoom != chatRoom2) {
if (proximityFor(chatRoom)) {
chatRoom2.broadcastNear(killer.getLocation(), radius, component);
@@ -143,7 +142,7 @@ public class ChatListener implements Listener {
@EventHandler
public void onAsyncPlayerChat(AsyncPlayerChatEvent event) {
Player player = event.getPlayer();
- ChatRoom chatRoom = chatModule.getPlayerChatRoom(player);
+ ChatRoom chatRoom = chatManager.getPlayerChatRoom(player);
String message = event.getMessage();
var component = new ComponentBuilder()
diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java b/src/main/java/eu/m724/tweaks/chat/ChatManager.java
similarity index 82%
rename from src/main/java/eu/m724/tweaks/module/chat/ChatModule.java
rename to src/main/java/eu/m724/tweaks/chat/ChatManager.java
index ad8ae65..04d1a84 100644
--- a/src/main/java/eu/m724/tweaks/module/chat/ChatModule.java
+++ b/src/main/java/eu/m724/tweaks/chat/ChatManager.java
@@ -1,45 +1,50 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.chat;
+package eu.m724.tweaks.chat;
-import eu.m724.tweaks.module.TweaksModule;
+import eu.m724.tweaks.TweaksConfig;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ComponentBuilder;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
+import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;
+import org.bukkit.plugin.Plugin;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
-public class ChatModule extends TweaksModule {
- private final NamespacedKey chatRoomKey = new NamespacedKey(getPlugin(), "chatRoom");
- private final String defaultRoom = getConfig().chatDefaultName();
+public class ChatManager {
+ private final Plugin plugin;
+ private final NamespacedKey chatRoomKey;
+ private final String defaultRoom;
private final Map playerMap = new HashMap<>();
private final Map roomIdMap = new HashMap<>();
+ public ChatManager(Plugin plugin) {
+ this.plugin = plugin;
+ this.chatRoomKey = new NamespacedKey(plugin, "chatRoom");
+ this.defaultRoom = TweaksConfig.getConfig().chatDefaultName();
+ }
- @Override
- protected void onInit() {
- if (getPlugin().getServer().isEnforcingSecureProfiles()) {
+ public void init(PluginCommand chatCommand, PluginCommand chatManageCommand) {
+ if (plugin.getServer().isEnforcingSecureProfiles()) {
throw new RuntimeException("Please disable enforce-secure-profile in server.properties to use chatrooms");
}
- ChatRoomLoader.init(getPlugin());
getById(defaultRoom);
- registerEvents(new ChatListener(this));
+ plugin.getServer().getPluginManager().registerEvents(new ChatListener(this), plugin);
var chatCommands = new ChatCommands(this);
- registerCommand("chat", chatCommands);
- registerCommand("chatmanage", chatCommands);
-
+ chatCommand.setExecutor(chatCommands);
+ chatManageCommand.setExecutor(chatCommands);
}
/**
@@ -155,11 +160,11 @@ public class ChatModule extends TweaksModule {
case 0:
break;
case 1:
- throw new InvalidIdException("ID is too short, it must be at least 2 chars long");
+ throw new InvalidIdException("ID is too short, make it at least 2 chars");
case 2:
- throw new InvalidIdException("ID is too long, it mustn't be longer than 20 chars");
+ throw new InvalidIdException("ID is too long, make it 20 chars or shorter");
case 4:
- throw new InvalidIdException("ID must be of characters a-z and numbers 0-9");
+ throw new InvalidIdException("ID must be composed from characters a-z and numbers 0-9");
}
if (getById(id) != null)
diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatRoom.java b/src/main/java/eu/m724/tweaks/chat/ChatRoom.java
similarity index 97%
rename from src/main/java/eu/m724/tweaks/module/chat/ChatRoom.java
rename to src/main/java/eu/m724/tweaks/chat/ChatRoom.java
index 3eb34fe..a659694 100644
--- a/src/main/java/eu/m724/tweaks/module/chat/ChatRoom.java
+++ b/src/main/java/eu/m724/tweaks/chat/ChatRoom.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.chat;
+package eu.m724.tweaks.chat;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java b/src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java
similarity index 94%
rename from src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java
rename to src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java
index 0af0f59..a160311 100644
--- a/src/main/java/eu/m724/tweaks/module/chat/ChatRoomLoader.java
+++ b/src/main/java/eu/m724/tweaks/chat/ChatRoomLoader.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.chat;
+package eu.m724.tweaks.chat;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
@@ -29,7 +29,7 @@ public class ChatRoomLoader {
*/
static File getFile(String id) {
if (validateId(id) != 0)
- return null;
+ throw new RuntimeException("Invalid id: " + id);
return new File(chatRoomsDir, id + ".yml");
}
@@ -66,8 +66,7 @@ public class ChatRoomLoader {
*/
static ChatRoom load(String id) {
File chatRoomFile = getFile(id);
- if (chatRoomFile == null || !chatRoomFile.exists())
- return null;
+ if (!chatRoomFile.exists()) return null;
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(chatRoomFile);
diff --git a/src/main/java/eu/m724/tweaks/module/compass/CompassModule.java b/src/main/java/eu/m724/tweaks/compass/CompassListener.java
similarity index 91%
rename from src/main/java/eu/m724/tweaks/module/compass/CompassModule.java
rename to src/main/java/eu/m724/tweaks/compass/CompassListener.java
index 5516f93..f1873cd 100644
--- a/src/main/java/eu/m724/tweaks/module/compass/CompassModule.java
+++ b/src/main/java/eu/m724/tweaks/compass/CompassListener.java
@@ -1,12 +1,12 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.compass;
+package eu.m724.tweaks.compass;
-import eu.m724.tweaks.module.TweaksModule;
+import eu.m724.tweaks.TweaksConfig;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.ComponentBuilder;
@@ -25,9 +25,9 @@ import java.util.LinkedHashMap;
import java.util.Map;
// TODO dimension check
-public class CompassModule extends TweaksModule implements Listener {
- private final int precision = getConfig().compassPrecision(); // degrees every point
- private final int width = getConfig().compassWidth(); // points left to right
+public class CompassListener implements Listener {
+ private final int precision = TweaksConfig.getConfig().compassPrecision(); // degrees every point
+ private final int width = TweaksConfig.getConfig().compassWidth(); // points left to right
private final Map points = Map.of(
0, ChatColor.DARK_GRAY + "S",
@@ -36,11 +36,6 @@ public class CompassModule extends TweaksModule implements Listener {
270, ChatColor.DARK_GRAY + "E"
);
- @Override
- protected void onInit() {
- registerEvents(this);
- }
-
@EventHandler
public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
if (event.getMainHandItem().getType() == Material.COMPASS || event.getOffHandItem().getType() == Material.COMPASS) {
diff --git a/src/main/java/eu/m724/tweaks/compass/CompassManager.java b/src/main/java/eu/m724/tweaks/compass/CompassManager.java
new file mode 100644
index 0000000..0ba9113
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/compass/CompassManager.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.compass;
+
+import org.bukkit.plugin.Plugin;
+
+public class CompassManager {
+ private final Plugin plugin;
+
+ public CompassManager(Plugin plugin) {
+ this.plugin = plugin;
+ }
+
+ public void init() {
+ plugin.getServer().getPluginManager().registerEvents(new CompassListener(), plugin);
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/compass/CompassPlayerPreferences.java b/src/main/java/eu/m724/tweaks/compass/CompassPlayerPreferences.java
similarity index 89%
rename from src/main/java/eu/m724/tweaks/module/compass/CompassPlayerPreferences.java
rename to src/main/java/eu/m724/tweaks/compass/CompassPlayerPreferences.java
index 9e2fec2..f4d3b19 100644
--- a/src/main/java/eu/m724/tweaks/module/compass/CompassPlayerPreferences.java
+++ b/src/main/java/eu/m724/tweaks/compass/CompassPlayerPreferences.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.compass;
+package eu.m724.tweaks.compass;
import org.bukkit.entity.Player;
diff --git a/src/main/java/eu/m724/tweaks/config/ConfigLoader.java b/src/main/java/eu/m724/tweaks/config/ConfigLoader.java
deleted file mode 100644
index cf725f9..0000000
--- a/src/main/java/eu/m724/tweaks/config/ConfigLoader.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.config;
-
-import org.bukkit.configuration.file.FileConfiguration;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-class ConfigLoader {
- private final FileConfiguration configuration;
- private final List missing = new ArrayList<>();
-
- ConfigLoader(FileConfiguration configuration) {
- this.configuration = configuration;
- }
-
- List getMissing() {
- return missing;
- }
-
- TweaksConfig load() {
- boolean metrics = configuration.getBoolean("metrics", false);
- boolean debug = configuration.getBoolean("debug", false);
- String locale = configuration.getString("locale", "US");
-
- boolean worldborderExpand = getBoolean("worldborder.expand");
- boolean worldborderHide = getBoolean("worldborder.hide");
-
- boolean brandEnabled = getBoolean("brand.enabled");
- String brandText = getString("brand.text");
- boolean brandShowPing = getBoolean("brand.showPing");
- boolean brandShowMspt = getBoolean("brand.showMspt");
-
- boolean doorDoubleOpen = getBoolean("doors.doubleOpen");
- boolean doorKnocking = getBoolean("doors.knocking");
-
- boolean motdEnabled = getBoolean("motd.enabled");
- String motdSet = getString("motd.set");
-
- boolean chatEnabled = getBoolean("chat.enabled");
- boolean chatLocalEvents = getBoolean("chat.localEvents");
- String chatDefaultName = getString("chat.defaultName");
- int chatRadius = getInt("chat.radius");
-
- boolean compassEnabled = getBoolean("compass.enabled");
- int compassWidth = getInt("compass.width");
- int compassPrecision = getInt("compass.precision");
-
- boolean pomodoroEnabled = getBoolean("pomodoro.enabled");
- boolean pomodoroForce = getBoolean("pomodoro.force");
-
- boolean updaterEnabled = getBoolean("updater.enabled");
-
- boolean hardcoreEnabled = getBoolean("hardcore.enabled");
- double hardcoreChance = getDouble("hardcore.chance");
-
- boolean sleepEnabled = getBoolean("sleep.enabled");
- boolean sleepInstant = getBoolean("sleep.instant");
- double sleepHeal = getDouble("sleep.heal");
-
- boolean authEnabled = getBoolean("auth.enabled");
- boolean authForce = getBoolean("auth.force");
- String authHostname = getString("auth.domain");
-
- boolean redstoneEnabled = getBoolean("retstone.enabled");
- String redstoneListen = getString("retstone.listen");
-
- // this is processed when initing knockback module
- Map knockbackModifiers = getValues("knockback");
-
- boolean killswitchEnabled = getBoolean("killswitch.enabled");
- String killswitchListen = getString("killswitch.listen");
-
- boolean swingEnabled = getBoolean("swing.enabled");
-
- return new TweaksConfig(
- metrics, debug, locale,
- worldborderExpand, worldborderHide,
- brandEnabled, brandText, brandShowPing, brandShowMspt,
- doorDoubleOpen, doorKnocking,
- motdEnabled, motdSet,
- chatEnabled, chatLocalEvents, chatDefaultName, chatRadius,
- compassEnabled, compassWidth, compassPrecision,
- pomodoroEnabled, pomodoroForce,
- updaterEnabled,
- hardcoreEnabled, hardcoreChance,
- sleepEnabled, sleepInstant, sleepHeal,
- authEnabled, authForce, authHostname,
- redstoneEnabled, redstoneListen,
- knockbackModifiers,
- killswitchEnabled, killswitchListen,
- swingEnabled
- );
- }
-
- private double getDouble(String key) {
- if (!configuration.contains(key))
- missing.add(key);
-
- // we return the whatever default value
- return configuration.getDouble(key);
- }
-
- private int getInt(String key) {
- if (!configuration.contains(key))
- missing.add(key);
-
- return configuration.getInt(key);
- }
-
- private boolean getBoolean(String key) {
- if (!configuration.contains(key))
- missing.add(key);
-
- return configuration.getBoolean(key);
- }
-
- private String getString(String key) {
- if (!configuration.contains(key))
- missing.add(key);
-
- return configuration.getString(key);
- }
-
- private Map getValues(String key) {
- var cs = configuration.getConfigurationSection(key);
-
- if (cs == null) {
- missing.add(key);
- // the default is null, which is bad
- return new HashMap<>();
- }
-
- return cs.getValues(false);
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/config/MissingFieldsException.java b/src/main/java/eu/m724/tweaks/config/MissingFieldsException.java
deleted file mode 100644
index 24f1be0..0000000
--- a/src/main/java/eu/m724/tweaks/config/MissingFieldsException.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.config;
-
-import java.util.List;
-
-class MissingFieldsException extends Exception {
- private final List missing;
-
- MissingFieldsException(List missing) {
- this.missing = missing;
- }
-
- @Override
- public String getMessage() {
- return String.join(", ", missing);
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/config/TweaksConfig.java b/src/main/java/eu/m724/tweaks/config/TweaksConfig.java
deleted file mode 100644
index 7442813..0000000
--- a/src/main/java/eu/m724/tweaks/config/TweaksConfig.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.config;
-
-import org.bukkit.plugin.Plugin;
-
-import java.util.Map;
-
-public record TweaksConfig(
- boolean metrics,
- boolean debug,
- String locale,
-
- boolean worldborderExpand,
- boolean worldborderHide,
-
- boolean brandEnabled,
- String brandText,
- boolean brandShowPing,
- boolean brandShowMspt,
-
- boolean doorDoubleOpen,
- boolean doorKnocking,
-
- boolean motdEnabled,
- String motdSet,
-
- boolean chatEnabled,
- boolean chatLocalEvents,
- String chatDefaultName,
- int chatRadius,
-
- boolean compassEnabled,
- int compassWidth,
- int compassPrecision,
-
- boolean pomodoroEnabled,
- boolean pomodoroForce,
-
- boolean updaterEnabled,
-
- boolean hardcoreEnabled,
- double hardcoreChance,
-
- boolean sleepEnabled,
- boolean sleepInstant,
- double sleepHeal,
-
- boolean authEnabled,
- boolean authForce,
- String authDomain,
-
- boolean redstoneEnabled,
- String redstoneListen,
-
- Map knockbackModifiers,
-
- boolean killswitchEnabled,
- String killswitchListen,
-
- boolean swingEnabled
-) {
- public static final int CONFIG_VERSION = 2;
- private static TweaksConfig config;
-
- public static TweaksConfig getConfig() {
- return config;
- }
-
- public static TweaksConfig load(Plugin plugin) throws Exception {
- plugin.saveDefaultConfig();
- var pluginConfig = plugin.getConfig();
-
- var configVersion = pluginConfig.getInt("magic number don't modify this", 0);
- var exception = new RuntimeException("Config version is %d, expected %d".formatted(configVersion, CONFIG_VERSION));
-
- if (configVersion == 0) {
- throw exception;
- } else if (configVersion < CONFIG_VERSION) {
- throw new Exception("Please follow update instructions https://www.spigotmc.org/resources/tweaks724.121057/updates", exception);
- } else if (configVersion > CONFIG_VERSION) {
- throw new Exception("Did you downgrade the plugin? Delete config.yml and let the plugin re-create it", exception);
- }
-
- var loader = new ConfigLoader(pluginConfig);
- var config = loader.load();
-
- if (loader.getMissing().isEmpty()) {
- TweaksConfig.config = config;
- return config;
- } else {
- throw new Exception(
- "One or more fields are missing from config.yml. Did you follow the update instructions? https://www.spigotmc.org/resources/tweaks724.121057/updates",
- new MissingFieldsException(loader.getMissing())
- );
- }
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/eu/m724/tweaks/module/door/DoorKnockModule.java b/src/main/java/eu/m724/tweaks/door/DoorKnockListener.java
similarity index 89%
rename from src/main/java/eu/m724/tweaks/module/door/DoorKnockModule.java
rename to src/main/java/eu/m724/tweaks/door/DoorKnockListener.java
index 2213363..b9c718d 100644
--- a/src/main/java/eu/m724/tweaks/module/door/DoorKnockModule.java
+++ b/src/main/java/eu/m724/tweaks/door/DoorKnockListener.java
@@ -1,12 +1,11 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.door;
+package eu.m724.tweaks.door;
-import eu.m724.tweaks.module.TweaksModule;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
@@ -23,12 +22,7 @@ import org.bukkit.util.RayTraceResult;
import java.util.concurrent.ThreadLocalRandom;
-public class DoorKnockModule extends TweaksModule implements Listener {
- @Override
- protected void onInit() {
- registerEvents(this);
- }
-
+public class DoorKnockListener implements Listener {
@EventHandler
public void onBlockDamageAbort(BlockDamageAbortEvent event) {
Block block = event.getBlock();
diff --git a/src/main/java/eu/m724/tweaks/module/door/DoorOpenModule.java b/src/main/java/eu/m724/tweaks/door/DoorOpenListener.java
similarity index 91%
rename from src/main/java/eu/m724/tweaks/module/door/DoorOpenModule.java
rename to src/main/java/eu/m724/tweaks/door/DoorOpenListener.java
index 7705c68..1b431eb 100644
--- a/src/main/java/eu/m724/tweaks/module/door/DoorOpenModule.java
+++ b/src/main/java/eu/m724/tweaks/door/DoorOpenListener.java
@@ -1,12 +1,11 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.door;
+package eu.m724.tweaks.door;
-import eu.m724.tweaks.module.TweaksModule;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@@ -16,11 +15,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
-public class DoorOpenModule extends TweaksModule implements Listener {
- @Override
- protected void onInit() {
- registerEvents(this);
- }
+public class DoorOpenListener implements Listener {
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
@@ -76,4 +71,5 @@ public class DoorOpenModule extends TweaksModule implements Listener {
location.getBlock().setBlockData(nextDoor);
}
}
+
}
diff --git a/src/main/java/eu/m724/tweaks/module/full/FullModule.java b/src/main/java/eu/m724/tweaks/full/FullListener.java
similarity index 66%
rename from src/main/java/eu/m724/tweaks/module/full/FullModule.java
rename to src/main/java/eu/m724/tweaks/full/FullListener.java
index e9569f2..29f4572 100644
--- a/src/main/java/eu/m724/tweaks/module/full/FullModule.java
+++ b/src/main/java/eu/m724/tweaks/full/FullListener.java
@@ -1,22 +1,16 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.full;
+package eu.m724.tweaks.full;
-import eu.m724.tweaks.module.TweaksModule;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
-public class FullModule extends TweaksModule implements Listener {
- @Override
- protected void onInit() {
- registerEvents(this);
- }
-
+public class FullListener implements Listener {
@EventHandler
public void onPlayerLogin(PlayerLoginEvent event) {
if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL && event.getPlayer().hasPermission("tweaks724.bypass-full")) {
diff --git a/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java b/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java
new file mode 100644
index 0000000..0dc632b
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/hardcore/HardcoreManager.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.hardcore;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.ProtocolLibrary;
+import com.comphenix.protocol.events.*;
+import eu.m724.tweaks.TweaksConfig;
+import org.bukkit.plugin.Plugin;
+
+public class HardcoreManager {
+ private final float chance = TweaksConfig.getConfig().hardcoreChance();
+
+ public void init(Plugin plugin) {
+ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
+ plugin,
+ ListenerPriority.NORMAL,
+ PacketType.Play.Server.LOGIN
+ ) {
+ @Override
+ public void onPacketSending(PacketEvent event) {
+ PacketContainer packet = event.getPacket();
+ int entityId = packet.getIntegers().read(0);
+
+ if (chance > ((48271 * entityId) % 65537) / 65537f) // gotta be fast
+ // the "is hardcore" boolean https://wiki.vg/Protocol#Login_.28play.29
+ packet.getBooleans().write(0, true);
+ }
+ });
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/killswitch/KillswitchModule.java b/src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java
similarity index 81%
rename from src/main/java/eu/m724/tweaks/module/killswitch/KillswitchModule.java
rename to src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java
index 9756b88..c16f75d 100644
--- a/src/main/java/eu/m724/tweaks/module/killswitch/KillswitchModule.java
+++ b/src/main/java/eu/m724/tweaks/killswitch/KillswitchManager.java
@@ -4,16 +4,19 @@
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.killswitch;
+package eu.m724.tweaks.killswitch;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.TweaksModule;
+import eu.m724.tweaks.TweaksConfig;
+import eu.m724.tweaks.TweaksPlugin;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -24,12 +27,17 @@ import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
-public class KillswitchModule extends TweaksModule implements CommandExecutor, HttpHandler {
+public class KillswitchManager implements CommandExecutor, HttpHandler {
+ private final Plugin plugin;
private final Ratelimit ratelimit = new Ratelimit();
private byte[] secret;
private String secretEncoded;
+ public KillswitchManager(Plugin plugin) {
+ this.plugin = plugin;
+ }
+
private void loadKey(File file) {
if (file.exists()) {
try {
@@ -55,16 +63,15 @@ public class KillswitchModule extends TweaksModule implements CommandExecutor, H
this.secretEncoded = Base64.getEncoder().encodeToString(secret);
}
- @Override
- protected void onInit() {
- registerCommand("servkill", this);
+ public void init(PluginCommand serverKillCommand) {
+ serverKillCommand.setExecutor(this);
- if (getConfig().killswitchListen() != null) {
- loadKey(new File(getPlugin().getDataFolder(), "storage/killswitch key"));
+ if (TweaksConfig.getConfig().killswitchListen() != null) {
+ loadKey(new File(plugin.getDataFolder(), "storage/killswitch key"));
- ratelimit.runTaskTimerAsynchronously(getPlugin(), 0, 20 * 300);
+ ratelimit.runTaskTimerAsynchronously(plugin, 0, 20 * 300);
- var listenAddress = getConfig().killswitchListen().split(":");
+ var listenAddress = TweaksConfig.getConfig().killswitchListen().split(":");
InetSocketAddress bindAddress;
if (listenAddress.length == 1) {
bindAddress = new InetSocketAddress(Integer.parseInt(listenAddress[0]));
diff --git a/src/main/java/eu/m724/tweaks/module/killswitch/Ratelimit.java b/src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java
similarity index 93%
rename from src/main/java/eu/m724/tweaks/module/killswitch/Ratelimit.java
rename to src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java
index 311c30a..40039b6 100644
--- a/src/main/java/eu/m724/tweaks/module/killswitch/Ratelimit.java
+++ b/src/main/java/eu/m724/tweaks/killswitch/Ratelimit.java
@@ -4,7 +4,7 @@
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.killswitch;
+package eu.m724.tweaks.killswitch;
import org.bukkit.scheduler.BukkitRunnable;
diff --git a/src/main/java/eu/m724/tweaks/module/knockback/KnockbackModule.java b/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java
similarity index 64%
rename from src/main/java/eu/m724/tweaks/module/knockback/KnockbackModule.java
rename to src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java
index 29092fd..14e4764 100644
--- a/src/main/java/eu/m724/tweaks/module/knockback/KnockbackModule.java
+++ b/src/main/java/eu/m724/tweaks/knockback/KnockbackListener.java
@@ -1,28 +1,27 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.knockback;
+package eu.m724.tweaks.knockback;
import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.TweaksModule;
+import eu.m724.tweaks.TweaksConfig;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityKnockbackByEntityEvent;
-import org.bukkit.util.Vector;
+import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Map;
-public class KnockbackModule extends TweaksModule implements Listener {
- private final Map modifiers = new HashMap<>();
+public class KnockbackListener implements Listener {
+ private final Map modifiers = new HashMap<>();
- @Override
- protected void onInit() {
- getConfig().knockbackModifiers().forEach((k, v) -> {
+ public KnockbackListener(Plugin plugin) {
+ TweaksConfig.getConfig().knockbackModifiers().forEach((k, v) -> {
EntityType type;
double mod;
@@ -46,17 +45,11 @@ public class KnockbackModule extends TweaksModule implements Listener {
}
if (mod == 1) return;
- modifiers.put(type, new Vector(mod, mod >= 1 ? mod : 1, mod)); // don't touch vertical
+ modifiers.put(type, mod);
});
- if (!modifiers.isEmpty()) {
- registerEvents(this);
-
- try {
- Class.forName("com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent");
- DebugLogger.warning("Ignore that. Server performance will NOT be affected.");
- } catch (ClassNotFoundException ignored) { }
- }
+ if (!modifiers.isEmpty())
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
diff --git a/src/main/java/eu/m724/tweaks/module/TweaksModule.java b/src/main/java/eu/m724/tweaks/module/TweaksModule.java
deleted file mode 100644
index 6cf6191..0000000
--- a/src/main/java/eu/m724/tweaks/module/TweaksModule.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module;
-
-import com.comphenix.protocol.PacketType;
-import com.comphenix.protocol.ProtocolLibrary;
-import com.comphenix.protocol.events.ListenerPriority;
-import com.comphenix.protocol.events.PacketAdapter;
-import com.comphenix.protocol.events.PacketEvent;
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.config.TweaksConfig;
-import eu.m724.tweaks.TweaksPlugin;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.event.Listener;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.function.Consumer;
-
-public abstract class TweaksModule {
- /**
- * Called on module initialize.
- */
- protected abstract void onInit();
-
- void init() {
- var name = getClass().getSimpleName();
- DebugLogger.finer("Initializing module " + name);
-
- long start = System.nanoTime();
-
- this.onInit();
-
- long end = System.nanoTime();
-
- DebugLogger.fine("Initialized %s in %d µs", name, (end - start) / 1000);
- }
-
- /**
- * Gets the plugin instance.
- *
- * @return The plugin instance
- */
- protected TweaksPlugin getPlugin() {
- return TweaksPlugin.getInstance();
- }
-
- /**
- * Gets the plugin config.
- *
- * @return The plugin config
- */
- protected TweaksConfig getConfig() {
- return TweaksConfig.getConfig();
- }
-
- /**
- * Registers an event listener.
- *
- * @param listener The event listener
- */
- protected void registerEvents(Listener listener) {
- getPlugin().getServer().getPluginManager().registerEvents(listener, getPlugin());
-
- DebugLogger.finer("Registered event listener: " + listener.getClass().getName());
- }
-
- /**
- * Registers an OUTGOING packet listener.
- * Priority is {@link ListenerPriority}.NORMAL.
- *
- * @param packetType The {@link PacketType} to listen for
- * @param consumer The consumer that will be called when the packet is received.
- */
- protected void onPacketSend(PacketType packetType, Consumer consumer) {
- ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(getPlugin(), ListenerPriority.NORMAL, packetType) {
- @Override
- public void onPacketSending(PacketEvent event) {
- consumer.accept(event);
- }
- });
-
- DebugLogger.finer("Registered outgoing packet listener: " + packetType.name());
- }
-
- /**
- * Registers an INCOMING packet listener.
- * Priority is {@link ListenerPriority}.NORMAL.
- *
- * @param packetType The {@link PacketType} to listen for
- * @param consumer The consumer that will be called when the packet is received.
- */
- protected void onPacketReceive(PacketType packetType, Consumer consumer) {
- ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(getPlugin(), ListenerPriority.NORMAL, packetType) {
- @Override
- public void onPacketReceiving(PacketEvent event) {
- consumer.accept(event);
- }
- });
-
- DebugLogger.finer("Registered incoming packet listener: " + packetType.name());
- }
-
- /**
- * Registers a command.
- *
- * @param command The command
- * @param executor The command executor
- */
- protected void registerCommand(String command, CommandExecutor executor) {
- getPlugin().getCommand(command).setExecutor(executor);
- DebugLogger.finer("Registered command: " + command);
- }
-
- /**
- * Initializes a module.
- *
- * @param clazz The class of the initialized module
- * @return The module instance
- * @param The type of the initialized module
- */
- public static T init(Class clazz) {
- T module;
- try {
- module = clazz.getDeclaredConstructor().newInstance();
- } catch (InstantiationException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- throw new RuntimeException(e);
- }
-
- module.init();
-
- return module;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/alert/AlertModule.java b/src/main/java/eu/m724/tweaks/module/alert/AlertModule.java
deleted file mode 100644
index c900b86..0000000
--- a/src/main/java/eu/m724/tweaks/module/alert/AlertModule.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.alert;
-
-import com.comphenix.protocol.PacketType;
-import com.comphenix.protocol.ProtocolLibrary;
-import com.comphenix.protocol.events.PacketContainer;
-import eu.m724.tweaks.module.TweaksModule;
-import org.bukkit.entity.Player;
-import org.bukkit.scheduler.BukkitTask;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class AlertModule extends TweaksModule {
- private BukkitTask notifyTask;
- static Alert current;
- static Map pages = new HashMap<>();
-
- @Override
- protected void onInit() {
- registerCommand("emergencyalert", new AlertCommand(this));
-
- onPacketReceive(PacketType.Play.Client.ENCHANT_ITEM, (event) -> {
- if (current == null) return;
- if (!current.isOpen(event.getPlayer())) return;
-
- PacketContainer packet = event.getPacket();
-
- int windowId, buttonId;
- windowId = packet.getIntegers().read(0);
- buttonId = packet.getIntegers().read(1);
-
- var page = pages.getOrDefault(event.getPlayer(),1);
-
- if (buttonId == 1) { // prev page
- page--;
- } else if (buttonId == 2) { // nextc page
- page++;
- } else {
- return;
- }
-
- pages.put(event.getPlayer(), page);
- var npacket = new PacketContainer(PacketType.Play.Server.WINDOW_DATA);
- npacket.getIntegers().write(0, windowId);
- npacket.getIntegers().write(1, 0);
- npacket.getIntegers().write(2, page);
- ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), npacket);
- });
- }
-
- public Alert start(String... content) {
- stop();
- current = new Alert(content);
- notifyTask = new AlertRunnable(current, v -> this.stop()).runTaskTimer(getPlugin(), 0, 10);
- return current;
- }
-
- public void stop() {
- if (current == null) return;
- for (Player player : getPlugin().getServer().getOnlinePlayers()) {
- if (current.isOpen(player))
- player.closeInventory();
- }
- pages.clear();
- notifyTask.cancel();
- current = null;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/auth/AuthModule.java b/src/main/java/eu/m724/tweaks/module/auth/AuthModule.java
deleted file mode 100644
index f09af23..0000000
--- a/src/main/java/eu/m724/tweaks/module/auth/AuthModule.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.auth;
-
-import eu.m724.tweaks.module.TweaksModule;
-
-public class AuthModule extends TweaksModule {
- @Override
- protected void onInit() {
- var authStorage = new AuthStorage(getPlugin());
-
- registerEvents(new AuthListener(authStorage));
- registerCommand("tauth", new AuthCommands(authStorage));
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java b/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java
deleted file mode 100644
index 59133f0..0000000
--- a/src/main/java/eu/m724/tweaks/module/chat/ChatCommands.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.chat;
-
-import eu.m724.tweaks.Language;
-import net.md_5.bungee.api.ChatColor;
-import net.md_5.bungee.api.chat.BaseComponent;
-import net.md_5.bungee.api.chat.ClickEvent;
-import net.md_5.bungee.api.chat.ComponentBuilder;
-import net.md_5.bungee.api.chat.HoverEvent;
-import net.md_5.bungee.api.chat.hover.content.Text;
-import org.bukkit.Bukkit;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.stream.Collectors;
-
-public class ChatCommands implements CommandExecutor {
- private final ChatModule manager;
-
- public ChatCommands(ChatModule manager) {
- this.manager = manager;
- }
-
- @Override
- public boolean onCommand(@NotNull CommandSender sender, Command command, @NotNull String label, String[] args) {
- if (command.getName().equals("chat")) {
- Player player = (Player) sender;
- ChatRoom chatRoom = manager.getPlayerChatRoom(player);
-
- if (args.length == 0) { // show room
- player.spigot().sendMessage(chatRoom.getInfoComponent());
- } else { // join room
- String id = args[0];
-
- if (id.equals(chatRoom.id)) {
- sender.spigot().sendMessage(Language.getComponent("chatAlreadyHere", ChatColor.GRAY));
- return true;
- }
-
- String password = null;
- if (args.length > 1) {
- password = Arrays.stream(args).skip(1).collect(Collectors.joining(" "));
- }
-
- boolean authenticated = false;
- BaseComponent component = null;
- ChatRoom newRoom = manager.getById(id);
- if (newRoom != null) {
- if (newRoom.password != null) {
- if (newRoom.password.equals(password)) {
- authenticated = true;
- } else if (password == null) {
- component = Language.getComponent("chatPasswordProtected", ChatColor.RED);
- } else {
- component = Language.getComponent("chatWrongPassword", ChatColor.RED);
- }
- } else {
- authenticated = true;
- }
- } else {
- if (ChatRoomLoader.validateId(id) == 0) {
- component = Language.getComponent("chatNoSuchRoom", ChatColor.RED, id);
- } else {
- component = Language.getComponent("chatNoSuchRoomInvalidId", ChatColor.RED, id);
- }
- }
-
- if (authenticated) {
- /*component = new ComponentBuilder(Language.getComponent("chatJoined", ChatColor.GOLD))
- .append(" ")
- .append(ChatFormatUtils.formatChatRoom(chatRoom)).color(newRoom.color)
- .build();*/
- player.sendMessage("");
- manager.setPlayerChatRoom(newRoom, player);
- } else {
- player.spigot().sendMessage(component);
- }
-
- }
- } else if (command.getName().equals("chatmanage")) {
- Player player = (Player) sender;
- ChatRoom chatRoom = manager.getPlayerChatRoom(player);
- boolean isOwner = player.equals(chatRoom.owner);
-
- String action = args.length > 0 ? args[0] : null;
- String argument = args.length > 1 ? args[1] : null;
-
- switch (action) {
- case "create" -> {
- if (argument == null) {
- sender.sendMessage("Please pass a room name as an argument. The room name can contain only characters and digits.");
- return true;
- }
-
- try {
- ChatRoom newRoom = manager.createChatRoom(argument, null, player);
-
- var component = new ComponentBuilder("Created a chat room. Join it: ").color(ChatColor.GOLD)
- .append("/c " + newRoom.id).color(ChatColor.AQUA)
- .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/c " + newRoom.id))
- .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToExecuteCommand"))))
- .append("\n")
- .append("To protect it with a password, join it and use ").color(ChatColor.GRAY)
- .append("/cm setpassword ").color(ChatColor.DARK_PURPLE)
- .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/cm setpassword "))
- .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToExecuteCommand"))));
-
- sender.spigot().sendMessage(component.build());
- } catch (ChatModule.InvalidIdException e) {
- var component = new ComponentBuilder("ID is invalid: ").color(ChatColor.GRAY)
- .append(e.getMessage()).color(ChatColor.RED);
-
- sender.spigot().sendMessage(component.build());
- } catch (ChatModule.ChatRoomExistsException e) {
- sender.sendMessage("Room %s already exists".formatted(argument));
- } catch (IOException e) {
- sender.sendMessage("Error creating room");
- throw new RuntimeException(e);
- }
- }
- case "delete" -> {
- if (isOwner) {
- if (argument == null) {
- sender.sendMessage("You want to delete room \"%s\". Confirm by passing the ID as an argument.".formatted(chatRoom.id));
- return true;
- }
-
- if (argument.equals(chatRoom.id)) {
- manager.deleteChatRoom(chatRoom);
- sender.sendMessage("Room %s deleted".formatted(chatRoom.id));
- } else {
- sender.sendMessage("Pass \"%s\" as an argument to confirm".formatted(chatRoom.id));
- }
- } else {
- sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id));
- }
- }
- case "setowner" -> {
- if (isOwner) {
- if (argument == null) {
- sender.sendMessage("To transfer ownership of room %s, pass the new owner name as an argument for this action.".formatted(chatRoom.id));
- return true;
- }
-
- Player newOwner = Bukkit.getPlayer(argument);
- if (newOwner != null && newOwner.isOnline()) {
- chatRoom.owner = newOwner;
- try {
- manager.saveChatRoom(chatRoom);
- sender.sendMessage("Owner changed to " + newOwner.getName());
- } catch (IOException e) {
- sender.sendMessage("Error changing owner");
- throw new RuntimeException(e);
- }
- } else {
- sender.sendMessage("Player must be online");
- }
- } else {
- sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id));
- }
- }
- case "setpassword" -> {
- if (isOwner) {
- if (argument == null) {
- sender.sendMessage("To change the password of room %s, pass the new password as an argument for this action.".formatted(chatRoom.id));
- return true;
- }
-
- chatRoom.password = Arrays.stream(args).skip(1).collect(Collectors.joining(" "));
- try {
- manager.saveChatRoom(chatRoom);
-
- var component = new ComponentBuilder("Password changed to ").color(ChatColor.GREEN)
- .append("(hover to view)").color(ChatColor.AQUA)
- .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(chatRoom.password)))
- .append("\n")
- .append("To unset, ").color(ChatColor.GRAY)
- .append("/cm unsetpassword").color(ChatColor.DARK_PURPLE)
- .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/cm unsetpassword"))
- .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToExecuteCommand"))));
-
- sender.spigot().sendMessage(component.build());
- } catch (IOException e) {
- sender.sendMessage("Error changing password");
- throw new RuntimeException(e);
- }
- } else {
- sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id));
- }
- }
- case "unsetpassword" -> {
- if (isOwner) {
- chatRoom.password = null;
- try {
- manager.saveChatRoom(chatRoom);
- sender.sendMessage("Password removed from " + chatRoom.id);
- } catch (IOException e) {
- sender.sendMessage("Error removing password");
- throw new RuntimeException(e);
- }
- } else {
- sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id));
- }
- }
- case "setcolor" -> {
- if (isOwner) {
- if (argument == null) {
- sender.sendMessage("To change the message color of room %s, pass the new color as an argument for this action. #hex or color name.".formatted(chatRoom.id));
- return true;
- }
-
- ChatColor newColor = ChatColor.of(argument);
- if (newColor != null) {
- chatRoom.color = newColor;
- try {
- manager.saveChatRoom(chatRoom);
- sender.sendMessage("Message color changed to " + newColor.getName());
- } catch (IOException e) {
- sender.sendMessage("Error changing color");
- throw new RuntimeException(e);
- }
- } else {
- sender.sendMessage("Invalid color");
- }
- } else {
- sender.sendMessage("You're not the owner of %s, please enter the room you want to make changes in".formatted(chatRoom.id));
- }
- }
- case null, default -> {
- sender.sendMessage("Actions: create, delete, setowner, setpassword, unsetpassword, setcolor");
- }
- }
- }
-
- return true;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/durability/DPlayerProperties.java b/src/main/java/eu/m724/tweaks/module/durability/DPlayerProperties.java
deleted file mode 100644
index d3a92d3..0000000
--- a/src/main/java/eu/m724/tweaks/module/durability/DPlayerProperties.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.durability;
-
-import eu.m724.tweaks.TweaksPlugin;
-import org.bukkit.NamespacedKey;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerJoinEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.persistence.PersistentDataType;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class DPlayerProperties implements Listener {
- private final NamespacedKey namespacedKey = new NamespacedKey(TweaksPlugin.getInstance(), "durability_enabled");
- private final Set players = new HashSet<>();
-
- @EventHandler
- public void onPlayerJoin(PlayerJoinEvent event) {
- var player = event.getPlayer();
-
- if (player.hasPermission("tweaks724.durabilityalert")) {
- var enabled = player.getPersistentDataContainer().get(namespacedKey, PersistentDataType.BOOLEAN);
- if (enabled != null && enabled) {
- players.add(player);
- }
- }
- }
-
- @EventHandler
- public void onPlayerQuit(PlayerQuitEvent event) {
- players.remove(event.getPlayer());
- }
-
- Set getPlayers() {
- return Set.copyOf(players);
- }
-
- boolean isPlayerEnabled(Player player) {
- return players.contains(player);
- }
-
- void disableForPlayer(Player player) {
- players.remove(player);
- player.getPersistentDataContainer().set(namespacedKey, PersistentDataType.BOOLEAN, false);
- }
-
- void enableForPlayer(Player player) {
- players.add(player);
- player.getPersistentDataContainer().set(namespacedKey, PersistentDataType.BOOLEAN, true);
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/durability/DurabilityCaches.java b/src/main/java/eu/m724/tweaks/module/durability/DurabilityCaches.java
deleted file mode 100644
index 4ab41d7..0000000
--- a/src/main/java/eu/m724/tweaks/module/durability/DurabilityCaches.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.durability;
-
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class DurabilityCaches {
- private final Map lastFullReminder = new HashMap<>();
- // BAD
- private final Map> lastUse = new HashMap<>();
- // BAD
- private final Map> lastPing = new HashMap<>();
-
- boolean shouldFullRemind(Player player, long now) {
- var lfr = lastFullReminder.getOrDefault(player, 0L);
-
- if (now - lfr > 300 * 1000) {
- lastFullReminder.put(player, now);
- return true;
- } else if (now - lfr < 3 * 1000) {
- return true;
- }
-
- return false;
- }
-
- boolean shouldRemind(Player player, ItemStack itemStack, long now) {
- var lu = lastUse.computeIfAbsent(player, (k) -> new HashMap<>()).getOrDefault(itemStack.getType(), 0L);
-
- if (now - lu > 180 * 1000) {
- lastUse.get(player).put(itemStack.getType(), now);
- return true;
- } else if (now - lu < 3 * 1000) {
- return true;
- }
-
- return false;
- }
-
- boolean shouldPing(Player player, ItemStack itemStack, long now) {
- var lp = lastPing.computeIfAbsent(player, (k) -> new HashMap<>()).getOrDefault(itemStack.getType(), 0L);
-
- if (now - lp > 60 * 1000) {
- lastPing.get(player).put(itemStack.getType(), now);
- return true;
- }
-
- return false;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/durability/DurabilityCommands.java b/src/main/java/eu/m724/tweaks/module/durability/DurabilityCommands.java
deleted file mode 100644
index 2d6501c..0000000
--- a/src/main/java/eu/m724/tweaks/module/durability/DurabilityCommands.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.durability;
-
-import eu.m724.tweaks.Language;
-import net.md_5.bungee.api.ChatColor;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
-
-public class DurabilityCommands implements CommandExecutor {
- private final DPlayerProperties properties;
-
- public DurabilityCommands(DPlayerProperties properties) {
- this.properties = properties;
- }
-
- @Override
- public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
- if (!(sender instanceof Player player)) {
- sender.sendMessage("Only players can use this command");
- return true;
- }
-
- if (properties.isPlayerEnabled(player)) {
- properties.disableForPlayer(player);
- sender.spigot().sendMessage(Language.getComponent("durabilityDisabled", ChatColor.GRAY));
- } else {
- properties.enableForPlayer(player);
- sender.spigot().sendMessage(Language.getComponent("durabilityEnabled", ChatColor.GRAY));
- }
-
- return true;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java b/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java
deleted file mode 100644
index b582bfc..0000000
--- a/src/main/java/eu/m724/tweaks/module/durability/DurabilityModule.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.durability;
-
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.TweaksModule;
-import net.md_5.bungee.api.ChatColor;
-import net.md_5.bungee.api.ChatMessageType;
-import net.md_5.bungee.api.chat.ComponentBuilder;
-import org.bukkit.Material;
-import org.bukkit.Sound;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerItemDamageEvent;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.Damageable;
-import org.bukkit.scheduler.BukkitRunnable;
-
-import java.awt.Color;
-
-public class DurabilityModule extends TweaksModule implements Listener {
- private final DurabilityCaches cache = new DurabilityCaches();
- private final DPlayerProperties properties = new DPlayerProperties();
-
- @Override
- protected void onInit() {
- registerEvents(this);
-
- registerCommand("durabilityalert", new DurabilityCommands(properties));
-
- new BukkitRunnable() {
- @Override
- public void run() {
- properties.getPlayers().forEach(p -> refreshBar(p));
- }
- }.runTaskTimerAsynchronously(getPlugin(), 0, 40);
- }
-
- @EventHandler
- public void onPlayerItemDamage(PlayerItemDamageEvent event) {
- refreshBar(event.getPlayer(), event.getItem(), event.getDamage());
- }
-
- private void refreshBar(Player player) {
- refreshBar(player, null, -1);
- }
-
- private void refreshBar(Player player, ItemStack justDamaged, int damage) {
- if (!properties.isPlayerEnabled(player)) return;
-
- var items = new ItemStack[] {
- player.getInventory().getHelmet(),
- player.getInventory().getChestplate(),
- player.getInventory().getLeggings(),
- player.getInventory().getBoots(),
- player.getInventory().getItemInMainHand(),
- player.getInventory().getItemInOffHand()
- };
-
- var builder = new ComponentBuilder();
-
- var now = System.currentTimeMillis();
- var all = cache.shouldFullRemind(player, now);
-
- for (var itemStack : items) {
- if (itemStack == null || !itemStack.hasItemMeta()) continue;
-
- if (itemStack.getItemMeta() instanceof Damageable meta) {
- var target = itemStack.equals(justDamaged);
-
- var maxDurability = itemStack.getType().getMaxDurability();
- var durability = maxDurability - meta.getDamage() - (target ? damage : 0);
- durability = Math.max(0, durability);
- var percentage = (double) durability / maxDurability;
-
- var notify = durability < 30 && (durability < 10 || percentage < 0.1);
-
- var remind = cache.shouldRemind(player, itemStack, now);
- var important = target && notify && cache.shouldPing(player, itemStack, now);
-
- DebugLogger.finer("%s's %s: %d / %d (%.2f%%)%s%s", player.getName(), itemStack.getType().name(), durability, maxDurability, percentage * 100, notify ? " notify" : "", important ? " important" : "");
-
- if (notify || all || remind) {
- var longName = remind || important;
- var label = longName ? getMaterialLongName(itemStack.getType()) : getMaterialShortName(itemStack.getType());
- var labelColor = percentage > 0 ? matColor(itemStack.getType()) : ChatColor.DARK_RED;
-
- var percentageStr = (int) (percentage * 100) + "%";
- var percentageColor = mixColor(labelColor, ChatColor.DARK_RED, 1.0 - percentage * 10);
-
- builder.append(label + " ").color(labelColor);
- builder.append(percentageStr + " ").color(percentageColor);
-
- if (important) {
- player.playSound(player, Sound.BLOCK_ANVIL_PLACE, 0.5f, 1.5f);
- player.sendTitle("", labelColor + label + " " + percentageColor + percentageStr, 5, 20, 5);
- }
- }
- }
- }
-
- var component = builder.create();
- if (component.length > 0)
- player.spigot().sendMessage(ChatMessageType.ACTION_BAR, component);
- }
-
- private String getMaterialLongName(Material material) {
- var sp = material.name().split("_");
- var str = sp[sp.length - 1];
- return str.charAt(0) + str.substring(1).toLowerCase();
- }
-
- private String getMaterialShortName(Material material) {
- return getMaterialLongName(material).substring(0, 2);
- }
-
- private ChatColor mixColor(ChatColor from, ChatColor to, double percentage) {
- percentage = Math.clamp(percentage, 0.0, 1.0);
-
- var diffR = to.getColor().getRed() - from.getColor().getRed();
- var diffG = to.getColor().getGreen() - from.getColor().getGreen();
- var diffB = to.getColor().getBlue() - from.getColor().getBlue();
-
- var r = from.getColor().getRed() + (int) (diffR * percentage);
- var g = from.getColor().getGreen() + (int) (diffG * percentage);
- var b = from.getColor().getBlue() + (int) (diffB * percentage);
-
- return ChatColor.of(new Color(r, g, b));
- }
-
- private ChatColor matColor(Material material) {
- var color = ChatColor.DARK_GRAY;
-
- if (material.name().startsWith("DIAMOND_")) {
- color = ChatColor.AQUA;
- } else if (material.name().startsWith("NETHERITE_")) {
- color = ChatColor.DARK_PURPLE;
- } else if (material.name().startsWith("IRON_")) {
- color = ChatColor.WHITE;
- } else if (material.name().startsWith("STONE_")) {
- color = ChatColor.GRAY;
- } else if (material.name().startsWith("WOODEN_")) {
- color = ChatColor.DARK_GREEN;
- } else if (material.name().startsWith("GOLDEN_")) {
- color = ChatColor.GOLD;
- }
-
- return color;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/hardcore/HardcoreModule.java b/src/main/java/eu/m724/tweaks/module/hardcore/HardcoreModule.java
deleted file mode 100644
index 387d51b..0000000
--- a/src/main/java/eu/m724/tweaks/module/hardcore/HardcoreModule.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.hardcore;
-
-import com.comphenix.protocol.PacketType;
-import com.comphenix.protocol.events.PacketContainer;
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.TweaksModule;
-import net.minecraft.world.level.levelgen.RandomSupport;
-import net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-// how we do it is much faster than any Random
-public class HardcoreModule extends TweaksModule {
- private final Xoroshiro128PlusPlus rng;
- private final long chanceLong;
-
- public HardcoreModule() {
- this.rng = new Xoroshiro128PlusPlus(
- RandomSupport.generateUniqueSeed(),
- RandomSupport.generateUniqueSeed()
- );
-
- this.chanceLong = BigInteger.valueOf(Long.MIN_VALUE)
- .add(
- new BigDecimal(
- BigInteger.valueOf(Long.MAX_VALUE).subtract(BigInteger.valueOf(Long.MIN_VALUE))
- ).multiply(
- BigDecimal.valueOf(getConfig().hardcoreChance())
- ).toBigInteger()
- ).longValue();
- }
-
- @Override
- protected void onInit() {
- DebugLogger.fine("Chance long: " + chanceLong);
-
- onPacketSend(PacketType.Play.Server.LOGIN, (event) -> {
- PacketContainer packet = event.getPacket();
-
- if (rng.nextLong() < chanceLong)
- // the "is hardcore" boolean https://wiki.vg/Protocol#Login_.28play.29
- packet.getBooleans().write(0, true);
- });
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java b/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java
deleted file mode 100644
index 63f1b6c..0000000
--- a/src/main/java/eu/m724/tweaks/module/motd/MotdModule.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.motd;
-
-import com.comphenix.protocol.PacketType;
-import com.comphenix.protocol.events.InternalStructure;
-import com.comphenix.protocol.events.PacketContainer;
-import com.comphenix.protocol.reflect.StructureModifier;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonParser;
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.TweaksModule;
-import net.md_5.bungee.api.chat.TextComponent;
-import net.md_5.bungee.chat.ComponentSerializer;
-import net.minecraft.SharedConstants;
-import net.minecraft.core.RegistryAccess;
-import net.minecraft.network.chat.Component;
-import net.minecraft.network.protocol.status.ServerStatus;
-
-import java.io.IOException;
-import java.nio.file.FileAlreadyExistsException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.Optional;
-import java.util.concurrent.ThreadLocalRandom;
-
-public class MotdModule extends TweaksModule {
- @Override
- protected void onInit() {
- Path motdSetPath = getPlugin().getDataFolder().toPath().resolve("motd sets").resolve(getConfig().motdSet() + ".txt");
-
- // create "motd sets" directory
- try {
- Files.createDirectories(motdSetPath);
- } catch (FileAlreadyExistsException ignored) {
-
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- // if this is a builtin set
- if (!Files.exists(motdSetPath) && getPlugin().hasResource("motd sets/" + motdSetPath.getFileName()))
- getPlugin().saveResource("motd sets/" + motdSetPath.getFileName(), false);
-
- if (!Files.exists(motdSetPath)) {
- throw new RuntimeException("MOTD set \"%s\" doesn't exist".formatted(getConfig().motdSet()));
- }
-
- String fileContent;
- try {
- fileContent = Files.readString(motdSetPath);
- } catch (IOException e) {
- throw new RuntimeException("Reading motd set", e);
- }
-
- // MOTDs are split with an empty line
- Component[] motds = Arrays.stream(fileContent.split("\n\n"))
- .map(entry -> {
- entry = entry.strip();
- JsonElement json = null;
-
- try {
- json = JsonParser.parseString(entry);
- DebugLogger.finer("JSON line: %s...", entry.substring(0, Math.min(entry.length(), 10)));
- } catch (JsonParseException e) {
- DebugLogger.finer("JSON line: %s...", entry.substring(0, Math.min(entry.length(), 10)));
- }
-
- if (json == null) {
- json = ComponentSerializer.toJson(TextComponent.fromLegacy(entry));
- }
-
- return Component.Serializer.fromJson(json, RegistryAccess.EMPTY);
- })
- .toArray(Component[]::new);
-
- onPacketSend(PacketType.Status.Server.SERVER_INFO, (event) -> {
- PacketContainer packet = event.getPacket();
-
- Component motd = motds[ThreadLocalRandom.current().nextInt(motds.length)];
-
- ServerStatus serverStatus = (ServerStatus) packet.getStructures().read(0).getHandle();
-
- /* this:
- * removes server mod prefix (Paper, Spigot, any brand)
- * hides players
- */
- ServerStatus newStatus = new ServerStatus(
- motd,
- Optional.empty(),
- Optional.of(new ServerStatus.Version(
- SharedConstants.getCurrentVersion().getName(),
- SharedConstants.getProtocolVersion()
- )),
- serverStatus.favicon(),
- false
- );
-
- packet.getStructures().write(0, new InternalStructure(newStatus, new StructureModifier<>(ServerStatus.class)));
- });
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java
deleted file mode 100644
index 331c1c6..0000000
--- a/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoro.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.pomodoro;
-
-import java.util.concurrent.TimeUnit;
-
-public class PlayerPomodoro {
- private int intervalsDone = 0;
-
- private boolean breaktime = false;
- private long currentIntervalStartedAtNanos = -1;
-
- public int getIntervalsDone() {
- return intervalsDone;
- }
-
- public boolean isBreaktime() {
- return breaktime;
- }
-
- public boolean isLongBreak() {
- return (intervalsDone + 1) % PomodoroModule.INTERVALS_BEFORE_LONG_BREAK == 0;
- }
-
- /**
- * @return The time the current interval or break started, in milliseconds
- */
- public long getCurrentIntervalStartedAtNanos() {
- return currentIntervalStartedAtNanos;
- }
-
- public int getCurrentIntervalDurationSeconds() {
- if (breaktime) {
- if (isLongBreak()) {
- return PomodoroModule.LONG_BREAK_DURATION_SECONDS;
- }
-
- return PomodoroModule.SHORT_BREAK_DURATION_SECONDS;
- } else {
- return PomodoroModule.INTERVAL_DURATION_SECONDS;
- }
- }
-
- public long getCurrentIntervalDurationNanos() {
- return TimeUnit.SECONDS.toNanos(getCurrentIntervalDurationSeconds());
- }
-
- public long getCurrentIntervalRemainingNanos(long nowNanos) {
- long elapsed = nowNanos - getCurrentIntervalStartedAtNanos();
- return getCurrentIntervalDurationNanos() - elapsed;
- }
-
- public boolean isIntervalComplete(long nowNanos) {
- return currentIntervalStartedAtNanos + getCurrentIntervalDurationNanos() < nowNanos;
- }
-
- /**
- * Resets and starts the timer
- */
- public void start() {
- this.intervalsDone = 0;
- this.breaktime = false;
- this.currentIntervalStartedAtNanos = System.nanoTime();
- }
-
- /**
- * Completes a cycle
- */
- public void startBreakOrNextInterval() {
- if (breaktime) { // from break to interval
- this.intervalsDone++;
- this.intervalsDone %= PomodoroModule.INTERVALS_BEFORE_LONG_BREAK;
- }
-
- this.currentIntervalStartedAtNanos = System.nanoTime();
- breaktime = !breaktime;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoroTracker.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoroTracker.java
deleted file mode 100644
index 92e3c6f..0000000
--- a/src/main/java/eu/m724/tweaks/module/pomodoro/PlayerPomodoroTracker.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.pomodoro;
-
-import org.bukkit.entity.Player;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-public class PlayerPomodoroTracker {
- static final Map timers = new HashMap<>();
-
- public static PlayerPomodoro get(Player player) {
- return timers.get(player.getUniqueId());
- }
-
- public static PlayerPomodoro create(Player player) {
- return timers.computeIfAbsent(player.getUniqueId(), (k) -> new PlayerPomodoro());
- }
-
- public static boolean remove(Player player) {
- return timers.remove(player.getUniqueId()) != null;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java
deleted file mode 100644
index ee452ab..0000000
--- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroCommands.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.pomodoro;
-
-import eu.m724.tweaks.Language;
-import eu.m724.tweaks.config.TweaksConfig;
-import net.md_5.bungee.api.ChatColor;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.jetbrains.annotations.NotNull;
-
-public class PomodoroCommands implements CommandExecutor {
- @Override
- public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
- Player player = (Player) sender;
- String action = args.length > 0 ? args[0] : null;
-
- PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player);
-
- long now = System.nanoTime();
-
- if (pomodoro != null) {
- if ("stop".equals(action)) {
- PlayerPomodoroTracker.remove(player);
- sender.spigot().sendMessage(Language.getComponent("pomodoroStopped", ChatColor.GREEN, label));
- } else {
- if (pomodoro.isIntervalComplete(now)) {
- pomodoro.startBreakOrNextInterval();
-
- if (pomodoro.isBreaktime() && TweaksConfig.getConfig().pomodoroForce()) {
- player.kickPlayer(PomodoroModule.formatTimer(pomodoro, now).toLegacyText());
- }
- }
-
- sender.spigot().sendMessage(PomodoroModule.formatTimer(pomodoro, now));
- }
- } else {
- if ("start".equals(action)) {
- pomodoro = PlayerPomodoroTracker.create(player);
- pomodoro.start();
-
- sender.spigot().sendMessage(PomodoroModule.formatTimer(pomodoro, now));
- } else {
- // TODO help?
- sender.spigot().sendMessage(Language.getComponent("pomodoroStart", ChatColor.GOLD, label));
- }
- }
-
- return true;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java
deleted file mode 100644
index 853215e..0000000
--- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroListener.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.pomodoro;
-
-import eu.m724.tweaks.config.TweaksConfig;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerLoginEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.event.player.PlayerToggleSneakEvent;
-
-public class PomodoroListener implements Listener {
- private final TweaksConfig config = TweaksConfig.getConfig();
-
- @EventHandler
- public void onPlayerLogin(PlayerLoginEvent event) {
- // Joining ends break
- Player player = event.getPlayer();
- PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player);
- if (pomodoro == null) return;
-
- long now = System.nanoTime();
- long remaining = pomodoro.getCurrentIntervalRemainingNanos(now);
-
- if (pomodoro.isBreaktime()) {
- if (remaining > 0 && config.pomodoroForce()) {
- player.kickPlayer(PomodoroModule.formatTimer(pomodoro, now).toLegacyText());
- } else {
- pomodoro.startBreakOrNextInterval();
- }
- }
- }
-
- @EventHandler
- public void onPlayerQuit(PlayerQuitEvent event) {
- // Quitting starts break
- Player player = event.getPlayer();
- PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player);
- if (pomodoro == null) return;
-
- if (pomodoro.isBreaktime()) return;
-
- long now = System.nanoTime();
- long remaining = pomodoro.getCurrentIntervalRemainingNanos(now);
-
- if (remaining <= 0) {
- pomodoro.startBreakOrNextInterval();
- }
- }
-
- @EventHandler
- public void onPlayerToggleSneak(PlayerToggleSneakEvent event) {
- // Sneaking ends break
- if (!event.isSneaking()) return;
-
- Player player = event.getPlayer();
- PlayerPomodoro pomodoro = PlayerPomodoroTracker.get(player);
- if (pomodoro == null) return;
-
- if (!pomodoro.isBreaktime()) return;
-
- long now = System.nanoTime();
- long remaining = pomodoro.getCurrentIntervalRemainingNanos(now);
-
- if (remaining <= 0) {
- pomodoro.startBreakOrNextInterval();
- }
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java
deleted file mode 100644
index c97da7d..0000000
--- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroModule.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.pomodoro;
-
-import eu.m724.tweaks.Language;
-import eu.m724.tweaks.config.TweaksConfig;
-import eu.m724.tweaks.module.TweaksModule;
-import net.md_5.bungee.api.ChatColor;
-import net.md_5.bungee.api.chat.BaseComponent;
-import net.md_5.bungee.api.chat.ComponentBuilder;
-
-import java.util.concurrent.TimeUnit;
-
-public class PomodoroModule extends TweaksModule {
- static final int INTERVAL_DURATION_SECONDS = 10;
- static final int SHORT_BREAK_DURATION_SECONDS = (int) TimeUnit.MINUTES.toSeconds(5);
- static final int LONG_BREAK_DURATION_SECONDS = (int) TimeUnit.MINUTES.toSeconds(20);
- static final int INTERVALS_BEFORE_LONG_BREAK = 4;
-
- static final int KICK_DELAY_SECONDS = 60;
-
- @Override
- protected void onInit() {
- registerEvents(new PomodoroListener());
- new PomodoroRunnable().runTaskTimerAsynchronously(getPlugin(), 0, 20L);
-
- registerCommand("pomodoro", new PomodoroCommands());
- }
-
- /**
- * Gets a formatted timer for a player.
- *
- * @param pomodoro the player's {@link PlayerPomodoro} instance
- * @param nowNanos unix now timestamp in nanoseconds
- * @return the timer as {@link BaseComponent}
- */
- static BaseComponent formatTimer(PlayerPomodoro pomodoro, long nowNanos) {
- ComponentBuilder builder = new ComponentBuilder();
-
- long remainingNanos = pomodoro.getCurrentIntervalRemainingNanos(nowNanos);
- long remainingSeconds = TimeUnit.NANOSECONDS.toSeconds(remainingNanos);
-
- if (pomodoro.isBreaktime()) {
- if (pomodoro.isLongBreak()) {
- builder.append(Language.getComponent("pomodoroLongBreak", ChatColor.LIGHT_PURPLE));
- } else {
- builder.append(Language.getComponent("pomodoroShortBreak", ChatColor.LIGHT_PURPLE));
- }
-
- if (remainingNanos > 0) {
- builder.append(" %02d:%02d".formatted(remainingSeconds / 60, remainingSeconds % 60))
- .color(ChatColor.GOLD);
- } else {
- builder.append(" 00:00")
- .color(ChatColor.GREEN);
-
- if (!TweaksConfig.getConfig().pomodoroForce()) {
- builder.append( "/pom").color(ChatColor.GOLD);
- }
- }
- } else {
- if (remainingNanos > 0) {
- builder
- .append("%02d:%02d".formatted(remainingSeconds / 60, remainingSeconds % 60))
- .color(ChatColor.GRAY);
- } else {
- builder
- .append("00:00")
- .color(remainingSeconds % 2 == 0 ? ChatColor.RED : ChatColor.GRAY);
-
- if (!TweaksConfig.getConfig().pomodoroForce()) {
- builder.append( "/pom").color(ChatColor.GOLD);
- }
- }
- }
-
-
- for (int i=0; i pomodoro.getIntervalsDone()) {
- color = ChatColor.DARK_GRAY;
- }
-
- builder.append(" o").color(color);
- }
-
- return builder.build();
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java b/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java
deleted file mode 100644
index f9bd924..0000000
--- a/src/main/java/eu/m724/tweaks/module/pomodoro/PomodoroRunnable.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.pomodoro;
-
-import eu.m724.tweaks.TweaksPlugin;
-import eu.m724.tweaks.config.TweaksConfig;
-import net.md_5.bungee.api.ChatMessageType;
-import org.bukkit.Sound;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.scheduler.BukkitRunnable;
-
-import java.util.concurrent.TimeUnit;
-
-public class PomodoroRunnable extends BukkitRunnable {
- private final TweaksConfig config = TweaksConfig.getConfig();
- private final Plugin plugin = TweaksPlugin.getInstance(); // used only to kick
-
- @Override
- public void run() {
- long now = System.nanoTime();
-
- PlayerPomodoroTracker.timers.forEach((uuid, pomodoro) -> {
- long remainingNanos = pomodoro.getCurrentIntervalRemainingNanos(now);
- long remainingSecs = TimeUnit.NANOSECONDS.toSeconds(remainingNanos);
-
- // TODO optimize?
- Player player = plugin.getServer().getPlayer(uuid);
-
- if (player != null && player.isOnline()) {
- // TODO make not always on
- player.spigot().sendMessage(ChatMessageType.ACTION_BAR, PomodoroModule.formatTimer(pomodoro, now));
-
- if (remainingNanos <= 0) {
- player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1.0f, 0.5f);
-
- if (remainingSecs < -PomodoroModule.KICK_DELAY_SECONDS && config.pomodoroForce()) {
- pomodoro.startBreakOrNextInterval();
-
- plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () ->
- player.kickPlayer(PomodoroModule.formatTimer(pomodoro, now).toLegacyText())
- );
- }
- }
- } else {
- if (remainingNanos <= 0) {
- // Start break automatically if the player is offline
- if (!pomodoro.isBreaktime()) {
- pomodoro.startBreakOrNextInterval();
- }
- }
- }
- });
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/sleep/SleepModule.java b/src/main/java/eu/m724/tweaks/module/sleep/SleepModule.java
deleted file mode 100644
index e2d45f8..0000000
--- a/src/main/java/eu/m724/tweaks/module/sleep/SleepModule.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.sleep;
-
-import eu.m724.tweaks.module.TweaksModule;
-
-public class SleepModule extends TweaksModule {
- @Override
- protected void onInit() {
- registerEvents(new SleepListener());
-
- if (!getConfig().sleepInstant())
- new TimeForwardRunnable(getPlugin()).runTaskTimer(getPlugin(), 0, 1); // TODO maybe not
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java b/src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java
deleted file mode 100644
index d435be9..0000000
--- a/src/main/java/eu/m724/tweaks/module/sleep/TimeForwardRunnable.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.sleep;
-
-import org.bukkit.GameRule;
-import org.bukkit.Server;
-import org.bukkit.World;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.scheduler.BukkitRunnable;
-
-public class TimeForwardRunnable extends BukkitRunnable {
- private final Server server;
-
- public TimeForwardRunnable(Plugin plugin) {
- this.server = plugin.getServer();
- }
-
- @Override
- public void run() {
- for (World world : server.getWorlds()) {
- var gameRuleValue = world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE);
- if (gameRuleValue == null) gameRuleValue = 100;
- double percentage = gameRuleValue / 100.0;
-
- int playersSleeping = SleepState.playersSleeping;
- //System.out.println(playersSleeping);
- if (playersSleeping == 0) return;
-
- int onlinePlayers = (int) (world.getPlayers().size() / percentage);
-
- double sleepPercentage = (double) playersSleeping / onlinePlayers;
-
- // we want sleep to take 200 ticks which is 10 seconds assuming all palyres onilien
-
- long time = world.getTime();
- long untilDay = 23459 - time;
-
- if (untilDay == 0) return;
-
- long perSkip = 200 + (100000 / -untilDay);
- perSkip = Math.clamp(perSkip, 20, 200);
- perSkip = (long) (perSkip * sleepPercentage);
-
- world.setTime(world.getTime() + perSkip);
- }
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/swing/SwingModule.java b/src/main/java/eu/m724/tweaks/module/swing/SwingModule.java
deleted file mode 100644
index 392c13f..0000000
--- a/src/main/java/eu/m724/tweaks/module/swing/SwingModule.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.swing;
-
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.TweaksModule;
-import org.bukkit.Material;
-import org.bukkit.attribute.Attribute;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.block.BlockBreakEvent;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-public class SwingModule extends TweaksModule implements Listener {
- private final Set tools = new HashSet<>();
-
- @Override
- protected void onInit() {
- Arrays.stream(Material.values())
- .filter(m -> m.name().contains("SWORD"))
- .forEach(tools::add);
-
- DebugLogger.finer("Tools: " + tools.size());
-
- registerEvents(this);
- }
-
- @EventHandler
- public void onBreak(BlockBreakEvent event) {
- var type = event.getBlock().getType();
- if (type.isOccluding()) return;
-
- var player = event.getPlayer();
- var tool = player.getInventory().getItemInMainHand().getType();
- Entity entity = null;
-
- if (tools.contains(tool)) { // if sword, raycast to hit farther
- var result = player.getWorld().rayTraceEntities(
- player.getEyeLocation(),
- player.getEyeLocation().getDirection(),
- player.getAttribute(Attribute.PLAYER_ENTITY_INTERACTION_RANGE).getValue(),
- e -> e != player
- );
-
- if (result != null)
- entity = result.getHitEntity();
- } else {
- entity = event.getBlock().getWorld()
- .getNearbyEntities(event.getBlock().getLocation().add(0.5, 0.5, 0.5), 0.5, 0.5, 0.5)
- .stream().filter(e -> (e instanceof LivingEntity && e != player))
- .findFirst().orElse(null);
- }
-
- if (entity != null) {
- player.attack(entity);
- DebugLogger.fine("Swing " + player.getName() + " hit " + entity.getName());
- }
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/updater/UpdaterModule.java b/src/main/java/eu/m724/tweaks/module/updater/UpdaterModule.java
deleted file mode 100644
index 6c39e17..0000000
--- a/src/main/java/eu/m724/tweaks/module/updater/UpdaterModule.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.updater;
-
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.TweaksModule;
-import eu.m724.tweaks.module.updater.backend.UpdateChecker;
-import eu.m724.tweaks.module.updater.backend.VersionCache;
-import eu.m724.tweaks.module.updater.object.ResourceVersion;
-import eu.m724.tweaks.module.updater.object.SpigotResource;
-import eu.m724.tweaks.module.updater.object.VersionedResource;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.plugin.Plugin;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-public class UpdaterModule extends TweaksModule {
- @Override
- protected void onInit() {
- var resources = loadInstalledPlugins();
-
- // load installed versions from cache
- var cacheFile = new File(getPlugin().getDataFolder(), "storage/cache/updater");
-
- final var installedVersions = loadInstalledVersionCache(cacheFile);
-
- var versionedResources = resources.stream()
- .map(res -> new VersionedResource(
- res, installedVersions.stream().filter(iv -> iv.resourceId() == res.resourceId()).findFirst().orElse(null), null
- ))
- .collect(Collectors.toSet());
-
-
- var updateChecker = new UpdateChecker(getPlugin().getLogger(), cacheFile, versionedResources);
- updateChecker.runTaskTimerAsynchronously(getPlugin(), 600, 12 * 3600 * 20); // 12 hours
-
- registerCommand("updates", new UpdaterCommands(updateChecker));
- }
-
- private Set loadInstalledVersionCache(File cacheFile) {
- try (FileInputStream inputStream = new FileInputStream(cacheFile)) {
- return VersionCache.loadAll(inputStream);
- } catch (FileNotFoundException ignored) {
- } catch (IOException e) {
- DebugLogger.warning("Error loading installed version cache, starting fresh. " + e.getMessage());
- }
-
- return new HashSet<>();
- }
-
- private Set loadInstalledPlugins() {
- File installedPluginsYml = new File(getPlugin().getDataFolder(), "installed_plugins.yml");
-
- if (!installedPluginsYml.exists()) {
- getPlugin().saveResource("installed_plugins.yml", false);
- }
-
- YamlConfiguration configuration = YamlConfiguration.loadConfiguration(installedPluginsYml);
-
- Plugin[] plugins = getPlugin().getServer().getPluginManager().getPlugins();
- Set spigotResources = new HashSet<>();
-
- for (Plugin plugin : plugins) {
- String pluginName = plugin.getName();
-
- if (!configuration.isSet(pluginName)) {
- configuration.set(pluginName, -1);
- continue;
- }
-
- int pluginId = configuration.getInt(pluginName);
- if (pluginId > 0) {
- spigotResources.add(
- new SpigotResource(plugin, pluginId, pluginName)
- );
- }
- }
-
- try {
- configuration.save(installedPluginsYml);
- } catch (IOException e) {
- throw new RuntimeException("Failed to update installed_plugins.yml", e);
- }
-
- return spigotResources;
-
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java
deleted file mode 100644
index 054d1ee..0000000
--- a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsConverter.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.wordcoords;
-
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.wordcoords.converter.Decoder;
-import eu.m724.tweaks.module.wordcoords.converter.Encoder;
-
-import java.util.NoSuchElementException;
-
-public class WordCoordsConverter {
- private final Encoder encoder;
- private final Decoder decoder;
-
-
- public WordCoordsConverter(WordList wordList) {
- this.encoder = new Encoder(wordList);
- this.decoder = new Decoder(wordList);
-
- DebugLogger.fine("Words: %d (%d bits)", wordList.getWordCount(), wordList.getBitsPerWord());
- DebugLogger.fine("Bits per word: %d", wordList.getBitsPerWord());
- }
-
- public String[] encode(int x, int z) {
- return encoder.encode(x, z);
- }
-
- public int[] decode(String[] words) throws NoSuchElementException {
- return decoder.decode(words);
- }
-
-}
diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java b/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java
deleted file mode 100644
index 603b33d..0000000
--- a/src/main/java/eu/m724/tweaks/module/wordcoords/WordCoordsModule.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.wordcoords;
-
-import eu.m724.tweaks.Language;
-import eu.m724.tweaks.module.TweaksModule;
-import net.md_5.bungee.api.ChatColor;
-import net.md_5.bungee.api.chat.BaseComponent;
-import net.md_5.bungee.api.chat.ClickEvent;
-import net.md_5.bungee.api.chat.ComponentBuilder;
-import net.md_5.bungee.api.chat.HoverEvent;
-import net.md_5.bungee.api.chat.hover.content.Text;
-
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerCommandPreprocessEvent;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-public class WordCoordsModule extends TweaksModule implements CommandExecutor, Listener {
- private WordList wordList;
- private WordCoordsConverter converter;
-
- @Override
- protected void onInit() {
- try {
- this.wordList = WordList.fromFile(getPlugin().getDataFolder().toPath().resolve("storage/wordlist.txt"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- this.converter = new WordCoordsConverter(wordList);
-
- registerCommand("wordcoords", this);
- registerEvents(this);
- }
-
- @Override
- public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
- int x = 0, z = 0;
- String[] words = new String[0];
-
- boolean encode = false; // means encode pos to words
-
- if (args.length == 0) {
- if (!(sender instanceof Player player)) {
- sender.sendMessage(Language.getString("wordCoordsPlayerOnly"));
- return true;
- }
-
- x = player.getLocation().getBlockX();
- z = player.getLocation().getBlockZ();
-
- encode = true;
- } else if (args.length > 1) {
- try {
- double dx = Double.parseDouble(args[0]);
- double dz = Double.parseDouble(args[args.length > 2 ? 2 : 1]);
-
- if (dx > Integer.MAX_VALUE || dx < Integer.MIN_VALUE || dz > Integer.MAX_VALUE || dz < Integer.MIN_VALUE) {
- sender.spigot().sendMessage(Language.getComponent("wordCoordsOutOfRange", ChatColor.RED));
- return true;
- }
-
- x = (int) dx;
- z = (int) dz;
-
- encode = true;
- } catch (NumberFormatException ignored) { }
- }
-
- if (encode) {
- words = converter.encode(x, z);
- String encoded = "///" + String.join(".", words);
-
- BaseComponent[] components = new ComponentBuilder()
- .append(String.format("%d, %d encodes to ", x, z))
- .color(ChatColor.GRAY)
- .append(encoded)
- .color(ChatColor.AQUA) // TODO improve color
- .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, encoded))
- .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Click to copy")))
- .create();
-
- sender.spigot().sendMessage(components);
- } else {
- String strArgs = String.join(" ", args);
- words = smartDetectWords(strArgs);
-
- if (words.length == 0) {
- sender.spigot().sendMessage(Language.getComponent("wordCoordsNoWords", ChatColor.GRAY));
- return true;
- }
-
- try {
- int[] xz = converter.decode(words);
- x = xz[0];
- z = xz[1];
- } catch (NoSuchElementException e) {
- sender.spigot().sendMessage(Language.getComponent("wordCoordsInvalidWord", ChatColor.RED, e.getMessage()));
- return true;
- }
-
- String encoded = "///" + String.join(".", words);
-
- BaseComponent[] components = new ComponentBuilder()
- .append(encoded + " decodes to ")
- .color(ChatColor.GRAY)
- .append("%d, %d".formatted(x, z))
- .color(ChatColor.AQUA) // TODO improve color
- .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, "%d, %d".formatted(x, z)))
- .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Click to copy")))
- .append(" ±8")
- .color(ChatColor.GRAY)
- .create();
- sender.spigot().sendMessage(components);
- }
-
- return true;
- }
-
- private String[] smartDetectWords(String str) {
- List words = new ArrayList<>();
- StringBuilder currentWord = new StringBuilder();
-
- for (int i=0; i wordList;
- private final int bitsPerWord;
-
- public WordList(List words) {
- this.wordList = words;
- this.bitsPerWord = 32 - Integer.numberOfLeadingZeros(words.size()) - 1;
- }
-
- public String getWord(int index) {
- return wordList.get(index);
- }
-
- public int getWordIndex(String word) {
- return wordList.indexOf(word);
- }
-
- public String[] getWords(int... indexes) {
- return Arrays.stream(indexes)
- .mapToObj(this::getWord)
- .toArray(String[]::new);
- }
-
- public int[] getIndexes(String... words) {
- return Arrays.stream(words)
- .mapToInt(wordList::indexOf)
- .toArray();
- }
-
- public int getWordCount() {
- return wordList.size();
- }
-
- public int getBitsPerWord() {
- return bitsPerWord;
- }
-
- public static WordList fromFile(Path path) throws IOException {
- try (var lines = Files.lines(path)) {
- var list = lines.filter(s -> !s.isBlank())
- .map(String::toLowerCase)
- .distinct()
- .toList();
-
- return new WordList(list);
- }
-
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java b/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java
deleted file mode 100644
index 65ff762..0000000
--- a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Decoder.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.wordcoords.converter;
-
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.wordcoords.WordList;
-
-import java.util.NoSuchElementException;
-import java.util.Arrays;
-
-public class Decoder {
- private final WordList wordList;
- private final int bitsPerWord;
-
- public Decoder(WordList wordList) {
- this.wordList = wordList;
- this.bitsPerWord = wordList.getBitsPerWord();
- }
-
- public int[] decode(String[] words) throws NoSuchElementException {
- int[] wordIndexes = new int[words.length];
-
- for (int i=0; i> bitsRequiredPerCoordinate) - coordinateOffset;
-
- return new int[] { x, z };
- }
-
-}
diff --git a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java b/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java
deleted file mode 100644
index 75d03e2..0000000
--- a/src/main/java/eu/m724/tweaks/module/wordcoords/converter/Encoder.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.wordcoords.converter;
-
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.wordcoords.WordList;
-import java.util.Arrays;
-public class Encoder {
- private final WordList wordList;
- private final int bitsPerWord;
-
- public Encoder(WordList wordList) {
- this.wordList = wordList;
- this.bitsPerWord = wordList.getBitsPerWord();
- }
-
- public String[] encode(int xCoord, int zCoord) {
- int chunkX = Math.floorDiv(xCoord, 16);
- int chunkZ = Math.floorDiv(zCoord, 16);
- DebugLogger.finer("Chunk: %d, %d", chunkX, chunkZ);
-
- // Calculate minimum bits required per coordinate based on range
- int bitsRequiredPerCoordinate = findBitsRequiredPerCoordinate(chunkX, chunkZ);
- int minTotalBits = bitsRequiredPerCoordinate * 2;
- DebugLogger.finer("Min bits required per coordinate: %d (total: %d)", bitsRequiredPerCoordinate, minTotalBits);
-
- // Calculate words required, ensuring total bits is sufficient and even
- int wordsRequired = 0;
- int actualTotalBits = 0;
- if (minTotalBits > 0) { // Avoid division by zero if bitsPerWord is 0, or log(0)
- wordsRequired = Math.ceilDiv(minTotalBits, bitsPerWord);
- actualTotalBits = wordsRequired * bitsPerWord;
- // Ensure total bits is sufficient
- while (actualTotalBits < minTotalBits) {
- wordsRequired++;
- actualTotalBits = wordsRequired * bitsPerWord;
- }
- } // else: coords are 0 or -1, minTotalBits=0, wordsRequired=0, actualTotalBits=0. Need special handling?
- // If x/z are 0/-1, findBitsRequired returns 1, minTotalBits=2. The loop handles it.
-
- // Final bits per coordinate based on words
- bitsRequiredPerCoordinate = actualTotalBits / 2;
- DebugLogger.finer("Final Words required: %d", wordsRequired);
- DebugLogger.finer("Final Bits required: %d (per coord: %d)", actualTotalBits, bitsRequiredPerCoordinate);
-
- int encodedX = encodeCoord(chunkX, bitsRequiredPerCoordinate);
- int encodedZ = encodeCoord(chunkZ, bitsRequiredPerCoordinate);
- DebugLogger.finer("Encoded coordinates: %d, %d", encodedX, encodedZ);
-
- long combinedValue = ((long) encodedX << bitsRequiredPerCoordinate) | encodedZ;
- DebugLogger.finer("Combined value: %d", combinedValue);
-
- int[] wordIndexes = combinedValueToWordIndexes(combinedValue, wordsRequired);
- DebugLogger.finer("Word indexes: %s", Arrays.toString(wordIndexes));
-
- return wordList.getWords(wordIndexes);
- }
-
- // Calculates the minimum number of bits required to represent the coordinate
- // using the encoding scheme (offset + coord) & mask, such that the coordinate
- // fits within the range [-(1 << (bits - 1)), (1 << (bits - 1)) - 1].
- private int findBitsRequiredPerCoordinate(int x, int z) {
- int maxVal = Math.max(x, z);
- int minVal = Math.min(x, z);
-
- // Determine the required positive magnitude for the encoding range's positive side.
- // We need `(1 << (bits - 1)) >= max(maxVal + 1, -minVal)`
- int requiredPositiveMagnitude = Math.max(maxVal + 1, -minVal);
-
- if (requiredPositiveMagnitude <= 0) {
- // Occurs only if maxVal <= -1 and minVal >= 0, which is impossible,
- // OR maxVal <= 0 and -minVal <= 0 => maxVal <= 0 and minVal >= 0.
- // This means x and z are both 0.
- // The range for 1 bit is [-1, 0]. If coords are 0, 1 bit is not enough for offset+coord.
- // Example: bits=1. offset=1<<0=1. mask=(1<<1)-1=1.
- // encodeCoord(0, 1) = (1+0)&1 = 1.
- // decodeCoord(1, 1): val=1. mask=1. offset=1. (1&1)-1 = 0. Correct.
- // What if we need to represent -1? encodeCoord(-1, 1) = (1-1)&1 = 0.
- // decodeCoord(0, 1): val=0. (0&1)-1 = -1. Correct.
- // So 1 bit works for range [-1, 0]. Let's check the condition:
- // x=0, z=0 -> maxVal=0, minVal=0. reqPosMag = max(1, 0) = 1.
- // x=-1, z=-1 -> maxVal=-1, minVal=-1. reqPosMag = max(0, 1) = 1.
- // x=0, z=-1 -> maxVal=0, minVal=-1. reqPosMag = max(1, 1) = 1.
- // So requiredPositiveMagnitude is 1 for the range [-1, 0].
- requiredPositiveMagnitude = 1; // Ensure it's at least 1 if coords are 0 or -1.
- }
-
- // Calculate p = bits - 1
- // We need the smallest integer p such that (1 << p) >= requiredPositiveMagnitude.
- // If requiredPositiveMagnitude = 1, we need 1 << p >= 1, smallest p is 0.
- // If requiredPositiveMagnitude > 1, this is equivalent to finding the number of bits
- // needed to represent (requiredPositiveMagnitude - 1) in binary.
- int p;
- if (requiredPositiveMagnitude == 1) {
- p = 0;
- } else {
- p = 32 - Integer.numberOfLeadingZeros(requiredPositiveMagnitude - 1);
- }
-
- // bits = p + 1
- return p + 1;
- }
-
- private int encodeCoord(int coord, int bitsRequiredPerCoordinate) {
- // Bitmask and offset for positive integer conversion
- int coordinateMask = (1 << bitsRequiredPerCoordinate) - 1;
- int coordinateOffset = 1 << (bitsRequiredPerCoordinate - 1);
-
- // Encode coordinates with offset into positive range
- return (coordinateOffset + coord) & coordinateMask;
- }
-
- private int[] combinedValueToWordIndexes(long combinedValue, int wordsRequired) {
- int bitsRequired = wordsRequired * bitsPerWord;
-
- // Break into word indexes
- int[] wordIndexes = new int[wordsRequired];
- int currentIndex = wordsRequired; // Start filling from end of array
-
- for (int remainingBits = bitsRequired; remainingBits > 0; remainingBits -= bitsPerWord) {
- int wordMask = (1 << bitsPerWord) - 1;
- wordIndexes[--currentIndex] = (int) (combinedValue & wordMask);
- combinedValue >>= bitsPerWord;
- }
-
- return wordIndexes;
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderHideModule.java b/src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderHideModule.java
deleted file mode 100644
index 52f90cd..0000000
--- a/src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderHideModule.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2025 Minecon724
- * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
- * in the project root for the full license text.
- */
-
-package eu.m724.tweaks.module.worldborder;
-
-import com.comphenix.protocol.PacketType;
-import com.comphenix.protocol.events.PacketContainer;
-import eu.m724.tweaks.module.TweaksModule;
-
-import java.nio.ByteBuffer;
-
-public class WorldBorderHideModule extends TweaksModule {
- private static final int EXTENSION_RADIUS = 512;
-
- @Override
- protected void onInit() {
- getPlugin().getServer().getMessenger().registerOutgoingPluginChannel(getPlugin(), "tweaks724:worldborder");
-
- byte[] infoArray = ByteBuffer.allocate(4).putInt(EXTENSION_RADIUS).array();
-
- onPacketSend(PacketType.Play.Server.INITIALIZE_BORDER, (event) -> {
- PacketContainer packet = event.getPacket();
- // old diameter
- packet.getDoubles().write(2, packet.getDoubles().read(2) + EXTENSION_RADIUS * 2);
- // new diameter
- packet.getDoubles().write(3, packet.getDoubles().read(3) + EXTENSION_RADIUS * 2);
-
- // border radius
- packet.getIntegers().write(0, packet.getIntegers().read(0) + EXTENSION_RADIUS);
- // warning distance
- packet.getIntegers().write(1, packet.getIntegers().read(1) + EXTENSION_RADIUS);
-
- event.getPlayer().sendPluginMessage(getPlugin(), "tweaks724:worldborder", infoArray);
- });
-
- onPacketSend(PacketType.Play.Server.SET_BORDER_SIZE, (event) -> {
- PacketContainer packet = event.getPacket();
- // diameter
- packet.getDoubles().write(0, packet.getDoubles().read(0) + EXTENSION_RADIUS * 2);
- });
-
- onPacketSend(PacketType.Play.Server.SET_BORDER_WARNING_DISTANCE, (event) -> {
- PacketContainer packet = event.getPacket();
- // warning distance
- packet.getIntegers().write(0, packet.getIntegers().read(0) + EXTENSION_RADIUS);
- });
- }
-}
diff --git a/src/main/java/eu/m724/tweaks/motd/MotdManager.java b/src/main/java/eu/m724/tweaks/motd/MotdManager.java
new file mode 100644
index 0000000..0ac9c79
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/motd/MotdManager.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2025 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.motd;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.ProtocolLibrary;
+import com.comphenix.protocol.events.*;
+import com.comphenix.protocol.reflect.StructureModifier;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+import eu.m724.tweaks.DebugLogger;
+import eu.m724.tweaks.TweaksConfig;
+import eu.m724.tweaks.TweaksPlugin;
+import net.md_5.bungee.api.chat.TextComponent;
+import net.md_5.bungee.chat.ComponentSerializer;
+import net.minecraft.SharedConstants;
+import net.minecraft.core.RegistryAccess;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.status.ServerStatus;
+import org.bukkit.plugin.Plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class MotdManager {
+ private final TweaksPlugin plugin;
+
+ private Component[] motds;
+
+ public MotdManager(TweaksPlugin plugin) {
+ this.plugin = plugin;
+ }
+
+ public void init() {
+ // TODO adding more MOTD features would require checking whether to enable set
+
+ String motdSetName = TweaksConfig.getConfig().motdSet();
+ String motdSetPath = "motd sets/" + motdSetName + ".txt";
+ File motdSetsFile = new File(plugin.getDataFolder(), motdSetPath);
+
+ // create "motd sets" directory
+ motdSetsFile.getParentFile().mkdirs();
+
+ // if this is a builtin set
+ if (!motdSetsFile.exists() && plugin.hasResource(motdSetPath))
+ plugin.saveResource(motdSetPath, false);
+
+ if (!motdSetsFile.exists()) {
+ throw new RuntimeException("MOTD set \"%s\" doesn't exist".formatted(motdSetName));
+ }
+
+ String fileContent = null;
+ try {
+ fileContent = Files.readString(motdSetsFile.toPath());
+ } catch (IOException e) {
+ throw new RuntimeException("Reading motd set", e);
+ }
+
+ // MOTDs are split with an empty line
+ motds = Arrays.stream(fileContent.split("\n\n"))
+ .map(entry -> {
+ entry = entry.strip();
+ JsonElement json = null;
+
+ try {
+ json = JsonParser.parseString(entry);
+ DebugLogger.fine("JSON line: " + entry);
+ } catch (JsonParseException e) {
+ DebugLogger.fine("Not a JSON line: " + entry);
+ }
+
+ if (json == null) {
+ json = ComponentSerializer.toJson(TextComponent.fromLegacy(entry));
+ }
+
+ return Component.Serializer.fromJson(json, RegistryAccess.EMPTY);
+ })
+ .toArray(Component[]::new);
+
+ registerListener(plugin);
+ }
+
+ private void registerListener(Plugin plugin) {
+ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
+ plugin,
+ ListenerPriority.NORMAL,
+ PacketType.Status.Server.SERVER_INFO
+ ) {
+ @Override
+ public void onPacketSending(PacketEvent event) {
+ PacketContainer packet = event.getPacket();
+
+ Component motd = motds[ThreadLocalRandom.current().nextInt(motds.length)];
+
+ ServerStatus serverStatus = (ServerStatus) packet.getStructures().read(0).getHandle();
+
+ /* this:
+ * removes server mod prefix (Paper, Spigot, any brand)
+ * hides players
+ */
+ ServerStatus newStatus = new ServerStatus(
+ motd,
+ Optional.empty(),
+ Optional.of(new ServerStatus.Version(
+ SharedConstants.getCurrentVersion().getName(),
+ SharedConstants.getProtocolVersion()
+ )),
+ serverStatus.favicon(),
+ false
+ );
+
+ packet.getStructures().write(0, new InternalStructure(newStatus, new StructureModifier<>(ServerStatus.class)));
+ }
+ });
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java b/src/main/java/eu/m724/tweaks/ping/F3NameListener.java
similarity index 97%
rename from src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java
rename to src/main/java/eu/m724/tweaks/ping/F3NameListener.java
index bf43d14..9577841 100644
--- a/src/main/java/eu/m724/tweaks/module/ping/F3NameListener.java
+++ b/src/main/java/eu/m724/tweaks/ping/F3NameListener.java
@@ -1,16 +1,16 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.ping;
+package eu.m724.tweaks.ping;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.*;
import com.comphenix.protocol.reflect.StructureModifier;
-import eu.m724.tweaks.config.TweaksConfig;
+import eu.m724.tweaks.TweaksConfig;
import net.minecraft.network.protocol.common.custom.BrandPayload;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
diff --git a/src/main/java/eu/m724/tweaks/module/ping/KeepAlivePingChecker.java b/src/main/java/eu/m724/tweaks/ping/KeepAlivePingChecker.java
similarity index 96%
rename from src/main/java/eu/m724/tweaks/module/ping/KeepAlivePingChecker.java
rename to src/main/java/eu/m724/tweaks/ping/KeepAlivePingChecker.java
index d88d340..45fa7bd 100644
--- a/src/main/java/eu/m724/tweaks/module/ping/KeepAlivePingChecker.java
+++ b/src/main/java/eu/m724/tweaks/ping/KeepAlivePingChecker.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.ping;
+package eu.m724.tweaks.ping;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
diff --git a/src/main/java/eu/m724/tweaks/module/ping/MsptChecker.java b/src/main/java/eu/m724/tweaks/ping/MsptChecker.java
similarity index 89%
rename from src/main/java/eu/m724/tweaks/module/ping/MsptChecker.java
rename to src/main/java/eu/m724/tweaks/ping/MsptChecker.java
index a030c2d..dec46a0 100644
--- a/src/main/java/eu/m724/tweaks/module/ping/MsptChecker.java
+++ b/src/main/java/eu/m724/tweaks/ping/MsptChecker.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.ping;
+package eu.m724.tweaks.ping;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
diff --git a/src/main/java/eu/m724/tweaks/module/ping/PingChecker.java b/src/main/java/eu/m724/tweaks/ping/PingChecker.java
similarity index 86%
rename from src/main/java/eu/m724/tweaks/module/ping/PingChecker.java
rename to src/main/java/eu/m724/tweaks/ping/PingChecker.java
index c1c61e6..41e95ab 100644
--- a/src/main/java/eu/m724/tweaks/module/ping/PingChecker.java
+++ b/src/main/java/eu/m724/tweaks/ping/PingChecker.java
@@ -1,14 +1,16 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.ping;
+package eu.m724.tweaks.ping;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.Plugin;
+import java.util.Objects;
+
public class PingChecker {
private final Plugin plugin;
diff --git a/src/main/java/eu/m724/tweaks/module/ping/PingCommands.java b/src/main/java/eu/m724/tweaks/ping/PingCommands.java
similarity index 94%
rename from src/main/java/eu/m724/tweaks/module/ping/PingCommands.java
rename to src/main/java/eu/m724/tweaks/ping/PingCommands.java
index 1e0f31d..01d9a1c 100644
--- a/src/main/java/eu/m724/tweaks/module/ping/PingCommands.java
+++ b/src/main/java/eu/m724/tweaks/ping/PingCommands.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.ping;
+package eu.m724.tweaks.ping;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
diff --git a/src/main/java/eu/m724/tweaks/module/ping/PlayerPingStorage.java b/src/main/java/eu/m724/tweaks/ping/PlayerPingStorage.java
similarity index 95%
rename from src/main/java/eu/m724/tweaks/module/ping/PlayerPingStorage.java
rename to src/main/java/eu/m724/tweaks/ping/PlayerPingStorage.java
index f8eb30c..f41285f 100644
--- a/src/main/java/eu/m724/tweaks/module/ping/PlayerPingStorage.java
+++ b/src/main/java/eu/m724/tweaks/ping/PlayerPingStorage.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.ping;
+package eu.m724.tweaks.ping;
import org.bukkit.entity.Player;
diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java b/src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java
new file mode 100644
index 0000000..3aba1be
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/pomodoro/PlayerPomodoro.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.pomodoro;
+
+public class PlayerPomodoro {
+ private int pomodori = 0;
+
+ private boolean isBreak = false;
+ // this is for both break and not break
+ private long intervalStart = -1;
+
+ /**
+ * A "pomodoro" is the 25-minute cycle you take breaks after
+ * This returns how many cycles already elapsed, so if this is the first cycle this is 0
+ * The break after the "pomodoro," so if it's breaktime after the first "pomodoro" it stays at 0
+ */
+ public int getPomodori() {
+ return pomodori;
+ }
+
+ /**
+ * When did the current interval start
+ * Or when did the break start
+ *
+ * @see PlayerPomodoro#isBreak()
+ */
+ public long getIntervalStart() {
+ return intervalStart;
+ }
+
+ public int getCycleDurationSeconds() {
+ return isBreak ? (pomodori < 3 ? 300 : 1200) : 1500;
+ }
+
+ public long getRemainingSeconds(long now) {
+ return getCycleDurationSeconds() - (now - getIntervalStart()) / 1000000000;
+ }
+
+ /**
+ * Is it a break currently
+ */
+ public boolean isBreak() {
+ return isBreak;
+ }
+
+ public boolean isCycleComplete() {
+ return intervalStart + getCycleDurationSeconds() * 1000000000L < System.nanoTime();
+ }
+
+ /**
+ * Resets and starts the timer
+ */
+ public void start() {
+ this.pomodori = 0;
+ this.isBreak = false;
+ this.intervalStart = System.nanoTime();
+ }
+
+ /**
+ * Completes a cycle
+ */
+ public void next() {
+ if (isBreak) { // from break to interval
+ this.pomodori++;
+ this.pomodori %= 4;
+ }
+
+ this.intervalStart = System.nanoTime();
+ isBreak = !isBreak;
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroCommands.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroCommands.java
new file mode 100644
index 0000000..fc5af95
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroCommands.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.pomodoro;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class PomodoroCommands implements CommandExecutor {
+ @Override
+ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
+ Player player = (Player) sender;
+ String action = args.length > 0 ? args[0] : null;
+
+ PlayerPomodoro pomodoro = Pomodoros.get(player);
+
+ if (pomodoro != null) {
+ if ("stop".equals(action)) {
+ Pomodoros.remove(player);
+ sender.sendMessage("Pomodoro disabled");
+ } else {
+ if (pomodoro.isCycleComplete()) {
+ pomodoro.next();
+ }
+ sender.spigot().sendMessage(Pomodoros.formatTimer(pomodoro, pomodoro.getRemainingSeconds(System.nanoTime())));
+ }
+ } else {
+ if ("start".equals(action)) {
+ pomodoro = Pomodoros.create(player);
+ pomodoro.start();
+ sender.spigot().sendMessage(Pomodoros.formatTimer(pomodoro, pomodoro.getCycleDurationSeconds()));
+ } else {
+ sender.sendMessage("Start pomodoro with /pom start");
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java
new file mode 100644
index 0000000..9859e64
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroListener.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.pomodoro;
+
+import eu.m724.tweaks.TweaksConfig;
+import net.md_5.bungee.api.chat.ComponentBuilder;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.*;
+
+public class PomodoroListener implements Listener {
+ private final boolean force = TweaksConfig.getConfig().pomodoroForce();
+
+ @EventHandler
+ public void onPlayerLogin(PlayerLoginEvent event) {
+ Player player = event.getPlayer();
+ PlayerPomodoro pomodoro = Pomodoros.get(player);
+ if (pomodoro == null) return;
+
+ long remaining = pomodoro.getRemainingSeconds(System.nanoTime());
+
+ if (pomodoro.isBreak()) {
+ if (pomodoro.isCycleComplete()) {
+ pomodoro.next();
+ } else {
+ if (force) {
+ event.getPlayer().kickPlayer(
+ new ComponentBuilder()
+ .append(Pomodoros.formatTimer(pomodoro, remaining))
+ .build().toLegacyText()
+ );
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void onPlayerQuit(PlayerQuitEvent event) {
+ Player player = event.getPlayer();
+ PlayerPomodoro pomodoro = Pomodoros.get(player);
+ if (pomodoro == null) return;
+
+ if (!pomodoro.isBreak() && pomodoro.isCycleComplete()) {
+ pomodoro.next();
+ }
+ }
+
+ @EventHandler
+ public void onPlayerMove(PlayerMoveEvent event) {
+ Player player = event.getPlayer();
+ PlayerPomodoro timer = Pomodoros.get(player);
+ if (timer == null) return;
+
+ if (timer.isBreak() && timer.getRemainingSeconds(System.nanoTime()) <= 0)
+ timer.next(); // resume timer if break ended
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java
new file mode 100644
index 0000000..0483042
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroManager.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.pomodoro;
+
+import org.bukkit.command.PluginCommand;
+import org.bukkit.plugin.Plugin;
+
+public class PomodoroManager {
+ private final Plugin plugin;
+
+ public PomodoroManager(Plugin plugin) {
+ this.plugin = plugin;
+ }
+
+ public void init(PluginCommand pomodoroCommand) {
+ plugin.getServer().getPluginManager().registerEvents(new PomodoroListener(), plugin);
+ new PomodoroRunnable(plugin).runTaskTimerAsynchronously(plugin, 0, 20L);
+
+ pomodoroCommand.setExecutor(new PomodoroCommands());
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java
new file mode 100644
index 0000000..3f28def
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/pomodoro/PomodoroRunnable.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.pomodoro;
+
+import eu.m724.tweaks.TweaksConfig;
+import net.md_5.bungee.api.ChatMessageType;
+import org.bukkit.Bukkit;
+import org.bukkit.Sound;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class PomodoroRunnable extends BukkitRunnable {
+ private final boolean force = TweaksConfig.getConfig().pomodoroForce();
+ private final Plugin plugin;
+
+ public PomodoroRunnable(Plugin plugin) {
+ this.plugin = plugin; // only used for kicking
+ }
+
+ @Override
+ public void run() {
+ long now = System.nanoTime();
+ Bukkit.getOnlinePlayers().forEach(player -> {
+ PlayerPomodoro pomodoro = Pomodoros.get(player);
+ if (pomodoro == null) return;
+
+ long remaining = pomodoro.getRemainingSeconds(now);
+ // TODO make not always on
+ player.spigot().sendMessage(ChatMessageType.ACTION_BAR, Pomodoros.formatTimer(pomodoro, remaining));
+
+ if (remaining <= 0) {
+ player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1.0f, 0.5f);
+ if (remaining < -60 && force) {
+ plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {
+ pomodoro.next();
+ player.kickPlayer(Pomodoros.formatTimer(pomodoro, pomodoro.getRemainingSeconds(now)).toLegacyText());
+ });
+ }
+ }
+ });
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java b/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java
new file mode 100644
index 0000000..10044f9
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/pomodoro/Pomodoros.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.pomodoro;
+
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.chat.BaseComponent;
+import net.md_5.bungee.api.chat.ComponentBuilder;
+import org.bukkit.entity.Player;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class Pomodoros {
+ static final Map timers = new HashMap<>();
+
+ public static PlayerPomodoro get(Player player) {
+ return timers.get(player.getUniqueId());
+ }
+
+ public static PlayerPomodoro create(Player player) {
+ return timers.computeIfAbsent(player.getUniqueId(), (k) -> new PlayerPomodoro());
+ }
+
+ public static boolean remove(Player player) {
+ return timers.remove(player.getUniqueId()) != null;
+ }
+
+ static BaseComponent formatTimer(PlayerPomodoro pomodoro, long remaining) {
+ ComponentBuilder builder = new ComponentBuilder();
+
+ if (pomodoro.isBreak()) {
+ builder.append("Break ").color(ChatColor.LIGHT_PURPLE);
+ if (remaining > 0) {
+ builder.append("%02d:%02d".formatted(remaining / 60, remaining % 60))
+ .color(ChatColor.GOLD);
+ } else {
+ builder.append("00:00")
+ .color(ChatColor.GREEN);
+ }
+ } else {
+ if (remaining > 0) {
+ builder
+ .append("%02d:%02d".formatted(remaining / 60, remaining % 60))
+ .color(ChatColor.GRAY);
+ } else {
+ builder
+ .append("00:00")
+ .color(remaining % 2 == 0 ? ChatColor.RED : ChatColor.YELLOW);
+ }
+ }
+
+
+ for (int i=0; i<4; i++) {
+ ChatColor color = ChatColor.GRAY;
+ if (i == pomodoro.getPomodori()) {
+ color = ChatColor.LIGHT_PURPLE;
+ } else if (i > pomodoro.getPomodori()) {
+ color = ChatColor.DARK_GRAY;
+ }
+
+ builder.append(" o").color(color);
+ }
+
+ return builder.build();
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/redstone/GatewayItem.java b/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java
similarity index 77%
rename from src/main/java/eu/m724/tweaks/module/redstone/GatewayItem.java
rename to src/main/java/eu/m724/tweaks/redstone/GatewayItem.java
index 29863dc..5d24f05 100644
--- a/src/main/java/eu/m724/tweaks/module/redstone/GatewayItem.java
+++ b/src/main/java/eu/m724/tweaks/redstone/GatewayItem.java
@@ -1,12 +1,11 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.redstone;
+package eu.m724.tweaks.redstone;
-import eu.m724.tweaks.DebugLogger;
import eu.m724.tweaks.Language;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
@@ -19,21 +18,14 @@ public class GatewayItem {
private final NamespacedKey gatewayKey;
public GatewayItem(Plugin plugin) {
- var start = System.nanoTime();
-
this.gatewayKey = new NamespacedKey(plugin, "gateway");
- var recipe = new ShapelessRecipe(gatewayKey, itemStack());
- // this takes a long time for some reason. The first one especially
- // do this somewhere off measure to JIT and skew the measurement: new RecipeChoice.MaterialChoice(Material.DIRT);
+ var recipe = new ShapelessRecipe(gatewayKey, itemStack());
recipe.addIngredient(Material.NETHER_STAR);
recipe.addIngredient(Material.ENDER_CHEST);
recipe.addIngredient(Material.CHORUS_FLOWER);
recipe.addIngredient(Material.DAYLIGHT_DETECTOR);
-
plugin.getServer().addRecipe(recipe);
-
- DebugLogger.finer("Adding the recipe took %d ms, which is a long time", (System.nanoTime() - start) / 1000000);
}
public ItemStack itemStack() {
diff --git a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneCommands.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java
similarity index 95%
rename from src/main/java/eu/m724/tweaks/module/redstone/RedstoneCommands.java
rename to src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java
index c489a8e..f1c6b28 100644
--- a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneCommands.java
+++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneCommands.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.redstone;
+package eu.m724.tweaks.redstone;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
diff --git a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneGateways.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneGateways.java
similarity index 98%
rename from src/main/java/eu/m724/tweaks/module/redstone/RedstoneGateways.java
rename to src/main/java/eu/m724/tweaks/redstone/RedstoneGateways.java
index 9f17572..d7ae10f 100644
--- a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneGateways.java
+++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneGateways.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.redstone;
+package eu.m724.tweaks.redstone;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
diff --git a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneListener.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java
similarity index 97%
rename from src/main/java/eu/m724/tweaks/module/redstone/RedstoneListener.java
rename to src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java
index 0e1abfa..bff3c1e 100644
--- a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneListener.java
+++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneListener.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.redstone;
+package eu.m724.tweaks.redstone;
import eu.m724.tweaks.DebugLogger;
import eu.m724.tweaks.Language;
diff --git a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java
similarity index 75%
rename from src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java
rename to src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java
index b574786..2dde5bc 100644
--- a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java
+++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneManager.java
@@ -1,36 +1,43 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.redstone;
+package eu.m724.tweaks.redstone;
import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.config.TweaksConfig;
-import eu.m724.tweaks.module.TweaksModule;
+import eu.m724.tweaks.TweaksConfig;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.plugin.Plugin;
import java.io.IOException;
import java.net.*;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
-public class RedstoneModule extends TweaksModule {
- private final RedstoneGateways redstoneGateways = new RedstoneGateways(getPlugin());
+public class RedstoneManager {
+ private final Plugin plugin;
+ private final RedstoneGateways redstoneGateways;
private DatagramSocket socket;
private RedstoneStateUpdateRunnable runnable;
- @Override
- protected void onInit() {
- RedstoneStore.init(getPlugin());
- var gatewayItem = new GatewayItem(getPlugin());
- registerEvents(new RedstoneListener(redstoneGateways, gatewayItem));
- registerCommand("retstone", new RedstoneCommands(gatewayItem));
+ public RedstoneManager(Plugin plugin) {
+ this.plugin = plugin;
+ this.redstoneGateways = new RedstoneGateways(plugin);
+ }
+
+ public void init(PluginCommand command) {
+ RedstoneStore.init(plugin);
+ var gatewayItem = new GatewayItem(plugin);
+
+ plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneGateways, gatewayItem), plugin);
+ command.setExecutor(new RedstoneCommands(gatewayItem));
this.runnable = new RedstoneStateUpdateRunnable(redstoneGateways);
- this.runnable.runTaskTimer(getPlugin(), 0, 20); // TODO configurable
+ this.runnable.runTaskTimer(plugin, 0, 20); // TODO configurable
var listenAddress = TweaksConfig.getConfig().redstoneListen().split(":");
InetSocketAddress bindAddress;
@@ -45,6 +52,7 @@ public class RedstoneModule extends TweaksModule {
} catch (SocketException e) {
throw new RuntimeException("Starting socket", e);
}
+
}
private void initSocket(SocketAddress bindAddress) throws SocketException {
@@ -88,12 +96,12 @@ public class RedstoneModule extends TweaksModule {
}
private void enqueueUpdate(int gatewayId, byte power) {
- DebugLogger.finer("Update enqueued " + gatewayId + " " + power);
+ DebugLogger.fine("Update enqueued " + gatewayId + " " + power);
runnable.enqueueUpdate(gatewayId, power);
}
private void enqueueRetrieve(int gatewayId, Consumer consumer) {
- DebugLogger.finer("Retrieve enqueued " + gatewayId);
+ DebugLogger.fine("Retrieve enqueued " + gatewayId);
runnable.enqueueRetrieve(gatewayId, consumer);
}
}
diff --git a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneStateUpdateRunnable.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java
similarity index 94%
rename from src/main/java/eu/m724/tweaks/module/redstone/RedstoneStateUpdateRunnable.java
rename to src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java
index 2ab5410..f036f49 100644
--- a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneStateUpdateRunnable.java
+++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneStateUpdateRunnable.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.redstone;
+package eu.m724.tweaks.redstone;
import org.bukkit.scheduler.BukkitRunnable;
diff --git a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneStore.java b/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java
similarity index 96%
rename from src/main/java/eu/m724/tweaks/module/redstone/RedstoneStore.java
rename to src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java
index 3b2bc38..8c812ea 100644
--- a/src/main/java/eu/m724/tweaks/module/redstone/RedstoneStore.java
+++ b/src/main/java/eu/m724/tweaks/redstone/RedstoneStore.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.redstone;
+package eu.m724.tweaks.redstone;
import com.google.common.primitives.Ints;
import eu.m724.tweaks.DebugLogger;
diff --git a/src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java
similarity index 57%
rename from src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java
rename to src/main/java/eu/m724/tweaks/sleep/SleepListener.java
index b1d0f85..6e0c23c 100644
--- a/src/main/java/eu/m724/tweaks/module/sleep/SleepListener.java
+++ b/src/main/java/eu/m724/tweaks/sleep/SleepListener.java
@@ -1,14 +1,14 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.sleep;
+package eu.m724.tweaks.sleep;
-import eu.m724.tweaks.config.TweaksConfig;
+import eu.m724.tweaks.TweaksConfig;
import org.bukkit.GameRule;
-import org.bukkit.attribute.Attribute;
+import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -21,7 +21,6 @@ import java.util.Set;
public class SleepListener implements Listener {
private final boolean instant = TweaksConfig.getConfig().sleepInstant();
- private final double heal = TweaksConfig.getConfig().sleepHeal() * 2; // hearts to half hearts
private final Set skippedCurrentNight = new HashSet<>();
private long lastDay = 0;
@@ -31,21 +30,18 @@ public class SleepListener implements Listener {
if (event.getBedEnterResult() == PlayerBedEnterEvent.BedEnterResult.OK) {
SleepState.playersSleeping++;
- var player = event.getPlayer();
- var world = player.getWorld();
+ if (instant) {
+ World world = event.getPlayer().getWorld();
- long day = world.getFullTime() / 24000;
- if (day != lastDay) skippedCurrentNight.clear();
- lastDay = day;
+ long day = world.getFullTime() / 24000;
+ if (day != lastDay) skippedCurrentNight.clear();
+ lastDay = day;
- if (skippedCurrentNight.add(player)) {
- if (instant) {
- double onePlayerRatio = 1 / (player.getServer().getOnlinePlayers().size() * (world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE) / 100.0));
+ if (!skippedCurrentNight.contains(event.getPlayer())) {
+ double onePlayerRatio = 1 / (event.getPlayer().getServer().getOnlinePlayers().size() * (world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE) / 100.0));
world.setTime(Math.min(world.getTime() + (long) (10917 * onePlayerRatio), 23459));
+ skippedCurrentNight.add(event.getPlayer());
}
-
- var maxHealth = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue();
- player.setHealth(Math.min(player.getHealth() + heal, maxHealth));
}
}
@@ -57,9 +53,8 @@ public class SleepListener implements Listener {
}
@EventHandler
- public void onTimeSkip(TimeSkipEvent event) {
- if (event.getSkipReason() == TimeSkipEvent.SkipReason.NIGHT_SKIP) {
+ public void onPlayerBedLeave(TimeSkipEvent event) {
+ if (event.getSkipReason() == TimeSkipEvent.SkipReason.NIGHT_SKIP)
event.setCancelled(true);
- }
}
}
diff --git a/src/main/java/eu/m724/tweaks/sleep/SleepManager.java b/src/main/java/eu/m724/tweaks/sleep/SleepManager.java
new file mode 100644
index 0000000..2aec5cf
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/sleep/SleepManager.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.sleep;
+
+import eu.m724.tweaks.TweaksConfig;
+import org.bukkit.plugin.Plugin;
+
+public class SleepManager {
+ public void init(Plugin plugin) {
+ plugin.getServer().getPluginManager().registerEvents(new SleepListener(), plugin);
+ if (!TweaksConfig.getConfig().sleepInstant())
+ new TimeForwardRunnable(plugin).runTaskTimer(plugin, 0, 1); // TODO maybe not
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/sleep/SleepState.java b/src/main/java/eu/m724/tweaks/sleep/SleepState.java
similarity index 74%
rename from src/main/java/eu/m724/tweaks/module/sleep/SleepState.java
rename to src/main/java/eu/m724/tweaks/sleep/SleepState.java
index e8f0991..f810e9e 100644
--- a/src/main/java/eu/m724/tweaks/module/sleep/SleepState.java
+++ b/src/main/java/eu/m724/tweaks/sleep/SleepState.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.sleep;
+package eu.m724.tweaks.sleep;
public class SleepState {
static int playersSleeping;
diff --git a/src/main/java/eu/m724/tweaks/sleep/TimeForwardRunnable.java b/src/main/java/eu/m724/tweaks/sleep/TimeForwardRunnable.java
new file mode 100644
index 0000000..41f91d5
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/sleep/TimeForwardRunnable.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.sleep;
+
+import org.bukkit.GameRule;
+import org.bukkit.Server;
+import org.bukkit.World;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class TimeForwardRunnable extends BukkitRunnable {
+ private final Server server;
+ private final World world; // TODO multi worlds
+
+ private final double percentage;
+
+ public TimeForwardRunnable(Plugin plugin) {
+ this.server = plugin.getServer();
+ this.world = server.getWorld("world");
+ this.percentage = (world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE) / 100.0);
+ }
+
+ @Override
+ public void run() {
+ int playersSleeping = SleepState.playersSleeping;
+ //System.out.println(playersSleeping);
+ if (playersSleeping == 0) return;
+
+ int onlinePlayers = (int) (server.getOnlinePlayers().size() / percentage); // TODO optimize remove size every tick maybe
+
+ double sleepPercentage = (double) playersSleeping / onlinePlayers;
+
+ // we want sleep to take 200 ticks which is 10 seconds assuming all palyres onilien
+
+ long time = world.getTime();
+ long untilDay = 23459 - time;
+
+ if (untilDay == 0) return;
+
+ long perSkip = 200 + (100000 / -untilDay);
+ perSkip = Math.clamp(perSkip, 20, 200);
+ perSkip = (long) (perSkip * sleepPercentage);
+
+ world.setTime(world.getTime() + perSkip);
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/updater/PluginScanner.java b/src/main/java/eu/m724/tweaks/updater/PluginScanner.java
new file mode 100644
index 0000000..a437b1c
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/updater/PluginScanner.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.updater;
+
+import eu.m724.tweaks.updater.cache.SpigotResource;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.plugin.Plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+public class PluginScanner {
+ private final Plugin thisPlugin;
+
+ PluginScanner(Plugin thisPlugin) {
+ this.thisPlugin = thisPlugin;
+ }
+
+ public Set load() throws IOException {
+ File installedPluginsYml = new File(thisPlugin.getDataFolder(), "installed_plugins.yml");
+
+ if (!installedPluginsYml.exists()) {
+ thisPlugin.saveResource("installed_plugins.yml", false);
+ }
+
+ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(installedPluginsYml);
+
+
+ Plugin[] plugins = thisPlugin.getServer().getPluginManager().getPlugins();
+ Set spigotResources = new HashSet<>();
+
+ for (Plugin plugin : plugins) {
+ String pluginName = plugin.getName();
+
+ if (!configuration.isSet(pluginName)) {
+ configuration.set(pluginName, -1);
+ continue;
+ }
+
+ int pluginId = configuration.getInt(pluginName);
+ if (pluginId > 0) {
+ spigotResources.add(
+ new SpigotResource(plugin, pluginId, pluginName)
+ );
+ }
+ }
+
+ configuration.save(installedPluginsYml);
+
+ return spigotResources;
+
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java
similarity index 50%
rename from src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java
rename to src/main/java/eu/m724/tweaks/updater/UpdateChecker.java
index 92afcb1..2687e32 100644
--- a/src/main/java/eu/m724/tweaks/module/updater/backend/UpdateChecker.java
+++ b/src/main/java/eu/m724/tweaks/updater/UpdateChecker.java
@@ -1,115 +1,89 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.updater.backend;
+package eu.m724.tweaks.updater;
import eu.m724.tweaks.DebugLogger;
import eu.m724.tweaks.Language;
-import eu.m724.tweaks.module.updater.object.VersionedResource;
+import eu.m724.tweaks.updater.cache.VersionedResource;
import org.bukkit.scheduler.BukkitRunnable;
-import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.time.LocalTime;
+import java.time.ZoneOffset;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletionException;
-import java.util.logging.Logger;
import java.util.stream.Collectors;
public class UpdateChecker extends BukkitRunnable {
- private final Logger logger;
- private final File cacheFile;
private final Set resources;
- private final Set availableUpdates = new HashSet<>();
- private long lastChecked = -1;
+ static final Set availableUpdates = new HashSet<>();
+ static LocalTime lastChecked = null;
- public UpdateChecker(Logger logger, File cacheFile, Set resources) {
- this.logger = logger;
- this.cacheFile = cacheFile;
+ UpdateChecker(Set resources) {
this.resources = resources; // TODO make a copy?
}
private void checkAll() {
- DebugLogger.fine("Checking for updates");
- lastChecked = System.currentTimeMillis();
+ //logger.info("Checking for updates");
+ lastChecked = LocalTime.now(ZoneOffset.UTC);
availableUpdates.clear();
- var errors = 0;
for (VersionedResource versionedResource : Set.copyOf(resources)) {
String pluginName = versionedResource.resource().plugin().getName();
+ //logger.info(versionedResource.resource().resourceId() + " " + versionedResource.resource().plugin().getName());
int page = versionedResource.running() != null ? versionedResource.running().page() : 1;
try {
- VersionedResource newResource = new VersionScanner(versionedResource.resource(), page).join(); // this runs async so it's ok
+ VersionedResource newResource = new VersionFinder(versionedResource.resource(), page).join(); // this runs async so it's ok
if (!versionedResource.equals(newResource)) {
resources.remove(versionedResource);
-
if (newResource.running() == null) {
- var pluginVersion = versionedResource.resource().plugin().getDescription().getVersion();
- var message = "";
-
- if (pluginVersion.endsWith("-SNAPSHOT")) {
- message = "Is it a development build?";
- } else if (versionedResource.running() != null) {
- message = "Did you downgrade it? If so, clear cache (delete Tweaks724/storage/cache/updater)";
+ DebugLogger.info("Unable to find installed version of %s".formatted(pluginName));
+ if (versionedResource.running() != null) {
+ DebugLogger.info("Did you downgrade %s? If so, clear cache".formatted(pluginName));
}
-
- DebugLogger.warning("This version of %s doesn't exist on SpigotMC. %s", pluginName, message);
- errors++;
} else {
if (!newResource.running().equals(newResource.latest())) {
availableUpdates.add(newResource);
+ //logger.info("Update available for %s. %d -> %d".formatted(pluginName, newResource.running().updateId(), newResource.latest().updateId()));
}
}
-
resources.add(newResource);
}
} catch (CompletionException e) {
DebugLogger.severe("Unable to refresh %s: %s".formatted(pluginName, e.getMessage()));
}
}
-
- if (errors > 0) {
- DebugLogger.info("To disable the updater for specific plugins, refer to updater_config.yml");
- }
}
private void alert() {
int n = availableUpdates.size();
if (n == 0) return;
- logger.info(Language.getString("updateAvailableNotice", n));
+ DebugLogger.info(Language.getString("updateAvailableNotice", n));
availableUpdates.stream()
.map(u -> "- %s (%s -> %s)".formatted(u.resource().name(), u.running().label(), u.latest().label()))
- .forEach(logger::info);
+ .forEach(DebugLogger::info);
}
@Override
public void run() {
checkAll();
- DebugLogger.finer("Done checking, now saving");
- cacheFile.getParentFile().mkdirs();
- try (FileOutputStream outputStream = new FileOutputStream(cacheFile)) {
- VersionCache.writeAll(outputStream, resources.stream().map(VersionedResource::running).filter(Objects::nonNull).collect(Collectors.toSet()));
+ try (FileOutputStream outputStream = new FileOutputStream(UpdaterManager.cacheFile)) {
+ VersionCheckCache.writeAll(outputStream, resources.stream().map(VersionedResource::running).filter(Objects::nonNull).collect(Collectors.toSet()));
} catch (IOException e) {
throw new RuntimeException(e);
}
alert();
}
-
- public long getLastChecked() {
- return lastChecked;
- }
-
- public Set getAvailableUpdates() {
- return availableUpdates;
- }
}
diff --git a/src/main/java/eu/m724/tweaks/module/updater/UpdaterCommands.java b/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java
similarity index 78%
rename from src/main/java/eu/m724/tweaks/module/updater/UpdaterCommands.java
rename to src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java
index 8e399be..46b7c9e 100644
--- a/src/main/java/eu/m724/tweaks/module/updater/UpdaterCommands.java
+++ b/src/main/java/eu/m724/tweaks/updater/UpdaterCommands.java
@@ -1,14 +1,13 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.updater;
+package eu.m724.tweaks.updater;
import eu.m724.tweaks.Language;
-import eu.m724.tweaks.module.updater.backend.UpdateChecker;
-import eu.m724.tweaks.module.updater.object.VersionedResource;
+import eu.m724.tweaks.updater.cache.VersionedResource;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
@@ -21,25 +20,18 @@ import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
-import java.time.Instant;
import java.time.format.DateTimeFormatter;
public class UpdaterCommands implements CommandExecutor {
- private final UpdateChecker updateChecker;
-
- public UpdaterCommands(UpdateChecker updateChecker) {
- this.updateChecker = updateChecker;
- }
-
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
- var lastChecked = updateChecker.getLastChecked();
- if (updateChecker.getLastChecked() == -1) {
+ if (UpdateChecker.lastChecked == null) {
sender.sendMessage(Language.getString("updatesNotChecked"));
return true;
}
- int n = updateChecker.getAvailableUpdates().size();
+ String lastChecked = UpdateChecker.lastChecked.format(DateTimeFormatter.ofPattern("HH:mm"));
+ int n = UpdateChecker.availableUpdates.size();
if (n > 0) {
sender.spigot().sendMessage(
@@ -47,14 +39,13 @@ public class UpdaterCommands implements CommandExecutor {
);
int i = 0;
- for (VersionedResource v : updateChecker.getAvailableUpdates()) {
+ for (VersionedResource v : UpdateChecker.availableUpdates) {
sender.spigot().sendMessage(
new ComponentBuilder(++i + ". ").color(ChatColor.GRAY).build(), resourceToBaseComponent(v)
);
}
} else {
- var lastCheckedFormat = DateTimeFormatter.ofPattern("HH:mm").format(Instant.ofEpochMilli(lastChecked));
- sender.spigot().sendMessage(Language.getComponent("updatesNoUpdates", ChatColor.GREEN, lastCheckedFormat));
+ sender.spigot().sendMessage(Language.getComponent("updatesNoUpdates", ChatColor.GREEN, lastChecked));
}
return true;
diff --git a/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java
new file mode 100644
index 0000000..f62bd19
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/updater/UpdaterManager.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2025 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.updater;
+
+import eu.m724.tweaks.DebugLogger;
+import eu.m724.tweaks.updater.cache.ResourceVersion;
+import eu.m724.tweaks.updater.cache.SpigotResource;
+import eu.m724.tweaks.updater.cache.VersionedResource;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.plugin.Plugin;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class UpdaterManager {
+ static File cacheFile;
+
+ private final Plugin plugin;
+
+ public UpdaterManager(Plugin plugin) {
+ this.plugin = plugin;
+ cacheFile = new File(plugin.getDataFolder(), "storage/cache/updater");
+ }
+
+ public void init(PluginCommand updatesCommand){
+ // scan installed plugins
+ Set resources = null;
+ try {
+ resources = new PluginScanner(plugin).load();
+ } catch (IOException e) {
+ throw new RuntimeException("Loading plugins", e);
+ }
+
+ cacheFile.getParentFile().mkdirs(); // TODO move this somewhere else
+
+ // load installed versions from cache
+ Set installedVersions;
+ try (FileInputStream inputStream = new FileInputStream(cacheFile)) {
+ installedVersions = VersionCheckCache.loadAll(inputStream);
+ } catch (FileNotFoundException e) {
+ installedVersions = new HashSet<>();
+ } catch (IOException e) {
+ DebugLogger.warning("Error loading installed version cache, starting fresh. " + e.getMessage());
+ installedVersions = new HashSet<>();
+ }
+
+ final Set ivf = installedVersions;
+ Set versionedResources = resources.stream()
+ .map(res -> new VersionedResource(
+ res, ivf.stream().filter(iv -> iv.resourceId() == res.resourceId()).findFirst().orElse(null), null
+ )).collect(Collectors.toSet());
+
+
+ new UpdateChecker(versionedResources)
+ .runTaskTimerAsynchronously(plugin, 600, 12 * 3600 * 20);
+
+ updatesCommand.setExecutor(new UpdaterCommands());
+ }
+}
diff --git a/src/main/java/eu/m724/tweaks/module/updater/backend/VersionCache.java b/src/main/java/eu/m724/tweaks/updater/VersionCheckCache.java
similarity index 94%
rename from src/main/java/eu/m724/tweaks/module/updater/backend/VersionCache.java
rename to src/main/java/eu/m724/tweaks/updater/VersionCheckCache.java
index e6952ad..7bc9b44 100644
--- a/src/main/java/eu/m724/tweaks/module/updater/backend/VersionCache.java
+++ b/src/main/java/eu/m724/tweaks/updater/VersionCheckCache.java
@@ -1,12 +1,12 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.updater.backend;
+package eu.m724.tweaks.updater;
-import eu.m724.tweaks.module.updater.object.ResourceVersion;
+import eu.m724.tweaks.updater.cache.ResourceVersion;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -15,7 +15,7 @@ import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;
-public class VersionCache {
+public class VersionCheckCache {
private static final byte FILE_VERSION = 1;
public static Set loadAll(FileInputStream inputStream) throws IOException {
diff --git a/src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java b/src/main/java/eu/m724/tweaks/updater/VersionFinder.java
similarity index 72%
rename from src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java
rename to src/main/java/eu/m724/tweaks/updater/VersionFinder.java
index 2eabcea..35676ef 100644
--- a/src/main/java/eu/m724/tweaks/module/updater/backend/VersionScanner.java
+++ b/src/main/java/eu/m724/tweaks/updater/VersionFinder.java
@@ -1,20 +1,19 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.updater.backend;
+package eu.m724.tweaks.updater;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
-import eu.m724.tweaks.DebugLogger;
-import eu.m724.tweaks.module.updater.object.SpigotResource;
-import eu.m724.tweaks.module.updater.object.ResourceVersion;
-import eu.m724.tweaks.module.updater.object.UpdateDescription;
-import eu.m724.tweaks.module.updater.object.VersionedResource;
+import eu.m724.tweaks.updater.cache.SpigotResource;
+import eu.m724.tweaks.updater.cache.ResourceVersion;
+import eu.m724.tweaks.updater.cache.UpdateDescription;
+import eu.m724.tweaks.updater.cache.VersionedResource;
import java.net.URI;
import java.net.URISyntaxException;
@@ -27,24 +26,23 @@ import java.util.concurrent.Executors;
// TODO optimize
-public class VersionScanner extends CompletableFuture {
+public class VersionFinder extends CompletableFuture {
private final SpigotResource resource;
private final int fromPage;
- VersionScanner(SpigotResource resource, int fromPage) {
+ VersionFinder(SpigotResource resource, int fromPage) {
this.resource = resource;
this.fromPage = fromPage;
start();
}
- VersionScanner(SpigotResource resource) {
+ VersionFinder(SpigotResource resource) {
this(resource, 1);
}
private void start() {
- DebugLogger.finer("Scanning %s (#%d) from page %d", resource.name(), resource.resourceId(), fromPage);
-
+ //System.out.printf("STarting for %d %s\n", resource.resourceId(), resource.plugin().getName());
try (ExecutorService executor = Executors.newSingleThreadExecutor()) {
executor.execute(() -> {
try {
@@ -53,14 +51,13 @@ public class VersionScanner extends CompletableFuture {
int page;
for (page = fromPage; page < 1000; page++) {
- DebugLogger.finer("Scan %s now at page %d", resource.name(), page);
-
+ //System.out.println("Page " + page);
String url = "https://api.spigotmc.org/simple/0.2/index.php?action=getResourceUpdates&page=%d&id=%d".formatted(page, resource.resourceId());
HttpRequest request;
try {
request = HttpRequest.newBuilder(new URI(url))
- .header("User-Agent", "twu/1") // tweaks updater v1
+ .header("User-Agent", "twu/1")
.build();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
@@ -71,7 +68,6 @@ public class VersionScanner extends CompletableFuture {
String body = response.body();
if (body.isBlank()) {
- DebugLogger.finer("Body is blank, stopping");
page--;
break;
}
@@ -79,7 +75,15 @@ public class VersionScanner extends CompletableFuture {
JsonArray jsonArray = JsonParser.parseString(body).getAsJsonArray();
for (JsonElement ele : jsonArray) {
JsonObject versionJson = ele.getAsJsonObject();
-
+ if (isRunningVersion(versionJson)) {
+ runningVersion = new ResourceVersion(
+ resource.resourceId(),
+ page,
+ versionJson.get("id").getAsInt(),
+ versionJson.get("resource_version").getAsString(),
+ null // no need for changelog of running version
+ );
+ }
latestVersion = new ResourceVersion(
resource.resourceId(),
page,
@@ -90,17 +94,14 @@ public class VersionScanner extends CompletableFuture {
versionJson.get("message").getAsString()
)
);
-
- if (isRunningVersion(versionJson))
- runningVersion = latestVersion;
-
- DebugLogger.finer("%s - %s #%d", resource.name(), latestVersion.updateId(), latestVersion.updateId());
+ //System.out.printf("%d %d %s\n", page, versionJson.get("id").getAsInt(), versionJson.get("resource_version").getAsString());
}
if (jsonArray.size() < 10) break;
}
}
+ //System.out.println("Done");
if (page > 999) {
throw new Exception("Too many pages");
@@ -116,8 +117,7 @@ public class VersionScanner extends CompletableFuture {
}
private boolean isRunningVersion(JsonObject versionJson) {
- // TODO make it work with more advanced strings
- return versionJson.get("resource_version").getAsString()
- .equals(resource.plugin().getDescription().getVersion());
+ // TODO
+ return versionJson.get("resource_version").getAsString().equals(resource.plugin().getDescription().getVersion());
}
}
diff --git a/src/main/java/eu/m724/tweaks/module/updater/object/ResourceVersion.java b/src/main/java/eu/m724/tweaks/updater/cache/ResourceVersion.java
similarity index 89%
rename from src/main/java/eu/m724/tweaks/module/updater/object/ResourceVersion.java
rename to src/main/java/eu/m724/tweaks/updater/cache/ResourceVersion.java
index 90efb34..d5d0fd3 100644
--- a/src/main/java/eu/m724/tweaks/module/updater/object/ResourceVersion.java
+++ b/src/main/java/eu/m724/tweaks/updater/cache/ResourceVersion.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.updater.object;
+package eu.m724.tweaks.updater.cache;
import java.util.Objects;
diff --git a/src/main/java/eu/m724/tweaks/module/updater/object/SpigotResource.java b/src/main/java/eu/m724/tweaks/updater/cache/SpigotResource.java
similarity index 76%
rename from src/main/java/eu/m724/tweaks/module/updater/object/SpigotResource.java
rename to src/main/java/eu/m724/tweaks/updater/cache/SpigotResource.java
index 28b0987..dce97cf 100644
--- a/src/main/java/eu/m724/tweaks/module/updater/object/SpigotResource.java
+++ b/src/main/java/eu/m724/tweaks/updater/cache/SpigotResource.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.updater.object;
+package eu.m724.tweaks.updater.cache;
import org.bukkit.plugin.Plugin;
@@ -12,4 +12,5 @@ public record SpigotResource(
Plugin plugin,
int resourceId,
String name
-) { }
+) {
+}
diff --git a/src/main/java/eu/m724/tweaks/module/updater/object/UpdateDescription.java b/src/main/java/eu/m724/tweaks/updater/cache/UpdateDescription.java
similarity index 72%
rename from src/main/java/eu/m724/tweaks/module/updater/object/UpdateDescription.java
rename to src/main/java/eu/m724/tweaks/updater/cache/UpdateDescription.java
index d22f588..1837716 100644
--- a/src/main/java/eu/m724/tweaks/module/updater/object/UpdateDescription.java
+++ b/src/main/java/eu/m724/tweaks/updater/cache/UpdateDescription.java
@@ -1,12 +1,13 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.updater.object;
+package eu.m724.tweaks.updater.cache;
public record UpdateDescription(
String title,
String description
-) { }
+) {
+}
diff --git a/src/main/java/eu/m724/tweaks/module/updater/object/VersionedResource.java b/src/main/java/eu/m724/tweaks/updater/cache/VersionedResource.java
similarity index 77%
rename from src/main/java/eu/m724/tweaks/module/updater/object/VersionedResource.java
rename to src/main/java/eu/m724/tweaks/updater/cache/VersionedResource.java
index 4c274e3..18d4bb2 100644
--- a/src/main/java/eu/m724/tweaks/module/updater/object/VersionedResource.java
+++ b/src/main/java/eu/m724/tweaks/updater/cache/VersionedResource.java
@@ -1,10 +1,10 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.updater.object;
+package eu.m724.tweaks.updater.cache;
public record VersionedResource(
SpigotResource resource,
diff --git a/src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderExpandModule.java b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpander.java
similarity index 64%
rename from src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderExpandModule.java
rename to src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpander.java
index b4a4a30..14eae1b 100644
--- a/src/main/java/eu/m724/tweaks/module/worldborder/WorldBorderExpandModule.java
+++ b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderExpander.java
@@ -1,25 +1,24 @@
/*
- * Copyright (C) 2025 Minecon724
+ * Copyright (C) 2024 Minecon724
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
* in the project root for the full license text.
*/
-package eu.m724.tweaks.module.worldborder;
+package eu.m724.tweaks.worldborder;
-import eu.m724.tweaks.module.TweaksModule;
import net.minecraft.server.level.ServerLevel;
-import org.bukkit.craftbukkit.v1_21_R3.CraftWorld;
+import org.bukkit.craftbukkit.v1_21_R1.CraftWorld;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldLoadEvent;
+import org.bukkit.plugin.Plugin;
-public class WorldBorderExpandModule extends TweaksModule implements Listener {
- @Override
- protected void onInit() {
- registerEvents(this);
+public class WorldBorderExpander implements Listener {
+ public void init(Plugin plugin) {
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
// because the plugin loads "post world"
- getPlugin().getServer().getWorlds().forEach(w -> {
+ plugin.getServer().getWorlds().forEach(w -> {
onWorldLoad(new WorldLoadEvent(w));
});
}
@@ -34,7 +33,7 @@ public class WorldBorderExpandModule extends TweaksModule implements Listener {
}
level.getWorldBorder().setAbsoluteMaxSize(30000000);
- // to align with player hitbox because player can't go beyond 30m - 1 and player's hitbox is 0.6 wide, multiply by 2 for - and +, that's 1.2 and 60000000 - 1.2 = 59999998.6
+ // to align with player hitbox because player can't go beyond 30m - 1 and player's hitbox is 0.6 wide so we make it "hug" the border
level.getWorldBorder().setSize(59999998.6);
}
}
diff --git a/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHider.java b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHider.java
new file mode 100644
index 0000000..06b3491
--- /dev/null
+++ b/src/main/java/eu/m724/tweaks/worldborder/WorldBorderHider.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2024 Minecon724
+ * Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
+ * in the project root for the full license text.
+ */
+
+package eu.m724.tweaks.worldborder;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.ProtocolLibrary;
+import com.comphenix.protocol.events.ListenerPriority;
+import com.comphenix.protocol.events.PacketAdapter;
+import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.events.PacketEvent;
+import org.bukkit.plugin.Plugin;
+
+import java.nio.ByteBuffer;
+
+public class WorldBorderHider {
+ private static final int EXTENSION_RADIUS = 512;
+
+ public void init(Plugin plugin) {
+ plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, "tweaks724:worldborder");
+ byte[] infoArray = ByteBuffer.allocate(4).putInt(EXTENSION_RADIUS).array();
+
+ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
+ plugin,
+ ListenerPriority.NORMAL,
+ PacketType.Play.Server.INITIALIZE_BORDER
+ ) {
+ @Override
+ public void onPacketSending(PacketEvent event) {
+ PacketContainer packet = event.getPacket();
+ // old diameter
+ packet.getDoubles().write(2, packet.getDoubles().read(2) + EXTENSION_RADIUS * 2);
+ // new diameter
+ packet.getDoubles().write(3, packet.getDoubles().read(3) + EXTENSION_RADIUS * 2);
+
+ // border radius
+ packet.getIntegers().write(0, packet.getIntegers().read(0) + EXTENSION_RADIUS);
+ // warning distance
+ packet.getIntegers().write(1, packet.getIntegers().read(1) + EXTENSION_RADIUS);
+
+ event.getPlayer().sendPluginMessage(plugin, "tweaks724:worldborder", infoArray);
+ }
+ });
+
+ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
+ plugin,
+ ListenerPriority.NORMAL,
+ PacketType.Play.Server.SET_BORDER_SIZE
+ ) {
+ @Override
+ public void onPacketSending(PacketEvent event) {
+ PacketContainer packet = event.getPacket();
+ // diameter
+ packet.getDoubles().write(0, packet.getDoubles().read(0) + EXTENSION_RADIUS * 2);
+ }
+ });
+
+ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
+ plugin,
+ ListenerPriority.NORMAL,
+ PacketType.Play.Server.SET_BORDER_WARNING_DISTANCE
+ ) {
+ @Override
+ public void onPacketSending(PacketEvent event) {
+ PacketContainer packet = event.getPacket();
+ // warning distance
+ packet.getIntegers().write(0, packet.getIntegers().read(0) + EXTENSION_RADIUS);
+ }
+ });
+ }
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 6b48d5f..9c49759 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -5,7 +5,7 @@
# - https://discord.gg/86X4Z5JUeq
# - https://www.spigotmc.org/threads/tweaks724.670906/
-# Metrics toggle. Please keep this on.
+# Metrics toggle. Ideally opt-in, but the system is very new and it needs testing.
metrics: true
# Warning: Don't use /worldborder while this is on
@@ -36,9 +36,9 @@ doors:
knocking: true
motd:
- enabled: true
# Name of the set containing the MOTDs
# (random displayed every ping)
+ # "" or false to disable
set: "example"
chat:
@@ -81,10 +81,8 @@ hardcore:
# 0.0 - 1.0 decimal. This is if you want to make it like an Easter egg
chance: 1.0
-# Sleep tweaks
-# Percentage: playersSleepingPercentage gamerule
-# If instant: how much % of players to skip the night
-# If not: how much % make skipping full speed
+# Makes sleeping
+# And adds a nice animation
sleep:
enabled: true
# This gives every player a "share" of the night
@@ -92,8 +90,9 @@ sleep:
# For example, if 5 players online and night is 5 minutes, one can go to sleep and skip 1 minute of the night
# Leaving the bed and reentering it does nothing
instant: false
- # How many hearts to heal after sleeping
- heal: 2.0
+ # Percentage: playersSleepingPercentage gamerule
+ # If instant: how much % of players to skip the night
+ # If not: how much % make skipping full speed
# "Hostname" authentication
# This makes a player need to join a unique hostname like "asd123.example.com" where "asd123" is the key
@@ -127,12 +126,6 @@ killswitch:
# To disable HTTP server, set to null
listen: 127.0.0.1:57932
-# Swing through grass (and alike)
-# If using sword, you can also hit behind the grass
-# If not, you can only hit the entity in the grass
-swing:
- enabled: true
-
# Finally, thank you for downloading Tweaks724, I hope you enjoy!
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 40473fb..fac4b46 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -8,7 +8,7 @@ api-version: 1.21.1
softdepend: [ProtocolLib]
libraries:
- - eu.m724:mstats-spigot:0.1.2
+ - eu.m724:mstats-spigot:0.1.0
commands:
chat:
@@ -40,36 +40,22 @@ commands:
servkill:
description: Immediately stop the server
permission: tweaks724.servkill
- durabilityalert:
- description: Durability alert toggle
- permission: tweaks724.durabilityalert
- wordcoords:
- description: Word to coords conversion
- permission: tweaks724.wordcoords
- aliases: [woco, wc, w3w]
permissions:
- tweaks724.chatmanage:
- default: true
- tweaks724.pomodoro:
- default: true
- tweaks724.updates:
- default: op
- tweaks724.tauth:
- default: op
- tweaks724.bypass-full:
- default: op
- tweaks724.emergencyalert:
- default: op
- tweaks724.retstone:
- default: op
- tweaks724.servkill:
- default: false
- tweaks724.durabilityalert:
- default: true
- tweaks724.wordcoords:
- default: true
-
- 7weaks724.ignore.this:
- description: "Internal, not for use. ${project.spigot.version}"
- default: false
+ tweaks724:
+ chatmanage:
+ default: true
+ pomodoro:
+ default: true
+ updates:
+ default: op
+ tauth:
+ default: op
+ bypass-full:
+ default: op
+ emergencyalert:
+ default: op
+ retstone:
+ default: op
+ servkill:
+ default: false
diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties
index 204bc20..550c4f8 100644
--- a/src/main/resources/strings.properties
+++ b/src/main/resources/strings.properties
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2025 Minecon724
+# Copyright (C) 2024 Minecon724
# Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
# in the project root for the full license text.
#
@@ -13,41 +13,23 @@ languageEnglish = English
updateAvailableNotice = Available updates (%d):
# Used in /updates
-updatesNotChecked = Not checked yet.
+updatesNotChecked = Not checked yet
# %s is time as HH:mm
updatesNoUpdates = No available updates. Last checked: %s
# %s is update title
updatesClickToOpen = Click to open on SpigotMC "%s"
# Used in /chat
-chatPasswordProtected = This room is password protected.
-chatWrongPassword = Wrong password.
-chatNoSuchRoom = Room %s doesn't exist.
-chatNoSuchRoomInvalidId = Room %s doesn't exist, because the ID is invalid.
-chatAlreadyHere = You're already in this room.
+chatPasswordProtected = This room is password protected
+chatWrongPassword = Wrong password
+chatNoSuchRoom = No room named %s
+chatAlreadyHere = You're already in this room
# Used when a player joins using the wrong key or no key
authKickWrongKey = You're connecting to the wrong server address. You must connect to the one you're registered to.
# If force is enabled and player is not registered. Changing this reveals you're using this plugin
authKickUnregistered = You are not whitelisted on this server!
-authKickError = An error occurred. Please try again. If this persists, contact an administrator.
redstoneGatewayItem = Redstone gateway
-clickToCopy = Click to copy to clipboard
-clickToExecuteCommand = Click to execute command
-
-durabilityEnabled = Enabled durability alert
-durabilityDisabled = Disabled durability alert
-
-# When console executes /wordcoords without arguments
-wordCoordsPlayerOnly = Only players can execute this command without arguments.
-wordCoordsOutOfRange = Those coordinates are invalid.
-wordCoordsInvalidWord = Invalid word: "%s"
-wordCoordsNoWords = Please provide the Z coordinate.
-
-# /pomodoro
-pomodoroStopped = Pomodoro stopped. Restart it with /%s start
-pomodoroStart = Start pomodoro with /%s start
-pomodoroShortBreak = Short break
-pomodoroLongBreak = Long break
\ No newline at end of file
+clickToCopy = Click to copy to clipboard
\ No newline at end of file
diff --git a/tools/download_nms.sh b/tools/download_nms.sh
index 95a44be..c22aac4 100755
--- a/tools/download_nms.sh
+++ b/tools/download_nms.sh
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/bin/bash
#
-# Copyright (C) 2025 Minecon724
+# Copyright (C) 2024 Minecon724
# Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
# in the project root for the full license text.
#