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. #