diff --git "a/.github/workflows/bu\303\255ld.yml" b/.github/workflows/build.yml similarity index 65% rename from ".github/workflows/bu\303\255ld.yml" rename to .github/workflows/build.yml index eaa6f1a..2b89e47 100644 --- "a/.github/workflows/bu\303\255ld.yml" +++ b/.github/workflows/build.yml @@ -10,30 +10,35 @@ jobs: build: strategy: matrix: - # Use these Java versions java: [ - 17 # Minimum supported by Minecraft + 21, ] - # and run on both Linux and Windows - os: [ubuntu-20.04, windows-latest] + + distribution: [ + "temurin", + ] + + os: [ubuntu-24.04, windows-2022] + runs-on: ${{ matrix.os }} steps: - name: checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v5 - name: validate gradle wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/wrapper-validation-action@v3 - name: setup jdk ${{ matrix.java }} - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} + distribution: ${{ matrix.distribution }} - name: make gradle wrapper executable if: ${{ runner.os != 'Windows' }} run: chmod +x ./gradlew - name: build - run: ./gradlew build + run: ./gradlew chiseledBuild - name: capture build artifacts - if: ${{ runner.os == 'Linux' && matrix.java == '17' }} # Only upload artifacts built from latest java on one OS - uses: actions/upload-artifact@v3 + if: ${{ runner.os == 'Linux' && matrix.java == '21' }} # Only upload artifacts built from latest java on one OS + uses: actions/upload-artifact@v4 with: name: Artifacts - path: build/libs \ No newline at end of file + path: build/libs/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 98c9d17..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: release - -on: - release: - types: - - published - - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - steps: - - name: Setup Temurin 17 - uses: actions/setup-java@v3 - with: - java-version: 17 - distribution: temurin - - - name: Checkout sources - uses: actions/checkout@v3 - - - name: validate gradle wrapper - uses: gradle/wrapper-validation-action@v1 - - - name: make gradle wrapper executable - if: ${{ runner.os != 'Windows' }} - run: chmod +x ./gradlew - # The USERNAME and TOKEN need to correspond to the credentials environment variables used in - # the publishing section of your build.gradle - - name: Publish to GitHub Packages - uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - with: - arguments: publish - env: - USERNAME: ${{ github.actor }} - TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish to modrinth - run: ./gradlew - with: - arguments: modrinth - # I have no ided if this will work - env: - MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index c78a8cc..33f7a5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,69 @@ -# gradle +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump -.gradle -build -out -classes +# Folder config file +[Dd]esktop.ini -# text editors -.obsidian +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# gradle + +.gradle/ +build/ +out/ +classes/ # eclipse @@ -19,17 +76,18 @@ classes *.ipr *.iws -qodana.sarif.json -qodana.yaml - # vscode -.settings -.vscode +.settings/ +.vscode/ bin/ .classpath .project +# macos + +*.DS_Store + # fabric -run/ +run/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..1019c96 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,3 @@ +# What's changed? +- moved to stonecutter (backend rewrite) +- multiple versions now supported \ No newline at end of file diff --git a/README.md b/README.md index 75869c8..daea373 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ yeahh!! this is the fabric library mod that i *sometimes* use in my projects. did i mention it has **0**, yes **zero** dependencies? ## Features -* read the [wiki](https://github.com/not-coded/codelib/wiki) +* read the javadocs somewhere (todo: implement javadocs github pages) * more coming soon ## How to use @@ -16,7 +16,7 @@ Add the following to your `gradle.properties` codelib_version=...+minecraft_version # Example -codelib_version=1.0.1+1.20 +codelib_version=2.0.0+1.20 ``` And `build.gradle` diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..c7ecae0 --- /dev/null +++ b/TODO.md @@ -0,0 +1,10 @@ +# to-do +- [x] add versions 1.16.5, 1.17.1, 1.18.2, 1.19.4, 1.21, etc. + - [ ] test if every version works (create a test mod) +- [ ] perhaps add a config with cool customizability thing + - [use simple structuring like with autoconfig](https://shedaniel.gitbook.io/cloth-config/auto-config/creating-a-config-class) +- [ ] add java docs as a github page +- [ ] fix maven +- [x] possibly use annotations in mixins to specify which version they should be run on? (possibly with the help of mixin plugins)? + - [x] e.g. @MinecraftVersion("1.21") or something (dunno if it's even possible) +- [ ] find out how to bundle multiple versions in one jar (e.g. 1.16.5, 1.19, 1.21 from stonecutter) \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 75b43b4..0000000 --- a/build.gradle +++ /dev/null @@ -1,84 +0,0 @@ -plugins { - id 'fabric-loom' version '1.3-SNAPSHOT' - id 'com.modrinth.minotaur' version '2.+' - id 'maven-publish' -} - -version = project.mod_version + "+" + project.minecraft_version.substring(0, 4) -group = project.maven_group - -base { - archivesName = project.archives_base_name -} - -dependencies { - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings loom.officialMojangMappings() - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" -} - -processResources { - inputs.property "version", project.version - filteringCharset "UTF-8" - - filesMatching("fabric.mod.json") { - expand "version": project.version - } -} - -tasks.withType(JavaCompile).configureEach { - it.options.encoding = "UTF-8" - it.options.release = 17 -} - -java { - withJavadocJar() - withSourcesJar() - - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -jar { - from("LICENSE") { - rename { "${it}_${project.base.archivesName.get()}"} - } -} - -// configure the maven publication -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - } - gpr(MavenPublication) { - from components.java - } - } - - repositories { - maven { - name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/not-coded/codelib") - credentials { - username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") - password = project.findProperty("gpr.key") ?: System.getenv("TOKEN") - } - } - } -} - -modrinth { - token = System.getenv("MODRINTH_TOKEN") - projectId = "codelib" - versionNumber = "${project.version}" - versionName = "v${project.version}".substring(0, 6) + " | ${project.minecraft_version}" - versionType = "release" - uploadFile = remapJar - additionalFiles.add(javadocJar) - additionalFiles.add(sourcesJar) - gameVersions.add(minecraft_version) - loaders.add("fabric") - loaders.add("quilt") - changelog = "### Read https://github.com/not-coded/codelib/releases/tag/${project.version}." -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..30b59d6 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,99 @@ +plugins { + id("fabric-loom") version "1.9.2" + id("com.modrinth.minotaur") version "2.+" + id("net.ltgt.errorprone") version "4.1.0" + id("maven-publish") +} + +val modName = property("mod.name").toString() +version = "${property("mod.version")}" + "+" + "${property("mod.version_name")}" +group = property("mod.maven_group").toString() + +base { + archivesName.set(modName) +} + +dependencies { + minecraft("com.mojang:minecraft:${property("deps.minecraft")}") + mappings("net.fabricmc:yarn:${property("deps.yarn_mappings")}:v2") + modImplementation("net.fabricmc:fabric-loader:${property("deps.fabric_loader")}") + + errorprone("com.google.errorprone:error_prone_core:${property("deps.errorprone")}") +} + +loom { + decompilers { + get("vineflower").apply { // Adds names to lambdas - useful for mixins + options.put("mark-corresponding-synthetics", "1") + } + } + + runConfigs.all { + ideConfigGenerated(true) + vmArgs("-Dmixin.debug.export=true") + runDir = "../../run" + } +} + +val target = ">=${property("mod.min_target")}- <=${property("mod.max_target")}" + +tasks.processResources { + val expandProps = mapOf( + "version" to project.version, + "minecraftVersion" to target, + "javaVersion" to project.property("deps.java") + ) + + filesMatching("fabric.mod.json") { + expand(expandProps) + } + + inputs.properties(expandProps) +} + +java { + withSourcesJar() + withJavadocJar() + + val javaVersion = if (project.property("deps.java") == "8") JavaVersion.VERSION_1_8 else JavaVersion.VERSION_17 + + sourceCompatibility = javaVersion + targetCompatibility = javaVersion +} + + +tasks.withType { + options.encoding = "UTF-8" + + // Minecraft 1.18 (1.18-pre2) upwards uses Java 17. + options.release.set(Integer.parseInt(project.property("deps.java").toString())) + + // Fixes Error Prone INIT policy + options.compilerArgs.add("--should-stop=ifError=FLOW") +} + +tasks.register("buildAndCollect") { + group = "build" + from(tasks.remapJar.get().archiveFile) + into(rootProject.layout.buildDirectory.file("libs")) + dependsOn("build") +} + +modrinth { + token.set(System.getenv("MODRINTH_TOKEN")) + projectId.set("wayfix") + versionNumber.set(version.toString()) + versionName.set("v$version") + versionType.set("release") + uploadFile.set(tasks.remapJar) + gameVersions.addAll(property("publishing.supported_versions").toString().split(",")) + loaders.addAll("fabric", "quilt") + //featured = true + + dependencies { + required.project("cloth-config") + optional.project("modmenu") + } + + changelog = rootProject.file("CHANGES.md").readText() +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 57f74ee..1433997 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,16 +1,22 @@ # Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx1G -org.gradle.parallel=true +org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +#org.gradle.parallel=true -# Fabric Properties - # check these on https://fabricmc.net/use - minecraft_version=1.20.1 - yarn_mappings=1.20.1+build.10 - loader_version=0.14.21 +mod.version=2.0.0 +mod.name=codelib +mod.maven_group=net.notcoded -# Mod Properties - mod_version = 1.0.1 - maven_group = net.notcoded - archives_base_name = codelib +mod.version_name=[VERSIONED] +mod.min_target=[VERSIONED] +mod.max_target=[VERSIONED] + +publishing.supported_versions=[VERSIONED] + +# Dependencies +# https://fabricmc.net/develop +deps.yarn=[VERSIONED] +deps.fabric_loader=0.14.21 +deps.errorprone=2.42.0 +deps.java=[VERSIONED] diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 490fda8..1b33c55 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9f4197d..d4081da 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 2fe81a7..23d15a9 100644 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,80 +15,115 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" + # Determine the Java command to use to start the JVM. 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" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,87 +132,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 62bd9b9..5eed7ee 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,103 +1,94 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..7c153a3 --- /dev/null +++ b/renovate.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ], + "dependencyDashboard": false, + "platformAutomerge": true, + "ignoreDeps": ["dev.kikugie.stonecutter"] +} diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 5b60df3..0000000 --- a/settings.gradle +++ /dev/null @@ -1,10 +0,0 @@ -pluginManagement { - repositories { - jcenter() - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - gradlePluginPortal() - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..f9ef4a3 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + repositories { + maven("https://maven.fabricmc.net/") + + gradlePluginPortal() + maven("https://maven.kikugie.dev/snapshots") + } +} + +plugins { + id("dev.kikugie.stonecutter") version "0.5-beta.5" +} + +stonecutter { + kotlinController = true + centralScript = "build.gradle.kts" + + shared { + versions("1.16.5", "1.17.1", "1.18.2", "1.19.4", "1.20.1", "1.21") + vcsVersion = "1.21" + } + + create(rootProject) +} + +rootProject.name = "codelib" \ No newline at end of file diff --git a/src/main/java/net/notcoded/codelib/CodeLib.java b/src/main/java/net/notcoded/codelib/CodeLib.java index cd182a0..18e3d78 100644 --- a/src/main/java/net/notcoded/codelib/CodeLib.java +++ b/src/main/java/net/notcoded/codelib/CodeLib.java @@ -1,32 +1,8 @@ package net.notcoded.codelib; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.ModInitializer; -import net.minecraft.client.Minecraft; -import net.minecraft.server.MinecraftServer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; -public class CodeLib implements ModInitializer { - - protected static EnvType type = EnvType.CLIENT; - - public static Minecraft client; - - public static MinecraftServer server; - - @Override - public void onInitialize() { - try { - loadClient(); - } catch(NoClassDefFoundError ignored){ - loadServer(); - } - } - - protected void loadServer() { - type = EnvType.SERVER; - } - - protected void loadClient() { - client = Minecraft.getInstance(); - } +public class CodeLib { + public static final Logger LOGGER = LogManager.getLogger(CodeLib.class); } diff --git a/src/main/java/net/notcoded/codelib/client/CodeLibClient.java b/src/main/java/net/notcoded/codelib/client/CodeLibClient.java new file mode 100644 index 0000000..dc4a9dd --- /dev/null +++ b/src/main/java/net/notcoded/codelib/client/CodeLibClient.java @@ -0,0 +1,13 @@ +package net.notcoded.codelib.client; + +import net.fabricmc.api.ClientModInitializer; +import net.minecraft.client.MinecraftClient; + +public class CodeLibClient implements ClientModInitializer { + public static MinecraftClient client; + + @Override + public void onInitializeClient() { + client = MinecraftClient.getInstance(); + } +} diff --git a/src/main/java/net/notcoded/codelib/common/mixinhelper/MixinPlugin.java b/src/main/java/net/notcoded/codelib/common/mixinhelper/MixinPlugin.java new file mode 100644 index 0000000..8a96e0a --- /dev/null +++ b/src/main/java/net/notcoded/codelib/common/mixinhelper/MixinPlugin.java @@ -0,0 +1,99 @@ +package net.notcoded.codelib.common.mixinhelper; + +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.Version; +import net.fabricmc.loader.api.VersionParsingException; +import net.fabricmc.loader.api.metadata.version.VersionPredicate; +import net.fabricmc.loader.impl.util.version.VersionPredicateParser; +import net.notcoded.codelib.common.mixinhelper.annotation.MinecraftVersion; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.util.*; + +public class MixinPlugin implements IMixinConfigPlugin { + @Override + public void onLoad(String mixinPackage) { + + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + @SuppressWarnings("IdentityBinaryExpression") + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + Class clazz; + try { + clazz = Thread.currentThread().getContextClassLoader().loadClass(mixinClassName); + } catch (ClassNotFoundException e) { + return true; // no idea what happened + } + + List minecraftVersions = new ArrayList<>(); + + for(Annotation annotation : clazz.getAnnotations()) { // this is cursed but it somehow works + if(annotation.annotationType().toGenericString().equals(MinecraftVersion.class.toGenericString())) { + try { + minecraftVersions = Arrays.asList((String[]) annotation.annotationType().getMethod("minecraft").invoke(annotation)); + break; + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException("Failed to get the value of MinecraftVersion annotation!"); + } + } + } + + if(minecraftVersions.isEmpty()) return true; + + Version gameVersion = FabricLoader.getInstance().getModContainer("minecraft").get().getMetadata().getVersion(); // 1.21 + Set versions; + + try { + versions = VersionPredicateParser.parse(minecraftVersions); + } catch (VersionParsingException e) { + throw new RuntimeException(e); + } + + if(minecraftVersions.size() == 2) { + String mcVer1 = minecraftVersions.get(0); + String mcVer2 = minecraftVersions.get(1); + + Iterator iterator = versions.iterator(); + // NOTE: "@MinecraftVersion(minecraft = {">=1.21", "<=1.21.5"})" would be correct syntax for this (example). + if(mcVer1.contains(">") && mcVer2.contains("<")) { + return iterator.next().test(gameVersion) && iterator.next().test(gameVersion); + } + } + + for(VersionPredicate minecraftVersion : versions) { + if (minecraftVersion.test(gameVersion)) return true; + } + + return false; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } +} \ No newline at end of file diff --git a/src/main/java/net/notcoded/codelib/common/mixinhelper/annotation/MinecraftVersion.java b/src/main/java/net/notcoded/codelib/common/mixinhelper/annotation/MinecraftVersion.java new file mode 100644 index 0000000..b5f657d --- /dev/null +++ b/src/main/java/net/notcoded/codelib/common/mixinhelper/annotation/MinecraftVersion.java @@ -0,0 +1,12 @@ +package net.notcoded.codelib.common.mixinhelper.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface MinecraftVersion { + String[] minecraft() default ""; +} diff --git a/src/main/java/net/notcoded/codelib/util/TickUtil.java b/src/main/java/net/notcoded/codelib/common/util/TickUtil.java similarity index 95% rename from src/main/java/net/notcoded/codelib/util/TickUtil.java rename to src/main/java/net/notcoded/codelib/common/util/TickUtil.java index e48bfe1..5cca852 100644 --- a/src/main/java/net/notcoded/codelib/util/TickUtil.java +++ b/src/main/java/net/notcoded/codelib/common/util/TickUtil.java @@ -1,4 +1,4 @@ -package net.notcoded.codelib.util; +package net.notcoded.codelib.common.util; public class TickUtil { diff --git a/src/main/java/net/notcoded/codelib/util/http/HttpAPI.java b/src/main/java/net/notcoded/codelib/common/util/http/HttpAPI.java similarity index 59% rename from src/main/java/net/notcoded/codelib/util/http/HttpAPI.java rename to src/main/java/net/notcoded/codelib/common/util/http/HttpAPI.java index d5f915f..2a4ecce 100644 --- a/src/main/java/net/notcoded/codelib/util/http/HttpAPI.java +++ b/src/main/java/net/notcoded/codelib/common/util/http/HttpAPI.java @@ -1,29 +1,28 @@ -package net.notcoded.codelib.util.http; +package net.notcoded.codelib.common.util.http; import org.jetbrains.annotations.NotNull; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.charset.Charset; public class HttpAPI { - public static String userAgent = "Mozilla/5.0 (compatible; codelib; +https://github.com/not-coded/codelib)"; - + private static final String userAgent = "Mozilla/5.0 (compatible; codelib; +https://github.com/not-coded/codelib)"; /** - * Sends a GET request to an url. - * @param url The url, e.g. https://notcoded.is-a.dev/ - * @return The response. + * Same as {@link HttpAPI#get(URL)} but with the ability to set the User Agent. + * @see HttpAPI#get(URL) */ - public static String get(@NotNull URL url) { + public static String get(@NotNull URL url, @NotNull String userAgent) { try { HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty("User-Agent", userAgent); connection.setRequestMethod("GET"); - BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charset.defaultCharset())); String line; StringBuilder response = new StringBuilder(); while ((line = reader.readLine()) != null) { @@ -36,4 +35,13 @@ public static String get(@NotNull URL url) { return response.toString(); } catch (Exception ignored) { return null; } } + + /** + * Sends a GET request to an url. + * @param url The url, e.g. https://notcoded.is-a.dev + * @return The response. + */ + public static String get(@NotNull URL url) { + return get(url, userAgent); + } } \ No newline at end of file diff --git a/src/main/java/net/notcoded/codelib/common/util/minecraft/MinecraftAPI.java b/src/main/java/net/notcoded/codelib/common/util/minecraft/MinecraftAPI.java new file mode 100644 index 0000000..fedb5c8 --- /dev/null +++ b/src/main/java/net/notcoded/codelib/common/util/minecraft/MinecraftAPI.java @@ -0,0 +1,77 @@ +package net.notcoded.codelib.common.util.minecraft; + +import com.google.gson.JsonElement; +import net.notcoded.codelib.common.util.http.HttpAPI; + +import java.net.URL; +import java.util.HashMap; +import java.util.Locale; + +import static net.notcoded.codelib.common.util.version.VersionUtil.parseString; + +public class MinecraftAPI { + public static HashMap cachedNames = new HashMap<>(); + + public static HashMap cachedUUIDs = new HashMap<>(); + + /** + * Returns the UUID of a name. + * @param name The name of the player, e.g. NotCoded + * @return The uuid of the player, e.g. {@code fcbf27a9-535e-466f-ae75-7c7959fba7f0} + */ + + public static String getUUID(String name) { + if(name.trim().isEmpty()) return null; + if(cachedUUIDs.containsKey(name.toLowerCase(Locale.ROOT))) return cachedUUIDs.get(name.toLowerCase(Locale.ROOT)); + + String response; + try { + response = HttpAPI.get(new URL(String.format("https://api.mojang.com/users/profiles/minecraft/%s", name))); + } catch (Exception ignored) { + return null; + } + + if (response == null || response.trim().isEmpty()) return null; + + JsonElement result = parseString(response); + String uuid = result.getAsJsonObject().get("id").getAsString(); + + if (uuid != null && !uuid.trim().isEmpty() && (uuid.length() == 32 || uuid.length() == 36)) { + cachedNames.put(uuid, name.toLowerCase(Locale.ROOT)); + return uuid; + } + + return null; + } + + /** + * Returns the name of an UUID. + * @param uuid The uuid of a player, e.g. fcbf27a9-535e-466f-ae75-7c7959fba7f0 + * @return The name of a player, e.g. {@code NotCoded} + */ + + public static String getName(String uuid) { + if(uuid.length() != 32 && uuid.length() != 36) return null; + if (cachedNames.containsKey(uuid.toLowerCase(Locale.ROOT))) return cachedNames.get(uuid.toLowerCase(Locale.ROOT)); + + String response; + + try { + response = HttpAPI.get(new URL(String.format("https://sessionserver.mojang.com/session/minecraft/profile/%s", uuid))); + } catch (Exception ignored) { + return null; + } + + if (response == null || response.trim().isEmpty()) return null; + + JsonElement result = parseString(response); + String name = result.getAsJsonObject().get("name").getAsString(); + + if (name != null && !name.trim().isEmpty()) { + cachedUUIDs.put(name, uuid.toLowerCase(Locale.ROOT)); + return name; + } + + return null; + } +} \ No newline at end of file diff --git a/src/main/java/net/notcoded/codelib/util/numbers/RomanNumbers.java b/src/main/java/net/notcoded/codelib/common/util/numbers/RomanNumbers.java similarity index 93% rename from src/main/java/net/notcoded/codelib/util/numbers/RomanNumbers.java rename to src/main/java/net/notcoded/codelib/common/util/numbers/RomanNumbers.java index 896d7c2..87e1345 100644 --- a/src/main/java/net/notcoded/codelib/util/numbers/RomanNumbers.java +++ b/src/main/java/net/notcoded/codelib/common/util/numbers/RomanNumbers.java @@ -1,10 +1,11 @@ -package net.notcoded.codelib.util.numbers; +package net.notcoded.codelib.common.util.numbers; import java.util.TreeMap; public class RomanNumbers { - private final static TreeMap romanNumbers = getRomanNumbers(); + + @SuppressWarnings("NonApiType") private static TreeMap getRomanNumbers() { TreeMap romanNumbers = new TreeMap<>(); romanNumbers.put(1000, "M"); diff --git a/src/main/java/net/notcoded/codelib/common/util/string/StringUtils.java b/src/main/java/net/notcoded/codelib/common/util/string/StringUtils.java new file mode 100644 index 0000000..620b8a8 --- /dev/null +++ b/src/main/java/net/notcoded/codelib/common/util/string/StringUtils.java @@ -0,0 +1,16 @@ +package net.notcoded.codelib.common.util.string; + +import java.util.Locale; + +public class StringUtils { + /** + * Forces the first word of any {@code String} to be lowercase. (HI, THIS IS A COOL LIBRARY -> hi, THIS IS A COOL LIBRARY) + * @param input The input. + * @return The lowercased output. + */ + public static String firstArgumentToLowerCase(String input) { + String[] args = input.split(" ", 2); + args[0] = args[0].toLowerCase(Locale.ROOT); + return String.join(" ", args); + } +} diff --git a/src/main/java/net/notcoded/codelib/common/util/version/VersionUtil.java b/src/main/java/net/notcoded/codelib/common/util/version/VersionUtil.java new file mode 100644 index 0000000..51c5abc --- /dev/null +++ b/src/main/java/net/notcoded/codelib/common/util/version/VersionUtil.java @@ -0,0 +1,31 @@ +package net.notcoded.codelib.common.util.version; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import net.minecraft.util.Identifier; + +public class VersionUtil { + public static JsonElement parseString(String response) { + //? if >=1.18 { + return JsonParser.parseString(response); + //?} elif <1.18 { + /*return new JsonParser().parse(response); + *///?} + } + + public static Identifier identifier(String namespace, String path) { + //? if >=1.21 { + return Identifier.of(namespace, path); + //?} elif <=1.20.1 { + /*return new Identifier(namespace, path); + *///?} + } + + public static Identifier identifier(String id) { + //? if >=1.21 { + return Identifier.of(id); + //?} elif <=1.20.1 { + /*return new Identifier(id); + *///?} + } +} \ No newline at end of file diff --git a/src/main/java/net/notcoded/codelib/common/util/world/WorldUtil.java b/src/main/java/net/notcoded/codelib/common/util/world/WorldUtil.java new file mode 100644 index 0000000..85cf34f --- /dev/null +++ b/src/main/java/net/notcoded/codelib/common/util/world/WorldUtil.java @@ -0,0 +1,25 @@ +package net.notcoded.codelib.common.util.world; + +import net.minecraft.util.Identifier; +import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; + +public class WorldUtil { + /** + * Gets the world name of a level. + * @param world The world. + * @return The name of the world, e.g. minecraft (namespace) and overworld (path) + */ + public static Identifier getWorldName(@NotNull World world) { + return world.getRegistryKey().getValue(); + } + + /** + * Gets the world name of a level as a string. + * @param world The world. + * @return The name of the world, e.g. minecraft:overworld + */ + public static String getStringWorldName(@NotNull World world) { + return getWorldName(world).toString(); + } +} \ No newline at end of file diff --git a/src/main/java/net/notcoded/codelib/minecraft/MinecraftAPI.java b/src/main/java/net/notcoded/codelib/minecraft/MinecraftAPI.java deleted file mode 100644 index 7abd45a..0000000 --- a/src/main/java/net/notcoded/codelib/minecraft/MinecraftAPI.java +++ /dev/null @@ -1,57 +0,0 @@ -package net.notcoded.codelib.minecraft; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.notcoded.codelib.util.http.HttpAPI; -import org.jetbrains.annotations.NotNull; - -import java.net.URL; -import java.util.UUID; - -public class MinecraftAPI { - - /** - * Returns the UUID of a name. - * @param name The name of the player, e.g. NotCoded - * @return The uuid of the player, e.g. fcbf27a9-535e-466f-ae75-7c7959fba7f0 - */ - public static UUID getUUID(@NotNull String name) { - if(name.trim().isEmpty() || name.length() < 3 || name.length() > 15) return null; - String response; - - try { - response = HttpAPI.get(new URL(String.format("https://api.mojang.com/users/profiles/minecraft/%s", name))); - } catch(Exception ignored) { return null; } - - if(response != null && !response.trim().isEmpty()) { - String uuid = JsonParser.parseString(response).getAsJsonObject().get("id").getAsString(); - if (uuid != null && !uuid.trim().isEmpty() && (uuid.length() == 32 || uuid.length() == 36)) return UUID.fromString(uuid); - } - return null; - } - - /** - * Returns the name of an UUID. - * @param uuid The uuid of a player, e.g. fcbf27a9-535e-466f-ae75-7c7959fba7f0 - * @return The name of a player, e.g. NotCoded - */ - - public static String getName(@NotNull UUID uuid){ - String response; - - try { - response = HttpAPI.get(new URL(String.format("https://sessionserver.mojang.com/session/minecraft/profile/%s", uuid))); - } catch(Exception ignored) { return null; } - - if(response != null && !response.trim().isEmpty()) { - JsonElement result = JsonParser.parseString(response); - String name = result.getAsJsonObject().get("name").getAsString(); - - if (name != null && !name.trim().isEmpty() && (name.length() > 2 && name.length() < 16)) return name; - } - - return null; - } -} \ No newline at end of file diff --git a/src/main/java/net/notcoded/codelib/players/AccuratePlayer.java b/src/main/java/net/notcoded/codelib/players/AccuratePlayer.java deleted file mode 100644 index d1d99a8..0000000 --- a/src/main/java/net/notcoded/codelib/players/AccuratePlayer.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.notcoded.codelib.players; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.notcoded.codelib.CodeLib; -import net.minecraft.server.level.ServerPlayer; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -@Environment(EnvType.SERVER) -public class AccuratePlayer { - private static List accuratePlayerList = new ArrayList<>(); - - public ServerPlayer player; - public UUID uuid; - - private AccuratePlayer(UUID uuid) { - this.uuid = uuid; - this.player = CodeLib.server.getPlayerList().getPlayer(uuid); - - accuratePlayerList.add(this); - } - - public static AccuratePlayer create(ServerPlayer player) { - for(AccuratePlayer accuratePlayer : accuratePlayerList) { - if(accuratePlayer.uuid.equals(player.getUUID())) return accuratePlayer; - } - - return new AccuratePlayer(player.getUUID()); - } - - /** - * Gets player from the server. - * @return Accurate player. - */ - public ServerPlayer get() { - ServerPlayer player = CodeLib.server.getPlayerList().getPlayer(this.uuid); - - if(player == null) { - accuratePlayerList.remove(this); - return null; - } - - if(this.player != player) this.player = player; - return this.player; - } -} diff --git a/src/main/java/net/notcoded/codelib/players/ExtendedPlayer.java b/src/main/java/net/notcoded/codelib/players/ExtendedPlayer.java deleted file mode 100644 index b243f19..0000000 --- a/src/main/java/net/notcoded/codelib/players/ExtendedPlayer.java +++ /dev/null @@ -1,78 +0,0 @@ -package net.notcoded.codelib.players; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.Holder; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.*; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundSource; -import net.notcoded.codelib.CodeLib; -import net.notcoded.codelib.util.pos.EntityPos; -import net.notcoded.codelib.util.item.ItemStackUtil; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; - -/** - * Gives more functions to the player - */ -@Environment(EnvType.SERVER) -public class ExtendedPlayer extends ServerPlayer { - public AccuratePlayer player; - - public ExtendedPlayer(AccuratePlayer player) { - super(CodeLib.server, player.get().serverLevel(), player.get().getGameProfile()); - this.player = player; - } - - public void removeItem(Item item, int count) { - for (ItemStack itemStack : ItemStackUtil.getInvItems(this.player.get())) { - if (itemStack.getItem() != item) continue; - - if (itemStack.getCount() >= count) { - itemStack.shrink(count); - break; - } else { - count -= itemStack.getCount(); - itemStack.shrink(itemStack.getCount()); - } - } - } - - public void sendSound(SoundEvent soundEvent, SoundSource soundSource, float volume, float pitch, long minVolume) { - sendSound(Holder.direct(SoundEvent.createVariableRangeEvent(soundEvent.getLocation())), soundSource, volume, pitch, minVolume); - } - - public void sendSound(Holder soundEvent, SoundSource soundSource, float volume, float pitch, long minVolume) { - sendSound(new EntityPos(this.player.get()), soundEvent, soundSource, volume, pitch, minVolume); - } - - public void sendSound(EntityPos position, Holder soundEvent, SoundSource soundSource, float volume, float pitch, long minVolume) { - this.player.get().connection.send(new ClientboundSoundPacket(soundEvent, soundSource, position.x, position.y, position.z, 16f * volume, pitch, minVolume)); - } - - public void stopSound() { - this.player.get().connection.send(new ClientboundStopSoundPacket(null, null)); - } - - public void sendTitle(String title, String sub, int in, int stay, int out) { - ServerPlayer serverPlayer = this.player.get(); - - serverPlayer.connection.send(new ClientboundSetTitlesAnimationPacket(in, stay, out)); - serverPlayer.connection.send(new ClientboundSetTitleTextPacket( - Component.literal(title))); - serverPlayer.connection.send(new ClientboundSetSubtitleTextPacket( - Component.literal(sub))); - } - - public void sendActionbar(String string){ - this.player.get().connection.send(new ClientboundSetActionBarTextPacket( - Component.literal(string)) - ); - } - - public void sendDefaultTitleLength() { - this.player.get().connection.send(new ClientboundSetTitlesAnimationPacket(10, 60, 20)); - } -} diff --git a/src/main/java/net/notcoded/codelib/server/CodeLibServer.java b/src/main/java/net/notcoded/codelib/server/CodeLibServer.java new file mode 100644 index 0000000..d8e355a --- /dev/null +++ b/src/main/java/net/notcoded/codelib/server/CodeLibServer.java @@ -0,0 +1,15 @@ +package net.notcoded.codelib.server; + +import net.fabricmc.api.DedicatedServerModInitializer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.server.MinecraftServer; + +@Environment(EnvType.SERVER) +public class CodeLibServer implements DedicatedServerModInitializer { + public static MinecraftServer server; + + @Override + public void onInitializeServer() { + } +} diff --git a/src/main/java/net/notcoded/codelib/mixins/server/MinecraftServerMixin.java b/src/main/java/net/notcoded/codelib/server/mixin/MinecraftServerMixin.java similarity index 78% rename from src/main/java/net/notcoded/codelib/mixins/server/MinecraftServerMixin.java rename to src/main/java/net/notcoded/codelib/server/mixin/MinecraftServerMixin.java index 55425bc..4427c49 100644 --- a/src/main/java/net/notcoded/codelib/mixins/server/MinecraftServerMixin.java +++ b/src/main/java/net/notcoded/codelib/server/mixin/MinecraftServerMixin.java @@ -1,8 +1,8 @@ -package net.notcoded.codelib.mixins.server; +package net.notcoded.codelib.server.mixin; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.notcoded.codelib.util.server.ServerUtils; +import net.notcoded.codelib.server.util.ServerUtils; import net.minecraft.server.MinecraftServer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -12,11 +12,12 @@ @Mixin(MinecraftServer.class) @Environment(EnvType.SERVER) +@SuppressWarnings({"UnusedMethod", "UnusedVariable"}) public class MinecraftServerMixin { @Unique boolean firstTickPassed = false; - @Inject(at = @At("HEAD"), method = "tickChildren") + @Inject(at = @At("HEAD"), method = "tick") private void tickHead(CallbackInfo ci) { if (!firstTickPassed) { firstTickPassed = true; diff --git a/src/main/java/net/notcoded/codelib/server/util/ServerUtils.java b/src/main/java/net/notcoded/codelib/server/util/ServerUtils.java new file mode 100644 index 0000000..a2ce7f1 --- /dev/null +++ b/src/main/java/net/notcoded/codelib/server/util/ServerUtils.java @@ -0,0 +1,71 @@ +package net.notcoded.codelib.server.util; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; +import net.notcoded.codelib.server.CodeLibServer; + +import java.util.List; + +import static net.notcoded.codelib.server.CodeLibServer.server; + +@Environment(EnvType.SERVER) +public class ServerUtils { + + public static void firstTick(MinecraftServer server) { + CodeLibServer.server = server; + } + + /** + * Runs a command as the server (console). + * Runs {@link #runCommand(String, boolean)} but with the giveFeedback parameter set to true. + * @param command The command. + * @return The command return value (1 is usually successful and 0 is unsuccessful) [WARNING ON >1.21: return value always returns 1] + */ + public static int runCommand(String command) { + return runCommand(command, true); + } + + /** + * Runs a command as the server (console). + * @param command The command. + * @param giveFeedback Whether it should output in console/to opped players. + * @return The command return value (1 is usually successful and 0 is unsuccessful) [WARNING ON >1.21: return value always returns 1] + */ + public static int runCommand(String command, boolean giveFeedback) { + ServerCommandSource commandSourceStack = server.getCommandSource(); + if(!giveFeedback) commandSourceStack.withSilent(); + + //? if <=1.18.2 { + /*return server.getCommandManager().execute(commandSourceStack, command); + *///?} else if >=1.19.4 { + /*? if <=1.20.1 {*/ /*return *//*?}*/ server.getCommandManager().executeWithPrefix(commandSourceStack, command); + //?} + + //? if >=1.21 { + return 1; + //?} + } + + /** + * Runs multiple commands as the server (console). + * Runs {@link #runCommands(List, boolean)}} but with the {@code giveFeedback} parameter set to true. + * @param commands The commands. + */ + + public static void runCommands(List commands) { + commands.forEach(ServerUtils::runCommand); + } + + /** + * Runs multiple commands as the server (console). + * Runs {@link #runCommand(String, boolean)} for each {@code String} in {@code List}. + * @param commands The commands. + * @param giveFeedback Whether it should output in console/to opped players. + */ + + public static void runCommands(List commands, boolean giveFeedback) { + commands.forEach(cmd -> runCommand(cmd, giveFeedback)); + } +} diff --git a/src/main/java/net/notcoded/codelib/server/util/structure/MapUtils.java b/src/main/java/net/notcoded/codelib/server/util/structure/MapUtils.java new file mode 100644 index 0000000..b7382e1 --- /dev/null +++ b/src/main/java/net/notcoded/codelib/server/util/structure/MapUtils.java @@ -0,0 +1,20 @@ +package net.notcoded.codelib.server.util.structure; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.util.Identifier; + +import java.io.File; + +@Environment(EnvType.SERVER) +public class MapUtils { + /** + * Gets the world name of a level. + * @param worldDirectoryName The world directory name (e.g. world [/world/...]) + * @param identifier The namespace (e.g. minecraft:overworld) + * @return If the file was deleted successfully + */ + public boolean deleteStructure(String worldDirectoryName, Identifier identifier) { + return new File(String.format("/%s/generated/%s/structures", worldDirectoryName, identifier.getNamespace()), identifier.getPath() + ".nbt").delete(); + } +} diff --git a/src/main/java/net/notcoded/codelib/server/util/structure/StructureMap.java b/src/main/java/net/notcoded/codelib/server/util/structure/StructureMap.java new file mode 100644 index 0000000..6048785 --- /dev/null +++ b/src/main/java/net/notcoded/codelib/server/util/structure/StructureMap.java @@ -0,0 +1,113 @@ +package net.notcoded.codelib.server.util.structure; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.notcoded.codelib.common.util.world.WorldUtil; +import net.notcoded.codelib.server.util.ServerUtils; +import org.jetbrains.annotations.NotNull; + +/** + * Uses Structure Blocks to paste a map using /setblock. + */ + +@SuppressWarnings("EmptyBlockTag") +@Environment(EnvType.SERVER) +public class StructureMap { + + // Default + public Identifier id; + public Rotation rotation; + public boolean cleanUp; + + // Parameters pre-set (without map) + public BlockPos placePos; + public BlockPos pastePos; + public boolean forceLoad; + + public StructureMap(@NotNull Identifier structureId, @NotNull Rotation rotation, boolean cleanUp) { + this.id = structureId; + this.rotation = rotation; + this.cleanUp = cleanUp; + } + + public StructureMap(@NotNull Identifier structureId, @NotNull Rotation rotation, boolean cleanUp, @NotNull BlockPos placePos, @NotNull BlockPos pastePos, boolean forceLoad) { + this.id = structureId; + this.rotation = rotation; + this.cleanUp = cleanUp; + + this.placePos = placePos; + this.pastePos = pastePos; + this.forceLoad = forceLoad; + } + + + /** + * Pastes a map. + * @param level The level where is going to get pasted in. + * @param placePos Where the structure block is going to get placed in. + * @param pastePos Where the map is going to get pasted in. + * @param forceLoad If the chunk should get force loaded. + */ + public void pasteMap(@NotNull World level, @NotNull BlockPos placePos, @NotNull BlockPos pastePos, boolean forceLoad) { + String start = "execute in " + WorldUtil.getStringWorldName(level); + + if(forceLoad) ServerUtils.runCommand(start + " run forceload add 0 0", false); + ServerUtils.runCommand(this.returnCommand(level, placePos, pastePos), false); + + if(this.cleanUp) { + ServerUtils.runCommand(String.format("%s run setblock %s %s %s minecraft:redstone_block", start, placePos.getX() + 1, placePos.getY(), placePos.getZ()), false); + + ServerUtils.runCommand(String.format("%s if block %s %s %s minecraft:structure_block run setblock %s %s %s air", start, placePos.getX(), placePos.getY(), placePos.getZ(), placePos.getX(), placePos.getY(), placePos.getZ()), false); + ServerUtils.runCommand(String.format("%s if block %s %s %s minecraft:redstone_block run setblock %s %s %s air", start, placePos.getX() + 1, placePos.getY(), placePos.getZ(), placePos.getX() + 1, placePos.getY(), placePos.getZ()), false); + } + } + + /** + * Pastes a map with some pre-set parameters. + * @param level The level where is going to get pasted in. + */ + public void pasteMap(@NotNull World level) { + if(this.placePos == null || this.pastePos == null) return; + this.pasteMap(level, this.placePos, this.pastePos, this.forceLoad); + } + + /** + * Returns a command which you can use in the console. + * @param level The level where is going to get pasted in. + * @param placePos Where the structure block is going to get placed in. + * @param pastePos Where the map is going to get pasted in. + * @return The command (/execute in dimension:name run setblock ...). + */ + public String returnCommand(@NotNull World level, @NotNull BlockPos placePos, @NotNull BlockPos pastePos) { + String start = "execute in " + WorldUtil.getStringWorldName(level); + String rotation = this.rotation != Rotation.NO_ROTATION ? ",rotation:\"" + this.rotation.id + "\"" : ""; + + return String.format("%s run setblock %s %s %s minecraft:structure_block{mode:'LOAD',name:'%s:%s',posX:%s,posY:%s,posZ:%s%s}", start, placePos.getX(), placePos.getY(), placePos.getZ(), this.id.getNamespace(), this.id.getPath(), pastePos.getX(), pastePos.getY(), pastePos.getZ(), rotation); + } + + /** + * Returns a command which you can use in the console. + * @param level The level where is going to get pasted in. + * @return The command (/execute in dimension:name run setblock ...). + */ + public String returnCommand(@NotNull World level) { + if(this.placePos == null || this.pastePos == null) return null; + return this.returnCommand(level, this.placePos, this.pastePos); + } + + public enum Rotation { + NO_ROTATION("0"), + CLOCKWISE_90("CLOCKWISE_90"), + CLOCKWISE_180("CLOCKWISE_180"), + COUNTERCLOCKWISE_90("COUNTERCLOCKWISE_90"); + + public final String id; + + Rotation(String id) { + this.id = id; + } + } +} \ No newline at end of file diff --git a/src/main/java/net/notcoded/codelib/util/item/BlockUtil.java b/src/main/java/net/notcoded/codelib/util/item/BlockUtil.java deleted file mode 100644 index 66903c8..0000000 --- a/src/main/java/net/notcoded/codelib/util/item/BlockUtil.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.notcoded.codelib.util.item; - -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -public class BlockUtil { - - /** - * Gets the block name, e.g. iron_block. - * @param blockState Block State. - * @return Block name. - */ - public static String blockToText(BlockState blockState) { - return blockToText(blockState.getBlock()); - } - - /** - * Gets the block name, e.g. iron_block - * @param block Block. - * @return Block name. - */ - public static String blockToText(Block block) { - String[] splitRegistryKey = BuiltInRegistries.BLOCK.getKey(block).toString().split(":"); - if (splitRegistryKey.length < 2) return splitRegistryKey[0]; - return splitRegistryKey[1]; - } - -} diff --git a/src/main/java/net/notcoded/codelib/util/item/ItemDisplayUtil.java b/src/main/java/net/notcoded/codelib/util/item/ItemDisplayUtil.java deleted file mode 100644 index c6d5d7b..0000000 --- a/src/main/java/net/notcoded/codelib/util/item/ItemDisplayUtil.java +++ /dev/null @@ -1,75 +0,0 @@ -package net.notcoded.codelib.util.item; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.world.item.ItemStack; - -public class ItemDisplayUtil { - - /** - * Adds lore to an item. - * @param itemStack ItemStack that should get the lore added onto. - * @param string The lore message. - * @param line The line. - */ - public static void addLore(ItemStack itemStack, String string, int line) { - CompoundTag compoundTag = itemStack.getOrCreateTag(); - CompoundTag display = compoundTag.getCompound("display"); - ListTag listTag = display.getList("Lore", 8); - - string = "{\"text\":\"" + string + "\"}"; - if (line < 0) { - listTag.add(listTag.size() + line + 1, StringTag.valueOf(string)); - } else { - listTag.add(line, StringTag.valueOf(string)); - } - - display.put("Lore", listTag); - compoundTag.put("display", display); - itemStack.setTag(compoundTag); - } - - /** - * Removes lore from an item. - * @param itemStack ItemStack that should get the lore removed. - * @param line The line that should get removed. - */ - - public static void removeLore(ItemStack itemStack, int line) { - CompoundTag compoundTag = itemStack.getOrCreateTag(); - CompoundTag display = compoundTag.getCompound("display"); - ListTag listTag = display.getList("Lore", 8); - - if (line < 0) { - if (!listTag.isEmpty()) listTag.remove(listTag.size() - 1); - } else { - if (listTag.size() > line) { - listTag.remove(line); - } - } - - if (!listTag.isEmpty()) display.put("Lore", listTag); - else display.remove("Lore"); - - if (!display.getAllKeys().isEmpty()) compoundTag.put("display", display); - else compoundTag.remove("display"); - - itemStack.setTag(compoundTag); - } - - /** - * Adds enchantment glint to an item. - * @param itemStack The ItemStack that should get the glint. - */ - public static void addGlint(ItemStack itemStack) { - try { - if (!itemStack.isEnchanted()) { - ListTag listTag = new ListTag(); - listTag.add(new CompoundTag()); - itemStack.getOrCreateTag().put("Enchantments", listTag); - } - } catch (Exception ignored) {} - } - -} diff --git a/src/main/java/net/notcoded/codelib/util/item/ItemStackUtil.java b/src/main/java/net/notcoded/codelib/util/item/ItemStackUtil.java deleted file mode 100644 index 96b5949..0000000 --- a/src/main/java/net/notcoded/codelib/util/item/ItemStackUtil.java +++ /dev/null @@ -1,144 +0,0 @@ -package net.notcoded.codelib.util.item; - -import net.minecraft.core.NonNullList; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.network.protocol.game.ServerboundContainerClickPacket; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.*; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentHelper; - -import java.util.ArrayList; -import java.util.Map; - -public class ItemStackUtil { - - /** - * Checks if the inventory has enough room to store an item. - * @return If the inventory has room for the item. - */ - public static boolean hasRoomFor(Inventory inventory, ItemStack itemStack) { - int count = itemStack.getCount(); - - for (ItemStack slot : inventory.items) { - if (slot.getItem() == Items.AIR) { - count -= 64; - } else if (isSameItem(slot, itemStack)) { - count -= 64 - slot.getCount(); - } - if (count <= 0) return true; - } - return false; - } - - /** - * Checks if the inventory has the item. - * @return If the inventory has the item. - */ - public static boolean hasItem(Inventory inventory, Item item) { - for (int i = 0; i < 41; i++) { - if (inventory.getItem(i).getItem() == item) return true; - } - return false; - } - - - /** - * Checks if the inventory has the same item. - * @param itemStack2 The original ItemStack. - * @param itemStack1 The ItemStack that's going to get compared. - * @return If the inventory has the same item. - */ - public static boolean isSameItem(ItemStack itemStack1, ItemStack itemStack2) { - if (itemStack1.getItem() != itemStack2.getItem()) return false; - - if (itemStack1.getTag() == null) { - return itemStack2.getTag() == null; - } else { - return itemStack1.getTag().equals(itemStack2.getTag()); - } - } - - /** - * Turns a string into an ItemStack, e.g. diamond_sword. - * @param string Name, e.g. diamond_sword. - * @return ItemStack. - */ - public static ItemStack stringToItemStack(String string) { - try { - String[] itemStack = string.split(" "); - String item = itemStack[itemStack.length-1]; - int amount = 1; - if (itemStack.length > 1) amount = Integer.parseInt(itemStack[0]); - - return new ItemStack(itemFromString(item), amount); - } catch (Exception exception) { - return null; - } - } - - /** - * Gets the ItemStack name, e.g. iron_block. - * @param itemStack ItemStack. - * @param reversible If the String can be turned back into an ItemStack with stringToItemStack. - * @return ItemStack name. - */ - public static String itemStackToString(ItemStack itemStack, boolean reversible) { - if(reversible){ - return itemStack.getCount() + " " + itemStack.getDescriptionId().split("\\.")[2]; - } - return itemStack.getDescriptionId(); - } - - /** - * Gets all the ItemStacks in the player's inventory. - * @param player The player. - * @return ItemStacks in ArrayList. - */ - public static ArrayList getInvItems(ServerPlayer player) { - ArrayList fullInv = new ArrayList<>(); - fullInv.addAll(player.getInventory().items); - fullInv.addAll(player.getInventory().armor); - fullInv.addAll(player.getInventory().offhand); - return fullInv; - } - - /** - * Gets the item name, e.g. diamond_sword. - * @param name The name. - * @return The Item (nullable). - */ - public static Item itemFromString(String name) { - name = name.toLowerCase(); - return BuiltInRegistries.ITEM.get(new ResourceLocation(name)); - } - - /** - * Enchants an ItemStack with an enchantment and level. - */ - public static void enchant(ItemStack itemStack, Enchantment enchantment, int level) { - Map enchantments = EnchantmentHelper.getEnchantments(itemStack); - if (level > 0) enchantments.put(enchantment, level); - else enchantments.remove(enchantment); - EnchantmentHelper.setEnchantments(enchantments, itemStack); - } - - /** - * Gets the ItemStack in the player's container click - * @return ItemStack. - */ - public static ItemStack getContainerClickItem(ServerPlayer player, ServerboundContainerClickPacket packet) { - int slot = packet.getSlotNum(); - - if (slot >= 0 && slot < player.containerMenu.slots.size()) { - return player.containerMenu.getSlot(slot).getItem(); - } else if (slot == -999) { - return player.containerMenu.getCarried(); - } else { - return null; - } - } -} diff --git a/src/main/java/net/notcoded/codelib/util/pos/BlockVec3.java b/src/main/java/net/notcoded/codelib/util/pos/BlockVec3.java deleted file mode 100644 index f2fcb77..0000000 --- a/src/main/java/net/notcoded/codelib/util/pos/BlockVec3.java +++ /dev/null @@ -1,91 +0,0 @@ -package net.notcoded.codelib.util.pos; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; - -public class BlockVec3 { - - public int x; - public int y; - public int z; - - public BlockVec3(int x, int y, int z) { - this.x = x; - this.y = y; - this.z = z; - } - - public BlockVec3(double x, double y, double z) { - this.x = (int)Math.floor(x); - this.y = (int)Math.floor(y); - this.z = (int)Math.floor(z); - } - - public BlockVec3(Vec3 vec3) { - this.x = (int)Math.floor(vec3.x); - this.y = (int)Math.floor(vec3.y); - this.z = (int)Math.floor(vec3.z); - } - - public BlockVec3(BlockPos blockPos) { - this.x = blockPos.getX(); - this.y = blockPos.getY(); - this.z = blockPos.getZ(); - } - - public BlockVec3(EntityPos entityPos) { - this.x = (int)Math.floor(entityPos.x); - this.y = (int)Math.floor(entityPos.y); - this.z = (int)Math.floor(entityPos.z); - } - - - public BlockVec3(Entity entity) { - this.x = (int)Math.floor(entity.getX()); - this.y = (int)Math.floor(entity.getY()); - this.z = (int)Math.floor(entity.getZ()); - } - - public BlockVec3 clone() { - return new BlockVec3(this.x, this.y, this.z); - } - - public BlockVec3 c() { - return this.clone(); - } - - public BlockVec3 add(int x, int y, int z) { - this.x += x; - this.y += y; - this.z += z; - return this; - } - - public BlockVec3 add(double x, double y, double z) { - return this.add((int)x, (int)y, (int)z ); - } - - public BlockVec3 add(BlockVec3 blockVec3) { - this.x += blockVec3.x; - this.y += blockVec3.y; - this.z += blockVec3.z; - return this; - } - - public BlockVec3 subtract(BlockVec3 blockVec3) { - this.x -= blockVec3.x; - this.y -= blockVec3.y; - this.z -= blockVec3.z; - return this; - } - - public BlockPos toBlockPos() { - return new BlockPos(this.x, this.y, this.z); - } - - public String toString() { - return "[x: " + this.x + ", y: " + this.y + ", z: " + this.z + "]"; - } - -} diff --git a/src/main/java/net/notcoded/codelib/util/pos/EntityPos.java b/src/main/java/net/notcoded/codelib/util/pos/EntityPos.java deleted file mode 100644 index e7fb726..0000000 --- a/src/main/java/net/notcoded/codelib/util/pos/EntityPos.java +++ /dev/null @@ -1,100 +0,0 @@ -package net.notcoded.codelib.util.pos; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; - -public class EntityPos { - - public double x; - public double y; - public double z; - public float yaw; - public float pitch; - - public EntityPos(double x, double y, double z, float yaw, float pitch) { - this.x = x; - this.y = y; - this.z = z; - this.yaw = yaw; - this.pitch = pitch; - } - - public EntityPos(double x, double y, double z) { - this(x, y, z, 0, 0); - } - - public EntityPos(Entity entity) { - this(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); - } - - public EntityPos(BlockPos blockPos) { - this(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - } - - public EntityPos(Vec3 vec3) { - this(vec3.x, vec3.y, vec3.z); - } - - public EntityPos clone() { - return new EntityPos(this.x, this.y, this.z, this.yaw, this.pitch); - } - - public EntityPos c() { - return this.clone(); - } - - public EntityPos add(double x, double y, double z) { - this.x += x; - this.y += y; - this.z += z; - return this; - } - - public EntityPos add(EntityPos entityPos) { - this.x += entityPos.x; - this.y += entityPos.y; - this.z += entityPos.z; - return this; - } - - public EntityPos between(EntityPos pos2) { - return new EntityPos((this.x + pos2.x) / 2, (this.y + pos2.y) / 2, (this.z + pos2.z) / 2); - } - - public BlockPos toBlockPos() { - return new BlockPos((int) this.x, (int) this.y, (int) this.z); - } - - public BlockVec3 toBlockVec3() { - return new BlockVec3(this.x, this.y, this.z); - } - - public double distance(EntityPos entityPos2) { - double x = this.x - entityPos2.x; - double y = this.y - entityPos2.y; - double z = this.z - entityPos2.z; - return Math.sqrt(x*x + y*y + z*z); - } - - @Environment(EnvType.SERVER) - public void teleportPlayer(ServerLevel level, ServerPlayer player) { - player.teleportTo(level, this.x, this.y,this.z,this.yaw,this.pitch); - } - - public String toString() { - return "[x: " + this.x + ", y: " + this.y + ", z: " + this.z + ", yaw: " + this.yaw + ", pitch: " + this.pitch + "]"; - } - - public boolean isInRadius(EntityPos entityPos2, float radius) { - double x = this.x - entityPos2.x; - double y = this.y - entityPos2.y; - double z = this.z - entityPos2.z; - return x*x + y*y + z*z <= radius*radius; - } - -} diff --git a/src/main/java/net/notcoded/codelib/util/pos/PositionUtil.java b/src/main/java/net/notcoded/codelib/util/pos/PositionUtil.java deleted file mode 100644 index fee829f..0000000 --- a/src/main/java/net/notcoded/codelib/util/pos/PositionUtil.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.notcoded.codelib.util.pos; - -import net.minecraft.core.BlockPos; -public class PositionUtil { - - /** - * Checks if the 2 block positions are in between one block position. - * @param corner1 Corner 1. - * @param corner2 Corner 2. - * @param between Position that is in between. - * @return If the block position is in between the 2 corners. - */ - public static boolean isBetween(BlockPos corner1, BlockPos corner2, BlockPos between) { - return corner1.getX() <= between.getX() && corner2.getX() >= between.getX() && - corner1.getY() <= between.getY() && corner2.getY() >= between.getY() && - corner1.getZ() <= between.getZ() && corner2.getZ() >= between.getZ(); - } -} diff --git a/src/main/java/net/notcoded/codelib/util/server/ServerUtils.java b/src/main/java/net/notcoded/codelib/util/server/ServerUtils.java deleted file mode 100644 index b5a90cb..0000000 --- a/src/main/java/net/notcoded/codelib/util/server/ServerUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.notcoded.codelib.util.server; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.server.MinecraftServer; -import net.notcoded.codelib.CodeLib; - -import java.util.ArrayList; - -import static net.notcoded.codelib.CodeLib.server; - -@Environment(EnvType.SERVER) -public class ServerUtils { - - public static void firstTick(MinecraftServer server) { - CodeLib.server = server; - } - - /** - * Runs a command as the server (console). - * @param command The command. - */ - public static void runCommand(String command) { - server.getCommands().performPrefixedCommand(server.createCommandSourceStack(), command); - } - - /** - * Runs multiple commands as the server (console). - * @param commands The commands. - */ - - public static void runCommands(ArrayList commands) { - commands.forEach(ServerUtils::runCommand); - } -} diff --git a/src/main/java/net/notcoded/codelib/util/string/StringUtils.java b/src/main/java/net/notcoded/codelib/util/string/StringUtils.java deleted file mode 100644 index 5ba3edb..0000000 --- a/src/main/java/net/notcoded/codelib/util/string/StringUtils.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.notcoded.codelib.util.string; - -public class StringUtils { - public static String firstArgumentToLowerCase(String input) { - String[] args = input.split(" ", 2); - args[0] = args[0].toLowerCase(); - return String.join(" ", args); - } -} diff --git a/src/main/java/net/notcoded/codelib/util/world/WorldUtil.java b/src/main/java/net/notcoded/codelib/util/world/WorldUtil.java deleted file mode 100644 index 9a003f2..0000000 --- a/src/main/java/net/notcoded/codelib/util/world/WorldUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.notcoded.codelib.util.world; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; - -public class WorldUtil { - /** - * Gets the world name of a level. - * @param level The level. - * @return The name of the world, e.g. minecraft:overworld - */ - public static String getWorldName(@NotNull Level level) { - return level.dimension().toString().replaceAll("dimension / ", "").replaceAll("]", "").replaceAll("ResourceKey\\[minecraft:", ""); - } - - /** - * Splits the world name. - * @param name The name - * @return ResourceLocation, e.g. minecraft (namespace) and overworld (path) - */ - public static ResourceLocation getWorldName(String name) { - String[] splitName = name.split(":"); - return new ResourceLocation(splitName[0], splitName[1]); - } - -} \ No newline at end of file diff --git a/src/main/java/net/notcoded/codelib/util/world/structure/MapUtils.java b/src/main/java/net/notcoded/codelib/util/world/structure/MapUtils.java deleted file mode 100644 index 4aaef2d..0000000 --- a/src/main/java/net/notcoded/codelib/util/world/structure/MapUtils.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.notcoded.codelib.util.world.structure; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.resources.ResourceLocation; - -import java.io.File; - -@Environment(EnvType.SERVER) -public class MapUtils { - public boolean deleteStructure(ResourceLocation identifier) { - return new File(String.format("/world/generated/%s/structures", identifier.getNamespace()), identifier.getPath() + ".nbt").delete(); - } -} diff --git a/src/main/java/net/notcoded/codelib/util/world/structure/Rotation.java b/src/main/java/net/notcoded/codelib/util/world/structure/Rotation.java deleted file mode 100644 index 721b399..0000000 --- a/src/main/java/net/notcoded/codelib/util/world/structure/Rotation.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.notcoded.codelib.util.world.structure; - -public class Rotation { - public String id; - - public static Rotation NO_ROTATION = new Rotation("0"); - - public static Rotation CLOCKWISE_90 = new Rotation("CLOCKWISE_90"); - - public static Rotation CLOCKWISE_180 = new Rotation("CLOCKWISE_180"); - - public static Rotation COUNTERCLOCKWISE_90 = new Rotation("COUNTERCLOCKWISE_90"); - - public Rotation(String id) { - this.id = id; - } -} diff --git a/src/main/java/net/notcoded/codelib/util/world/structure/StructureMap.java b/src/main/java/net/notcoded/codelib/util/world/structure/StructureMap.java deleted file mode 100644 index 4ff184c..0000000 --- a/src/main/java/net/notcoded/codelib/util/world/structure/StructureMap.java +++ /dev/null @@ -1,125 +0,0 @@ -package net.notcoded.codelib.util.world.structure; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.notcoded.codelib.util.server.ServerUtils; -import net.notcoded.codelib.util.world.WorldUtil; - -/** - * Uses Structure Blocks to paste a map using /setblock. - */ - -@Environment(EnvType.SERVER) -public class StructureMap { - - // Default - public ResourceLocation id; - public Rotation rotation; - public boolean cleanUp; - - // Parameters pre-set (without map) - public BlockPos placePos; - - public BlockPos pastePos; - - public boolean forceLoad; - - public StructureMap(ResourceLocation structureId, Rotation rotation, boolean cleanUp) { - this.id = structureId; - this.rotation = rotation; - this.cleanUp = cleanUp; - } - - public StructureMap(ResourceLocation structureId, Rotation rotation, boolean cleanUp, BlockPos placePos, BlockPos pastePos, boolean forceLoad) { - this.id = structureId; - this.rotation = rotation; - this.cleanUp = cleanUp; - - this.placePos = placePos; - this.pastePos = pastePos; - this.forceLoad = forceLoad; - } - - - /** - * Pastes a map. - * @param level The level where is going to get pasted in. - * @param placePos Where the structure block is going to get placed in. - * @param pastePos Where the map is going to get pasted in. - * @param forceLoad If the chunk should get force loaded. - */ - public void pasteMap(ServerLevel level, BlockPos placePos, BlockPos pastePos, boolean forceLoad) { - String stringRotation = this.rotation.id; - ResourceLocation name = WorldUtil.getWorldName(WorldUtil.getWorldName(level)); - String start = "execute in " + name.getNamespace() + ":" + name.getPath(); - - - if(forceLoad) ServerUtils.runCommand(start + " run forceload add 0 0"); - - if(!stringRotation.trim().isEmpty() && this.rotation != Rotation.NO_ROTATION) { - ServerUtils.runCommand(String.format("%s run setblock %s %s %s minecraft:structure_block{mode:'LOAD',name:'%s:%s',posX:%s,posY:%s,posZ:%s,rotation:\"%s\"}", start, placePos.getX(), placePos.getY(), placePos.getZ(), this.id.getNamespace(), this.id.getPath(), pastePos.getX(), pastePos.getY(), pastePos.getZ(), stringRotation)); - } else if(this.rotation == Rotation.NO_ROTATION){ - ServerUtils.runCommand(String.format("%s run setblock %s %s %s minecraft:structure_block{mode:'LOAD',name:'%s:%s',posX:%s,posY:%s,posZ:%s}", start, placePos.getX(), placePos.getY(), placePos.getZ(), this.id.getNamespace(), this.id.getPath(), pastePos.getX(), pastePos.getY(), pastePos.getZ())); - } - - if(this.cleanUp) { - ServerUtils.runCommand(String.format("%s run setblock %s %s %s minecraft:redstone_block", start, placePos.getX() + 1, placePos.getY(), placePos.getZ())); - - ServerUtils.runCommand(String.format("%s if block %s %s %s minecraft:structure_block run setblock %s %s %s air", start, placePos.getX(), placePos.getY(), placePos.getZ(), placePos.getX(), placePos.getY(), placePos.getZ())); - ServerUtils.runCommand(String.format("%s if block %s %s %s minecraft:redstone_block run setblock %s %s %s air", start, placePos.getX() + 1, placePos.getY(), placePos.getZ(), placePos.getX() + 1, placePos.getY(), placePos.getZ())); - } - } - - /** - * Pastes a map with some pre-set parameters. - * @param level The level where is going to get pasted in. - */ - public void pasteMap(ServerLevel level) { - String stringRotation = this.rotation.id; - ResourceLocation name = WorldUtil.getWorldName(WorldUtil.getWorldName(level)); - String start = "execute in " + name.getNamespace() + ":" + name.getPath(); - - ResourceLocation ResourceLocation = this.id; - BlockPos placePos = this.placePos; - BlockPos pastePos = this.pastePos; - boolean forceLoad = this.forceLoad; - - if(forceLoad) ServerUtils.runCommand(start + " run forceload add 0 0"); - - if(!stringRotation.trim().isEmpty() && this.rotation != Rotation.NO_ROTATION) { - ServerUtils.runCommand(String.format("%s run setblock %s %s %s minecraft:structure_block{mode:'LOAD',name:'%s:%s',posX:%s,posY:%s,posZ:%s,rotation:\"%s\"}", start, placePos.getX(), placePos.getY(), placePos.getZ(), ResourceLocation.getNamespace(), ResourceLocation.getPath(), pastePos.getX(), pastePos.getY(), pastePos.getZ(), stringRotation)); - } else if(this.rotation == Rotation.NO_ROTATION){ - ServerUtils.runCommand(String.format("%s run setblock %s %s %s minecraft:structure_block{mode:'LOAD',name:'%s:%s',posX:%s,posY:%s,posZ:%s}", start, placePos.getX(), placePos.getY(), placePos.getZ(), ResourceLocation.getNamespace(), ResourceLocation.getPath(), pastePos.getX(), pastePos.getY(), pastePos.getZ())); - } - - if(this.cleanUp) { - ServerUtils.runCommand(String.format("%s run setblock %s %s %s minecraft:redstone_block", start, placePos.getX() + 1, placePos.getY(), placePos.getZ())); - - ServerUtils.runCommand(String.format("%s if block %s %s %s minecraft:structure_block run setblock %s %s %s air", start, placePos.getX(), placePos.getY(), placePos.getZ(), placePos.getX(), placePos.getY(), placePos.getZ())); - ServerUtils.runCommand(String.format("%s if block %s %s %s minecraft:redstone_block run setblock %s %s %s air", start, placePos.getX() + 1, placePos.getY(), placePos.getZ(), placePos.getX() + 1, placePos.getY(), placePos.getZ())); - } - } - - /** - * Returns a command which you can use in the console. - * @param level The level where is going to get pasted in. - * @return The command (/setblock ...). - */ - public String returnCommand(ServerLevel level) { - ResourceLocation name = WorldUtil.getWorldName(WorldUtil.getWorldName(level)); - String start = "execute in " + name.getNamespace() + ":" + name.getPath(); - - ResourceLocation ResourceLocation = this.id; - BlockPos placePos = this.placePos; - BlockPos pastePos = this.pastePos; - - if(this.rotation != Rotation.NO_ROTATION) { - return String.format("%s run setblock %s %s %s minecraft:structure_block{mode:'LOAD',name:'%s:%s',posX:%s,posY:%s,posZ:%s,rotation:\"%s\"}", start, placePos.getX(), placePos.getY(), placePos.getZ(), ResourceLocation.getNamespace(), ResourceLocation.getPath(), pastePos.getX(), pastePos.getY(), pastePos.getZ(), this.rotation.id); - } else { - return String.format("%s run setblock %s %s %s minecraft:structure_block{mode:'LOAD',name:'%s:%s',posX:%s,posY:%s,posZ:%s}", start, placePos.getX(), placePos.getY(), placePos.getZ(), ResourceLocation.getNamespace(), ResourceLocation.getPath(), pastePos.getX(), pastePos.getY(), pastePos.getZ()); - } - } -} diff --git a/src/main/resources/codelib-client.mixins.json b/src/main/resources/codelib-client.mixins.json new file mode 100644 index 0000000..ddf245b --- /dev/null +++ b/src/main/resources/codelib-client.mixins.json @@ -0,0 +1,10 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.notcoded.codelib.client.mixin", + "compatibilityLevel": "JAVA_8", + "client": [], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/codelib.mixins.json b/src/main/resources/codelib-server.mixins.json similarity index 60% rename from src/main/resources/codelib.mixins.json rename to src/main/resources/codelib-server.mixins.json index 2fdd120..1e94131 100644 --- a/src/main/resources/codelib.mixins.json +++ b/src/main/resources/codelib-server.mixins.json @@ -1,12 +1,11 @@ { "required": true, "minVersion": "0.8", - "package": "net.notcoded.codelib.mixins", + "package": "net.notcoded.codelib.server.mixin", "compatibilityLevel": "JAVA_8", "server": [ - "server.MinecraftServerMixin" + "MinecraftServerMixin" ], - "client": [], "injectors": { "defaultRequire": 1 } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 0e0551d..4dfea5b 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -6,15 +6,18 @@ "name": "CodeLib", "description": "A Minecraft Fabric API/Library that provides useful features.", "entrypoints": { - "main": [ - "net.notcoded.codelib.CodeLib" + "client": [ + "net.notcoded.codelib.client.CodeLibClient" + ], + "server": [ + "net.notcoded.codelib.server.CodeLibServer" ] }, "authors": [ "NotCoded" ], "contact": { - "homepage": "https://notcoded.is-a.dev/", + "homepage": "https://modrinth.com/mod/codelib", "sources": "https://github.com/not-coded/codelib", "issues": "https://github.com/not-coded/codelib/issues" }, @@ -23,10 +26,13 @@ "environment": "*", "icon": "assets/codelib/logo.png", "mixins": [ - "codelib.mixins.json" + "codelib-server.mixins.json", + "codelib-client.mixins.json" ], "depends": { - "minecraft": ">=1.20" + "fabricloader": ">=0.13.3", + "minecraft": "${minecraftVersion}", + "java": ">=${javaVersion}" } } diff --git a/src/test/java/net/notcoded/codelibtest/CodeLibTest.java b/src/test/java/net/notcoded/codelibtest/CodeLibTest.java new file mode 100644 index 0000000..26f73d7 --- /dev/null +++ b/src/test/java/net/notcoded/codelibtest/CodeLibTest.java @@ -0,0 +1,10 @@ +package net.notcoded.codelibtest; + +import net.fabricmc.api.ModInitializer; + +public class CodeLibTest implements ModInitializer { + @Override + public void onInitialize() { + System.out.println("Hello World!"); + } +} diff --git a/src/test/java/net/notcoded/codelibtest/mixin/MinecraftClientMixin1165.java b/src/test/java/net/notcoded/codelibtest/mixin/MinecraftClientMixin1165.java new file mode 100644 index 0000000..4d6e567 --- /dev/null +++ b/src/test/java/net/notcoded/codelibtest/mixin/MinecraftClientMixin1165.java @@ -0,0 +1,19 @@ +package net.notcoded.codelibtest.mixin; + +import net.minecraft.client.MinecraftClient; +import net.notcoded.codelib.common.mixinhelper.annotation.MinecraftVersion; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@SuppressWarnings("all") +@MinecraftVersion(minecraft = {"1.16.5", "1.17.1"}) +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin1165 { + @Inject(at = @At("HEAD"), method = "run") + private void init(CallbackInfo info) { + // This code is injected into the start of MinecraftClient.run()V + System.out.println("This mixin is running on the minecraft version 1.16.5 or on 1.17.1!"); + } +} diff --git a/src/test/java/net/notcoded/codelibtest/mixin/MinecraftClientMixin121.java b/src/test/java/net/notcoded/codelibtest/mixin/MinecraftClientMixin121.java new file mode 100644 index 0000000..ce90d47 --- /dev/null +++ b/src/test/java/net/notcoded/codelibtest/mixin/MinecraftClientMixin121.java @@ -0,0 +1,19 @@ +package net.notcoded.codelibtest.mixin; + +import net.minecraft.client.MinecraftClient; +import net.notcoded.codelib.common.mixinhelper.annotation.MinecraftVersion; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@SuppressWarnings("all") +@MinecraftVersion(minecraft = {">=1.19", "<=1.21"}) +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin121 { + @Inject(at = @At("HEAD"), method = "run") + private void init(CallbackInfo info) { + // This code is injected into the start of MinecraftClient.run()V + System.out.println("This mixin is running on the minecraft version that is above (or equal to) 1.19 but under (or equal to) 1.21"); + } +} diff --git a/src/test/resources/codelib-test.mixins.json b/src/test/resources/codelib-test.mixins.json new file mode 100644 index 0000000..eca6153 --- /dev/null +++ b/src/test/resources/codelib-test.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.notcoded.codelibtest.mixin", + "compatibilityLevel": "JAVA_8", + "client": [ + "MinecraftClientMixin1165", + "MinecraftClientMixin121" + ], + "injectors": { + "defaultRequire": 1 + }, + "plugin": "net.notcoded.codelib.common.mixinhelper.MixinPlugin" +} \ No newline at end of file diff --git a/src/test/resources/fabric.mod.json b/src/test/resources/fabric.mod.json new file mode 100644 index 0000000..d0c717d --- /dev/null +++ b/src/test/resources/fabric.mod.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": 1, + "id": "codelib-test", + "version": "1.0.0", + + "name": "CodeLib Test", + "description": "Testing CodeLib", + "entrypoints": { + "main": [ + "net.notcoded.codelibtest.CodeLibTest" + ] + }, + "authors": [ + "NotCoded" + ], + + "environment": "*", + "mixins": ["codelib-test.mixins.json"], + "depends": { + "minecraft": "*", + "codelib": "*" + } +} diff --git a/stonecutter.gradle.kts b/stonecutter.gradle.kts new file mode 100644 index 0000000..37c28a1 --- /dev/null +++ b/stonecutter.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("dev.kikugie.stonecutter") +} +stonecutter active "1.21" /* [SC] DO NOT EDIT */ + +stonecutter registerChiseled tasks.register("chiseledBuild", stonecutter.chiseled) { + group = "project" + ofTask("buildAndCollect") +} + +stonecutter registerChiseled tasks.register("chiseledModrinth", stonecutter.chiseled) { + group = "project" + ofTask("modrinth") +} diff --git a/versions/1.16.5/gradle.properties b/versions/1.16.5/gradle.properties new file mode 100644 index 0000000..15c6886 --- /dev/null +++ b/versions/1.16.5/gradle.properties @@ -0,0 +1,12 @@ +# See latest at https://fabricmc.net/develop/ +deps.minecraft=1.16.5 +deps.yarn_mappings=1.16.5+build.10 +deps.java=8 + +mod.version_name=1.16.5 + +mod.min_target=1.16 +mod.max_target=1.16.5 + +# TODO: figure out what versions it supports +publishing.supported_versions=1.16,1.16.1,1.16.2,1.16.3,1.16.4,1.16.5 \ No newline at end of file diff --git a/versions/1.17.1/gradle.properties b/versions/1.17.1/gradle.properties new file mode 100644 index 0000000..b1fdf87 --- /dev/null +++ b/versions/1.17.1/gradle.properties @@ -0,0 +1,12 @@ +# See latest at https://fabricmc.net/develop/ +deps.minecraft=1.17.1 +deps.yarn_mappings=1.17.1+build.65 +deps.java=8 + +mod.version_name=1.17.1 + +mod.min_target=1.17 +mod.max_target=1.17.1 + +# TODO: figure out what versions it supports +publishing.supported_versions=1.17,1.17.1 \ No newline at end of file diff --git a/versions/1.18.2/gradle.properties b/versions/1.18.2/gradle.properties new file mode 100644 index 0000000..49989d7 --- /dev/null +++ b/versions/1.18.2/gradle.properties @@ -0,0 +1,13 @@ +# See latest at https://fabricmc.net/develop/ +deps.minecraft=1.18.2 +deps.yarn_mappings=1.18.2+build.4 +deps.java=17 + +mod.version_name=1.18.2 + +mod.min_target=1.18 +mod.max_target=1.18.2 + +# TODO: figure out what versions it supports +# as it seems 1.17 and 1.18 are compatible +publishing.supported_versions=1.18,1.18.1,1.18.2 \ No newline at end of file diff --git a/versions/1.19.4/gradle.properties b/versions/1.19.4/gradle.properties new file mode 100644 index 0000000..25fbc2e --- /dev/null +++ b/versions/1.19.4/gradle.properties @@ -0,0 +1,12 @@ +# See latest at https://fabricmc.net/develop/ +deps.minecraft=1.19.4 +deps.yarn_mappings=1.19.4+build.2 +deps.java=17 + +mod.version_name=1.19.4 + +mod.min_target=1.19 +mod.max_target=1.19.4 + +# TODO: figure out what versions it supports +publishing.supported_versions=1.19,1.19.1,1.19.2,1.19.3,1.19.4 \ No newline at end of file diff --git a/versions/1.20.1/gradle.properties b/versions/1.20.1/gradle.properties new file mode 100644 index 0000000..7318cbb --- /dev/null +++ b/versions/1.20.1/gradle.properties @@ -0,0 +1,12 @@ +# See latest at https://fabricmc.net/develop/ +deps.minecraft=1.20.1 +deps.yarn_mappings=1.20.1+build.10 +deps.java=17 + +mod.version_name=1.20.1 + +mod.min_target=1.20 +mod.max_target=1.20.1 + +# TODO: figure out what versions it supports +publishing.supported_versions=1.20,1.20.1 \ No newline at end of file diff --git a/versions/1.21/gradle.properties b/versions/1.21/gradle.properties new file mode 100644 index 0000000..43cf931 --- /dev/null +++ b/versions/1.21/gradle.properties @@ -0,0 +1,12 @@ +# See latest at https://fabricmc.net/develop/ +deps.minecraft=1.21 +deps.yarn_mappings=1.21+build.9 +deps.java=17 + +mod.version_name=1.21 + +mod.min_target=1.21 +mod.max_target=1.22 + +# TODO: figure out what versions it supports +publishing.supported_versions=1.20.2,1.20.3,1.20.4,1.20.5,1.20.6,1.21,1.21.1,1.21.2,1.21.3,1.21.4 \ No newline at end of file