├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
└── main
├── java
└── one
│ └── pouekdev
│ └── coordinatelist
│ ├── CList.java
│ ├── CListClient.java
│ ├── CListCommand.java
│ ├── CListConfig.java
│ ├── CListData.java
│ ├── CListDelayedEvent.java
│ ├── CListRenderLayers.java
│ ├── CListVariables.java
│ ├── CListWaypoint.java
│ ├── CListWaypointColor.java
│ ├── CListWaypointConfig.java
│ ├── CListWaypointScreen.java
│ └── mixin
│ └── CListChatGrabber.java
└── resources
├── assets
└── coordinatelist
│ ├── icon.png
│ ├── lang
│ ├── de_de.json
│ ├── en_us.json
│ ├── ja_jp.json
│ ├── pl_pl.json
│ ├── pt_br.json
│ ├── ru_ru.json
│ └── zh_cn.json
│ ├── skull.png
│ ├── textures
│ └── gui
│ │ └── sprites
│ │ └── icon
│ │ ├── change.png
│ │ ├── not_visible.png
│ │ └── visible.png
│ └── waypoint_icon.png
├── coordinatelist.mixins.json
└── fabric.mod.json
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | # Automatically build the project and run any configured tests for every push
2 | # and submitted pull request. This can help catch issues that only occur on
3 | # certain platforms or Java versions, and provides a first line of defence
4 | # against bad commits.
5 |
6 | name: build
7 | on: [pull_request, push, workflow_dispatch]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-24.04
12 | steps:
13 | - name: checkout repository
14 | uses: actions/checkout@v4
15 | - name: validate gradle wrapper
16 | uses: gradle/actions/wrapper-validation@v4
17 | - name: setup jdk
18 | uses: actions/setup-java@v4
19 | with:
20 | java-version: '21'
21 | distribution: 'microsoft'
22 | - name: make gradle wrapper executable
23 | run: chmod +x ./gradlew
24 | - name: build
25 | run: ./gradlew build
26 | - name: capture build artifacts
27 | uses: actions/upload-artifact@v4
28 | with:
29 | name: Artifacts
30 | path: build/libs/
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # gradle
2 |
3 | .gradle/
4 | build/
5 | out/
6 | classes/
7 |
8 | # eclipse
9 |
10 | *.launch
11 |
12 | # idea
13 |
14 | .idea/
15 | *.iml
16 | *.ipr
17 | *.iws
18 |
19 | # vscode
20 |
21 | .settings/
22 | .vscode/
23 | bin/
24 | .classpath
25 | .project
26 |
27 | # macos
28 |
29 | *.DS_Store
30 |
31 | # fabric
32 |
33 | run/
34 |
35 | # java
36 |
37 | hs_err_*.log
38 | replay_*.log
39 | *.hprof
40 | *.jfr
41 |
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Jakub Starostecki
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # CList
4 | Coordinate List (CList for short) is a simple minimalistic fabric mod for saving your coordinates. No minimaps. Just a list with in-game waypoints.
5 |
6 |
7 |
8 | ---
9 |
10 | (If you want to help and know any other language than English you can help by translating the mod [here](https://github.com/PouekDEV/CList) by making a pull request)
11 |
12 | ## Features
13 | - Hotkey for placing a waypoint in the current position
14 | - Automatic waypoints in the place where you died
15 | - Copying the waypoint coordinates to the clipboard
16 | - Toggling waypoint visibility
17 | - Changing the size of the waypoint to your liking
18 | - Changing the color of the waypoint to your liking
19 | - Setting the maximum rendering distance for waypoints
20 | - Detecting coordinates from chat
21 | - Available in multiple languages
22 | - **No minimap**
23 |
24 | ### The idea behind it
25 | I initially created this mod just for me and my friends. I'm not too fond of these waypoint mods which always have built-in minimap which lagged my game even when it was off. So I made my own mod to fulfill the need for a lightweight, minimalistic waypoint mod.
26 |
27 | ### Support
28 | CList will always receive latest features for the latest version of the game. Porting the newest features to older Minecraft versions is not planned so before creating an issue check if the feature you want isn't already implemented in the latest version of the mod.
29 |
30 | Forge/NeoForge is not planned, but it seems that [Sinytra Connector](https://modrinth.com/mod/connector) does a pretty good job if you want to use CList on Forge/NeoForge.
31 |
32 | You can freely include CList in any mod packs.
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'fabric-loom' version '1.10-SNAPSHOT'
3 | id 'maven-publish'
4 | }
5 |
6 | version = project.mod_version
7 | group = project.maven_group
8 |
9 | base {
10 | archivesName = project.archives_base_name
11 | }
12 |
13 | repositories {
14 | maven { url = "https://api.modrinth.com/maven" }
15 | // Add repositories to retrieve artifacts from in here.
16 | // You should only use this when depending on other mods because
17 | // Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
18 | // See https://docs.gradle.org/current/userguide/declaring_repositories.html
19 | // for more information about repositories.
20 | }
21 |
22 | dependencies {
23 | // To change the versions see the gradle.properties file
24 | minecraft "com.mojang:minecraft:${project.minecraft_version}"
25 | mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
26 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
27 |
28 | // Fabric API. This is technically optional, but you probably want it anyway.
29 | modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
30 | modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}"
31 | include "maven.modrinth:midnightlib:${project.midnightlib_version}"
32 | }
33 |
34 | processResources {
35 | inputs.property "version", project.version
36 |
37 | filesMatching("fabric.mod.json") {
38 | expand "version": inputs.properties.version
39 | }
40 | }
41 |
42 | tasks.withType(JavaCompile).configureEach {
43 | // Minecraft 1.18 (1.18-pre2) upwards uses Java 17.
44 | // The new Minecraft 1.20.5 upwards uses Java 21
45 | it.options.release = 21
46 | }
47 |
48 | java {
49 | // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
50 | // if it is present.
51 | // If you remove this line, sources will not be generated.
52 | withSourcesJar()
53 |
54 | sourceCompatibility = JavaVersion.VERSION_21
55 | targetCompatibility = JavaVersion.VERSION_21
56 | }
57 |
58 | jar {
59 | inputs.property "archivesName", project.base.archivesName
60 |
61 | from("LICENSE") {
62 | rename { "${it}_${inputs.properties.archivesName}"}
63 | }
64 | }
65 |
66 | // configure the maven publication
67 | publishing {
68 | publications {
69 | create("mavenJava", MavenPublication) {
70 | artifactId = project.archives_base_name
71 | from components.java
72 | }
73 | }
74 |
75 | // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
76 | repositories {
77 | // Add repositories to publish to here.
78 | // Notice: This block does NOT have the same function as the block in the top level.
79 | // The repositories here will be used for publishing your artifact, not for
80 | // retrieving dependencies.
81 | }
82 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Done to increase the memory available to gradle.
2 | org.gradle.jvmargs=-Xmx1G
3 | org.gradle.parallel=true
4 |
5 | # Fabric Properties
6 | # check these on https://fabricmc.net/develop
7 | minecraft_version=1.21.5
8 | yarn_mappings=1.21.5+build.1
9 | loader_version=0.16.10
10 |
11 | # Mod Properties
12 | mod_version = 1.7.2-1.21.5
13 | maven_group = one.pouekdev
14 | archives_base_name = coordinatelist
15 |
16 | # Dependencies
17 | fabric_version=0.119.5+1.21.5
18 | midnightlib_version=1.7.1+1.21.4-fabric
19 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PouekDEV/CList/0b29e293fb68139f4c4803f1102d12351f0bea13/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | # This is normally unused
84 | # shellcheck disable=SC2034
85 | APP_BASE_NAME=${0##*/}
86 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
87 |
88 | # Use the maximum available, or set MAX_FD != -1 to use that value.
89 | MAX_FD=maximum
90 |
91 | warn () {
92 | echo "$*"
93 | } >&2
94 |
95 | die () {
96 | echo
97 | echo "$*"
98 | echo
99 | exit 1
100 | } >&2
101 |
102 | # OS specific support (must be 'true' or 'false').
103 | cygwin=false
104 | msys=false
105 | darwin=false
106 | nonstop=false
107 | case "$( uname )" in #(
108 | CYGWIN* ) cygwin=true ;; #(
109 | Darwin* ) darwin=true ;; #(
110 | MSYS* | MINGW* ) msys=true ;; #(
111 | NONSTOP* ) nonstop=true ;;
112 | esac
113 |
114 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
115 |
116 |
117 | # Determine the Java command to use to start the JVM.
118 | if [ -n "$JAVA_HOME" ] ; then
119 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
120 | # IBM's JDK on AIX uses strange locations for the executables
121 | JAVACMD=$JAVA_HOME/jre/sh/java
122 | else
123 | JAVACMD=$JAVA_HOME/bin/java
124 | fi
125 | if [ ! -x "$JAVACMD" ] ; then
126 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
127 |
128 | Please set the JAVA_HOME variable in your environment to match the
129 | location of your Java installation."
130 | fi
131 | else
132 | JAVACMD=java
133 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
134 |
135 | Please set the JAVA_HOME variable in your environment to match the
136 | location of your Java installation."
137 | fi
138 |
139 | # Increase the maximum file descriptors if we can.
140 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
141 | case $MAX_FD in #(
142 | max*)
143 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
144 | # shellcheck disable=SC3045
145 | MAX_FD=$( ulimit -H -n ) ||
146 | warn "Could not query maximum file descriptor limit"
147 | esac
148 | case $MAX_FD in #(
149 | '' | soft) :;; #(
150 | *)
151 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
152 | # shellcheck disable=SC3045
153 | ulimit -n "$MAX_FD" ||
154 | warn "Could not set maximum file descriptor limit to $MAX_FD"
155 | esac
156 | fi
157 |
158 | # Collect all arguments for the java command, stacking in reverse order:
159 | # * args from the command line
160 | # * the main class name
161 | # * -classpath
162 | # * -D...appname settings
163 | # * --module-path (only if needed)
164 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
165 |
166 | # For Cygwin or MSYS, switch paths to Windows format before running java
167 | if "$cygwin" || "$msys" ; then
168 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
169 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
170 |
171 | JAVACMD=$( cygpath --unix "$JAVACMD" )
172 |
173 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
174 | for arg do
175 | if
176 | case $arg in #(
177 | -*) false ;; # don't mess with options #(
178 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
179 | [ -e "$t" ] ;; #(
180 | *) false ;;
181 | esac
182 | then
183 | arg=$( cygpath --path --ignore --mixed "$arg" )
184 | fi
185 | # Roll the args list around exactly as many times as the number of
186 | # args, so each arg winds up back in the position where it started, but
187 | # possibly modified.
188 | #
189 | # NB: a `for` loop captures its iteration list before it begins, so
190 | # changing the positional parameters here affects neither the number of
191 | # iterations, nor the values presented in `arg`.
192 | shift # remove old arg
193 | set -- "$@" "$arg" # push replacement arg
194 | done
195 | fi
196 |
197 |
198 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
199 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
200 |
201 | # Collect all arguments for the java command;
202 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
203 | # shell script including quotes and variable substitutions, so put them in
204 | # double quotes to make sure that they get re-expanded; and
205 | # * put everything else in single quotes, so that it's not re-expanded.
206 |
207 | set -- \
208 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
209 | -classpath "$CLASSPATH" \
210 | org.gradle.wrapper.GradleWrapperMain \
211 | "$@"
212 |
213 | # Stop when "xargs" is not available.
214 | if ! command -v xargs >/dev/null 2>&1
215 | then
216 | die "xargs is not available"
217 | fi
218 |
219 | # Use "xargs" to parse quoted args.
220 | #
221 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
222 | #
223 | # In Bash we could simply go:
224 | #
225 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
226 | # set -- "${ARGS[@]}" "$@"
227 | #
228 | # but POSIX shell has neither arrays nor command substitution, so instead we
229 | # post-process each arg (as a line of input to sed) to backslash-escape any
230 | # character that might be a shell metacharacter, then use eval to reverse
231 | # that process (while maintaining the separation between arguments), and wrap
232 | # the whole thing up as a single "set" statement.
233 | #
234 | # This will of course break if any of these variables contains a newline or
235 | # an unmatched quote.
236 | #
237 |
238 | eval "set -- $(
239 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
240 | xargs -n1 |
241 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
242 | tr '\n' ' '
243 | )" '"$@"'
244 |
245 | exec "$JAVACMD" "$@"
246 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | maven {
4 | name = 'Fabric'
5 | url = 'https://maven.fabricmc.net/'
6 | }
7 | mavenCentral()
8 | gradlePluginPortal()
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CList.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import eu.midnightdust.lib.config.MidnightConfig;
4 | import net.fabricmc.api.ModInitializer;
5 | import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class CList implements ModInitializer {
10 | public static final String MOD_ID = "coordinatelist";
11 | public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
12 | @Override
13 | public void onInitialize() {
14 | MidnightConfig.init(MOD_ID, CListConfig.class);
15 | ClientCommandRegistrationCallback.EVENT.register(new CListCommand());
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListClient.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import com.mojang.blaze3d.vertex.VertexFormat;
4 | import net.fabricmc.api.ClientModInitializer;
5 | import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
6 | import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
7 | import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
8 | import net.minecraft.client.font.TextRenderer;
9 | import net.minecraft.client.option.KeyBinding;
10 | import net.minecraft.client.render.*;
11 | import net.minecraft.client.util.InputUtil;
12 | import net.minecraft.client.util.math.MatrixStack;
13 | import net.minecraft.client.world.ClientWorld;
14 | import net.minecraft.entity.player.PlayerEntity;
15 | import net.minecraft.text.Text;
16 | import net.minecraft.util.Identifier;
17 | import net.minecraft.util.math.MathHelper;
18 | import net.minecraft.util.math.RotationAxis;
19 | import net.minecraft.util.math.Vec3d;
20 | import org.apache.commons.lang3.StringUtils;
21 | import org.joml.Matrix4f;
22 | import org.lwjgl.glfw.GLFW;
23 | import eu.midnightdust.lib.config.MidnightConfig;
24 |
25 | import java.util.List;
26 | import java.util.Objects;
27 | import java.util.Random;
28 |
29 | public class CListClient implements ClientModInitializer {
30 | public static CListVariables variables = new CListVariables();
31 | static Random rand = new Random();
32 | KeyBinding open_waypoints_keybind;
33 | KeyBinding add_a_waypoint;
34 | KeyBinding toggle_visibility;
35 | public float calculateWaypointSize(){
36 | return 0.5f * (CListConfig.multiplier/10.0f);
37 | }
38 | public float calculateTextSize(){
39 | return 15f * (CListConfig.multiplier/10.0f);
40 | }
41 | public float distanceTo(CListWaypoint waypoint) {
42 | float f = (float)(CListVariables.minecraft_client.player.getX() - waypoint.x);
43 | float g = (float)(CListVariables.minecraft_client.player.getY() - waypoint.y);
44 | float h = (float)(CListVariables.minecraft_client.player.getZ() - waypoint.z);
45 | return Math.round(MathHelper.sqrt(f * f + g * g + h * h));
46 | }
47 | public Vec3d calculateRenderCoords(CListWaypoint waypoint, Camera camera, float distance) {
48 | float px = (float)camera.getPos().x;
49 | float py = (float)camera.getPos().y;
50 | float pz = (float)camera.getPos().z;
51 | float wx = waypoint.x;
52 | float wy = waypoint.y;
53 | float wz = waypoint.z;
54 | float vx = wx - px;
55 | float vy = wy - py;
56 | float vz = wz - pz;
57 | float vector_len = (float)Math.sqrt((vx*vx) + (vy*vy) + (vz*vz));
58 | float radius = 32;
59 | float scx = radius / vector_len * vx;
60 | float scy = radius / vector_len * vy;
61 | float scz = radius / vector_len * vz;
62 | float prx, pry, prz;
63 | if (distance > 32) {
64 | prx = scx + px;
65 | pry = scy + py;
66 | prz = scz + pz;
67 | }
68 | else {
69 | prx = wx;
70 | pry = wy;
71 | prz = wz;
72 | }
73 | return new Vec3d(prx,pry,prz);
74 | }
75 | @Override
76 | public void onInitializeClient() {
77 | open_waypoints_keybind = KeyBindingHelper.registerKeyBinding(new KeyBinding(
78 | "keybinds.waypoints.menu",
79 | InputUtil.Type.KEYSYM,
80 | GLFW.GLFW_KEY_M,
81 | "keybinds.category.name"
82 | ));
83 | add_a_waypoint = KeyBindingHelper.registerKeyBinding(new KeyBinding(
84 | "keybinds.waypoint.add",
85 | InputUtil.Type.KEYSYM,
86 | GLFW.GLFW_KEY_B,
87 | "keybinds.category.name"
88 | ));
89 | toggle_visibility = KeyBindingHelper.registerKeyBinding(new KeyBinding(
90 | "keybinds.waypoints.toggle",
91 | InputUtil.Type.KEYSYM,
92 | GLFW.GLFW_KEY_J,
93 | "keybinds.category.name"
94 | ));
95 | WorldRenderEvents.END.register(context ->{
96 | if (!variables.waypoints.isEmpty() && CListConfig.waypoints_toggled && !CListVariables.minecraft_client.options.hudHidden) {
97 | for(int i = 0; i < variables.waypoints.size(); i++){
98 | CListWaypoint waypoint = variables.waypoints.get(i);
99 | int distance_without_decimal_places = (int) distanceTo(waypoint);
100 | if(Objects.equals(waypoint.getDimensionString(), getDimension(String.valueOf(variables.last_world.getDimension().effects()))) && waypoint.render && (CListConfig.render_distance == 0 || CListConfig.render_distance >= distance_without_decimal_places)) {
101 | Camera camera = context.camera();
102 | float size = calculateWaypointSize();
103 | Vec3d renderCoords = calculateRenderCoords(waypoint, camera, distance_without_decimal_places);
104 | Vec3d targetPosition = new Vec3d(renderCoords.x, renderCoords.y+1, renderCoords.z);
105 | Vec3d transformedPosition = targetPosition.subtract(camera.getPos());
106 | MatrixStack matrixStack = new MatrixStack();
107 | matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch()));
108 | matrixStack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(camera.getYaw() + 180.0F));
109 | matrixStack.translate(transformedPosition.x, transformedPosition.y, transformedPosition.z);
110 | matrixStack.multiply(camera.getRotation());
111 | matrixStack.scale(-size, size, size);
112 | Matrix4f positionMatrix = matrixStack.peek().getPositionMatrix();
113 | Tessellator tessellator = Tessellator.getInstance();
114 | BufferBuilder buffer = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR);
115 | buffer.vertex(positionMatrix, 0, 1, 0).color(variables.colors.get(i).r, variables.colors.get(i).g, variables.colors.get(i).b, 1f).texture(0f, 0f);
116 | buffer.vertex(positionMatrix, 0, 0, 0).color(variables.colors.get(i).r, variables.colors.get(i).g, variables.colors.get(i).b, 1f).texture(0f, 1f);
117 | buffer.vertex(positionMatrix, 1, 0, 0).color(variables.colors.get(i).r, variables.colors.get(i).g, variables.colors.get(i).b, 1f).texture(1f, 1f);
118 | buffer.vertex(positionMatrix, 1, 1, 0).color(variables.colors.get(i).r, variables.colors.get(i).g, variables.colors.get(i).b, 1f).texture(1f, 0f);
119 | Identifier icon;
120 | if(waypoint.deathpoint){
121 | icon = Identifier.of("coordinatelist", "skull.png");
122 | }
123 | else {
124 | icon = Identifier.of("coordinatelist", "waypoint_icon.png");
125 | }
126 | CListRenderLayers.POSITION_TEX_COLOR.apply(icon).draw(buffer.end());
127 | TextRenderer textRenderer = CListVariables.minecraft_client.textRenderer;
128 | String labelText = waypoint.name + " (" + distance_without_decimal_places + " m)";
129 | int textWidth = textRenderer.getWidth(labelText);
130 | matrixStack.scale(-0.025f, -0.025f, 0.025f);
131 | size = calculateTextSize();
132 | matrixStack.scale((float) Math.log(size * 4), (float) Math.log(size * 4), (float) Math.log(size * 4));
133 | matrixStack.translate(0,-20,0);
134 | positionMatrix = matrixStack.peek().getPositionMatrix();
135 | float h = (float) (-textWidth/2);
136 | VertexConsumerProvider.Immediate v = CListVariables.minecraft_client.getBufferBuilders().getEntityVertexConsumers();
137 | if(CListConfig.waypoint_text_background) {
138 | textRenderer.draw(labelText, h, 0, 0xFFFFFF, false, positionMatrix, v, TextRenderer.TextLayerType.SEE_THROUGH, 0x90000000, LightmapTextureManager.MAX_LIGHT_COORDINATE);
139 | }
140 | else{
141 | textRenderer.draw(labelText, h, 0, 0xFFFFFF, false, positionMatrix, v, TextRenderer.TextLayerType.SEE_THROUGH, 0x00000000, LightmapTextureManager.MAX_LIGHT_COORDINATE);
142 | }
143 | v.draw();
144 | }
145 | }
146 | }
147 | });
148 | ClientTickEvents.END_CLIENT_TICK.register(client -> {
149 | if(!CListVariables.delayed_events.isEmpty()){
150 | for(CListDelayedEvent event: CListVariables.delayed_events){
151 | boolean destroy = event.update();
152 | if(destroy){
153 | CListVariables.delayed_events.remove(event);
154 | break;
155 | }
156 | }
157 | }
158 | while (open_waypoints_keybind.wasPressed()) {
159 | client.setScreen(new CListWaypointScreen(Text.literal("Waypoints")));
160 | }
161 | while(add_a_waypoint.wasPressed()){
162 | if(!Objects.equals(client.currentScreen, new CListWaypointScreen(Text.literal("Waypoints")))){
163 | PlayerEntity player = CListVariables.minecraft_client.player;
164 | addNewWaypoint((int) Math.round(player.getX()), (int) Math.round(player.getY()), (int) Math.round(player.getZ()),false);
165 | }
166 | }
167 | while(toggle_visibility.wasPressed()){
168 | CListConfig.waypoints_toggled = !CListConfig.waypoints_toggled;
169 | MidnightConfig.write(CList.MOD_ID);
170 | }
171 | if (client.world == null) {
172 | variables.loaded_last_world = false;
173 | variables.waypoints.clear();
174 | variables.colors.clear();
175 | variables.worldName = null;
176 | variables.last_world = null;
177 | variables.is_world_error = false;
178 | }
179 | else{
180 | if(!variables.is_world_error){
181 | try{
182 | variables.last_world = client.world;
183 | checkForWorldChanges(variables.last_world);
184 | checkIfSaveIsNeeded(false);
185 | if (client.isInSingleplayer()) {
186 | variables.worldName = client.getServer().getSaveProperties().getLevelName();
187 | } else {
188 | if(client.getCurrentServerEntry().isRealm()) {
189 | variables.worldName = client.getCurrentServerEntry().name;
190 | }
191 | else {
192 | variables.worldName = client.getCurrentServerEntry().address;
193 | variables.worldName = variables.worldName.replace(":","P");
194 | }
195 | }
196 | if(!client.player.isAlive() && !variables.had_death_waypoint_placed && CListConfig.can_place_deathpoints){
197 | PlayerEntity player = client.player;
198 | addNewWaypoint((int) Math.round(player.getX()), (int) Math.round(player.getY()), (int) Math.round(player.getZ()),true);
199 | variables.had_death_waypoint_placed = true;
200 | } else if (client.player.isAlive() && variables.had_death_waypoint_placed) {
201 | variables.had_death_waypoint_placed = false;
202 | }
203 | }
204 | catch(NullPointerException e){
205 | CList.LOGGER.info("Can't get the current world. Player probably uses ReplayMod and is now watching the replay");
206 | variables.is_world_error = true;
207 | }
208 | }
209 | }
210 | });
211 | variables.saved_since_last_update = true;
212 | variables.loaded_last_world = false;
213 | }
214 | public static void addNewWaypoint(int x, int y, int z, boolean death){
215 | CList.LOGGER.info("New waypoint for dimension " + variables.last_world.getDimension().effects());
216 | String waypoint_name;
217 | if(death){
218 | waypoint_name = (Text.translatable("waypoint.last.death")).getString();
219 | }
220 | else{
221 | waypoint_name = (Text.translatable("waypoint.new.waypoint")).getString();
222 | }
223 | variables.waypoints.add(new CListWaypoint(x,y,z,waypoint_name,String.valueOf(variables.last_world.getDimension().effects()),true,death));
224 | variables.colors.add(new CListWaypointColor(rand.nextFloat(),rand.nextFloat(),rand.nextFloat()));
225 | variables.saved_since_last_update = false;
226 | if(!death){
227 | CListVariables.minecraft_client.setScreen(new CListWaypointConfig(Text.literal("Config"),variables.waypoints.size()-1));
228 | }
229 | }
230 | public static void deleteWaypoint(int position){
231 | try {
232 | variables.waypoints.remove(position);
233 | variables.colors.remove(position);
234 | variables.saved_since_last_update = false;
235 | }
236 | catch (IndexOutOfBoundsException ignored){}
237 | }
238 | public static String getDimension(String text){
239 | String s = text;
240 | s = s.replace("minecraft:","");
241 | s = s.replace("_"," ");
242 | s = StringUtils.capitalize(s);
243 | return s;
244 | }
245 | public static void checkForWorldChanges(ClientWorld current_world){
246 | if(!variables.loaded_last_world && variables.worldName != null){
247 | CList.LOGGER.info("New world " + variables.worldName);
248 | variables.last_world = current_world;
249 | // Check for old 1.0 saves and convert them
250 | List names = CListData.loadListFromFileLegacy("clist_names_"+variables.worldName);
251 | List dimensions = CListData.loadListFromFileLegacy("clist_dimensions_"+variables.worldName);
252 | if(names != null && !names.isEmpty()){
253 | List temp = CListData.loadListFromFileLegacy("clist_"+variables.worldName);
254 | for(int i = 0; i < names.size(); i++){
255 | variables.waypoints.add(new CListWaypoint(temp.get(i),names.get(i),dimensions.get(i),true,false));
256 | }
257 | for(int i = 0; i < variables.waypoints.size(); i++){
258 | variables.colors.add(new CListWaypointColor(rand.nextFloat(),rand.nextFloat(),rand.nextFloat()));
259 | }
260 | CListData.deleteLegacyFile("clist_names_"+variables.worldName);
261 | CListData.deleteLegacyFile("clist_dimensions_"+variables.worldName);
262 | CList.LOGGER.info("Loaded old 1.0 data for world " + variables.worldName);
263 | // Force save converting it to a new format
264 | checkIfSaveIsNeeded(true);
265 | }
266 | else{
267 | // Check for post 1.0 saves
268 | if(!CListVariables.minecraft_client.isInSingleplayer()){
269 | List ways = CListData.loadListFromFile("clist_"+CListVariables.minecraft_client.getCurrentServerEntry().name);
270 | if(ways != null && !ways.isEmpty()){
271 | variables.waypoints = ways;
272 | CListData.deleteLegacyFile("clist_"+CListVariables.minecraft_client.getCurrentServerEntry().name);
273 | CList.LOGGER.info("Loaded old multiplier server data");
274 | checkIfSaveIsNeeded(true);
275 | }
276 | else{
277 | ways = CListData.loadListFromFile("clist_"+variables.worldName);
278 | if(ways != null && !ways.isEmpty()){
279 | variables.waypoints = ways;
280 | CList.LOGGER.info("Loaded data for server " + variables.worldName);
281 | }
282 | else {
283 | CList.LOGGER.info("The file for " + variables.worldName + " doesn't exist");
284 | }
285 | }
286 | }
287 | else{
288 | List ways = CListData.loadListFromFile("clist_"+variables.worldName);
289 | if(ways != null && !ways.isEmpty()){
290 | variables.waypoints = ways;
291 | CList.LOGGER.info("Loaded data for world " + variables.worldName);
292 | }
293 | else {
294 | CList.LOGGER.info("The file for " + variables.worldName + " doesn't exist");
295 | }
296 | }
297 | }
298 | variables.loaded_last_world = true;
299 | }
300 | }
301 | public static void addRandomWaypointColor(){
302 | variables.colors.add(new CListWaypointColor(rand.nextFloat(),rand.nextFloat(),rand.nextFloat()));
303 | }
304 | public static void checkIfSaveIsNeeded(boolean force){
305 | if(!variables.saved_since_last_update || force){
306 | CList.LOGGER.info("Saving data for world " + variables.worldName);
307 | CListData.saveListToFile("clist_"+variables.worldName, variables.waypoints);
308 | variables.saved_since_last_update = true;
309 | }
310 | }
311 | }
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListCommand.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import com.mojang.brigadier.CommandDispatcher;
4 | import com.mojang.brigadier.arguments.IntegerArgumentType;
5 | import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
6 | import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
7 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
8 | import net.minecraft.command.CommandRegistryAccess;
9 |
10 | public class CListCommand implements ClientCommandRegistrationCallback {
11 | @Override
12 | public void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess) {
13 | dispatcher.register(ClientCommandManager.literal("clist")
14 | .then(ClientCommandManager.argument("x", IntegerArgumentType.integer(Integer.MIN_VALUE,Integer.MAX_VALUE))
15 | .then(ClientCommandManager.argument("y", IntegerArgumentType.integer(Integer.MIN_VALUE,Integer.MAX_VALUE))
16 | .then(ClientCommandManager.argument("z", IntegerArgumentType.integer(Integer.MIN_VALUE,Integer.MAX_VALUE))
17 | .executes(ctx -> {
18 | int x = IntegerArgumentType.getInteger(ctx,"x");
19 | int y = IntegerArgumentType.getInteger(ctx,"y");
20 | int z = IntegerArgumentType.getInteger(ctx,"z");
21 | CListClient.addNewWaypoint(x,y,z,false);
22 | return 0;
23 | })))));
24 | }
25 | }
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListConfig.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import eu.midnightdust.lib.config.MidnightConfig;
4 |
5 | public class CListConfig extends MidnightConfig {
6 | @Entry(min=1,max=200) public static int multiplier = 10;
7 | @Entry(min=0) public static int render_distance = 0;
8 | @Entry public static boolean waypoints_toggled = true;
9 | @Entry public static boolean can_place_deathpoints = true;
10 | @Entry public static boolean waypoint_text_background = true;
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListData.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import com.google.common.collect.Lists;
4 | import net.fabricmc.loader.api.FabricLoader;
5 |
6 | import java.io.*;
7 | import java.nio.charset.StandardCharsets;
8 | import java.nio.file.Files;
9 | import java.util.List;
10 |
11 | public class CListData {
12 | public static void saveListToFile(String fileName, List waypointList) {
13 | if (!Files.exists(FabricLoader.getInstance().getConfigDir().resolve("coordinatelist"))) {
14 | try {
15 | Files.createDirectories(FabricLoader.getInstance().getConfigDir().resolve("coordinatelist"));
16 | } catch (IOException ignored) {
17 | }
18 | }
19 | File dataDir = FabricLoader.getInstance().getConfigDir().resolve("coordinatelist").toFile();
20 | File file = new File(dataDir, fileName);
21 |
22 | try (PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)))) {
23 | for (int i = 0; i < waypointList.size(); i++) {
24 | writer.println(CListClient.variables.waypoints.get(i).getCoordinates() + "~" + CListClient.variables.waypoints.get(i).name.replaceAll("~","") + "~" + CListClient.variables.waypoints.get(i).dimension + "~" + CListClient.variables.colors.get(i).getHexNoAlpha() + "~" + CListClient.variables.waypoints.get(i).render + "~" + CListClient.variables.waypoints.get(i).deathpoint);
25 | }
26 | } catch (IOException ignored) {
27 | }
28 | }
29 |
30 | public static List loadListFromFile(String fileName) {
31 | File dataDir = FabricLoader.getInstance().getConfigDir().resolve("coordinatelist").toFile();
32 | File file = new File(dataDir, fileName);
33 |
34 | if (!file.exists()) {
35 | return null;
36 | }
37 |
38 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
39 | List waypointList = Lists.newArrayList();
40 | String line;
41 |
42 | while ((line = reader.readLine()) != null) {
43 | String[] segments = line.split("~");
44 | if (segments.length >= 3) {
45 | String coords = segments[0];
46 | String name = segments[1];
47 | String dimension = segments[2];
48 | String color = null,bool = null,deathpoint = null;
49 | try{
50 | color = segments[3];
51 | bool = segments[4];
52 | deathpoint = segments[5];
53 | }
54 | catch (IndexOutOfBoundsException ignored){}
55 | CListWaypoint waypoint = new CListWaypoint(coords, name, dimension, Boolean.parseBoolean(bool), Boolean.parseBoolean(deathpoint));
56 | if(color == null){
57 | CListClient.addRandomWaypointColor();
58 | }
59 | else{
60 | CListWaypointColor color_class = new CListWaypointColor(0,0,0);
61 | color_class.set(color);
62 | CListClient.variables.colors.add(color_class);
63 | }
64 | waypointList.add(waypoint);
65 | }
66 | }
67 |
68 | return waypointList;
69 | } catch (IOException ignored) {
70 | }
71 |
72 | return null;
73 | }
74 |
75 | public static void deleteLegacyFile(String fileName){
76 | File dataDir = FabricLoader.getInstance().getConfigDir().resolve("coordinatelist").toFile();
77 | File file = new File(dataDir, fileName);
78 | if(file.exists()){
79 | boolean ignored = file.delete();
80 | }
81 | }
82 |
83 | public static List loadListFromFileLegacy(String fileName) {
84 | File dataDir = FabricLoader.getInstance().getConfigDir().resolve("coordinatelist").toFile();
85 | File file = new File(dataDir, fileName);
86 |
87 | if (!file.exists()) {
88 | return null;
89 | }
90 |
91 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
92 | List stringList = Lists.newArrayList();
93 | String line;
94 |
95 | while ((line = reader.readLine()) != null) {
96 | stringList.add(line);
97 | }
98 |
99 | return stringList;
100 | } catch (IOException ignored) {
101 | }
102 |
103 | return null;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListDelayedEvent.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | public class CListDelayedEvent {
4 | private float ticks;
5 | private final Runnable function;
6 | public CListDelayedEvent(float seconds, Runnable function){
7 | this.ticks = seconds*20;
8 | this.function = function;
9 | }
10 | public boolean update(){
11 | this.ticks -= 1;
12 | if(ticks<=0){
13 | this.function.run();
14 | return true;
15 | }
16 | return false;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListRenderLayers.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import com.mojang.blaze3d.pipeline.RenderPipeline;
4 | import com.mojang.blaze3d.platform.DepthTestFunction;
5 | import net.minecraft.client.gl.RenderPipelines;
6 | import net.minecraft.client.render.RenderLayer;
7 | import net.minecraft.client.render.RenderPhase;
8 | import net.minecraft.util.Identifier;
9 | import net.minecraft.util.TriState;
10 | import net.minecraft.util.Util;
11 |
12 | import java.util.function.Function;
13 |
14 | public class CListRenderLayers {
15 | private static final RenderPipeline POSITION_TEX_COLOR_PIPELINE = RenderPipelines.register(
16 | RenderPipeline.builder(RenderPipelines.POSITION_TEX_COLOR_SNIPPET)
17 | .withLocation("pipeline/position_tex_color")
18 | .withCull(false)
19 | .withoutBlend()
20 | .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
21 | .withDepthWrite(true)
22 | .build()
23 | );
24 | public static final Function POSITION_TEX_COLOR = Util.memoize(
25 | texture -> RenderLayer.of(
26 | "pos_tex_color",
27 | 1536,
28 | false,
29 | true,
30 | POSITION_TEX_COLOR_PIPELINE,
31 | RenderLayer.MultiPhaseParameters.builder().texture(new RenderPhase.Texture(texture, TriState.FALSE, false)).build(false)
32 | )
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListVariables.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import net.minecraft.client.MinecraftClient;
4 | import net.minecraft.client.world.ClientWorld;
5 | import org.apache.commons.compress.utils.Lists;
6 | import java.util.List;
7 |
8 | public class CListVariables {
9 | public List waypoints = Lists.newArrayList();
10 | public List colors = Lists.newArrayList();
11 | public static List delayed_events = Lists.newArrayList();
12 | public String worldName;
13 | public ClientWorld last_world;
14 | public static MinecraftClient minecraft_client = MinecraftClient.getInstance();
15 | public boolean saved_since_last_update;
16 | public boolean loaded_last_world;
17 | public boolean had_death_waypoint_placed;
18 | public boolean is_world_error;
19 | }
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListWaypoint.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import net.minecraft.text.Text;
4 | import org.apache.commons.lang3.StringUtils;
5 |
6 | public class CListWaypoint {
7 | public int x, y, z;
8 | public String name;
9 | public String dimension;
10 | private int bug_fix;
11 | public boolean render;
12 | public boolean deathpoint;
13 | CListWaypoint(String coords, String waypoint_name, String waypoint_dimension, boolean is_rendered, boolean is_deathpoint){
14 | String s = coords;
15 | s = s.replace("X", "");
16 | s = s.replace("Y", "");
17 | s = s.replace("Z", "");
18 | s = s.replace(" ", "");
19 | String[] segments = s.split(":");
20 | this.x = Integer.parseInt(segments[1]);
21 | this.y = Integer.parseInt(segments[2]);
22 | this.z = Integer.parseInt(segments[3]);
23 | this.name = waypoint_name;
24 | this.dimension = waypoint_dimension;
25 | this.render = is_rendered;
26 | this.deathpoint = is_deathpoint;
27 | this.bug_fix = 0;
28 | }
29 | CListWaypoint(int x, int y, int z, String waypoint_name, String waypoint_dimension, boolean is_rendered, boolean is_deathpoint){
30 | this.x = x;
31 | this.y = y;
32 | this.z = z;
33 | this.name = waypoint_name;
34 | this.dimension = waypoint_dimension;
35 | this.render = is_rendered;
36 | this.deathpoint = is_deathpoint;
37 | this.bug_fix = 0;
38 | }
39 | public String getCoordinates(){
40 | return "X: " + x + " Y: " + y + " Z: " + z;
41 | }
42 | public void toggleVisibility(){
43 | this.bug_fix += 1;
44 | if(bug_fix == 2){
45 | this.bug_fix = 0;
46 | this.render = !this.render;
47 | CListClient.variables.saved_since_last_update = false;
48 | }
49 | }
50 | public Text getDimensionText(){
51 | return Text.literal(this.getDimensionString());
52 | }
53 | public String getDimensionString(){
54 | String s = this.dimension;
55 | s = s.replace("minecraft:","");
56 | s = s.replace("_"," ");
57 | s = StringUtils.capitalize(s);
58 | return s;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListWaypointColor.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | public class CListWaypointColor {
4 | public float r;
5 | public float g;
6 | public float b;
7 | CListWaypointColor(float red, float green, float blue){
8 | r = red;
9 | g = green;
10 | b = blue;
11 | }
12 | public void set(float[] hsv) {
13 | float h = hsv[0];
14 | float s = hsv[1];
15 | float v = hsv[2];
16 | s /= 100;
17 | v /= 100;
18 | float c = v * s;
19 | float x = c * (1 - Math.abs((h / 60) % 2 - 1));
20 | float m = v - c;
21 | float rPrime, gPrime, bPrime;
22 | if (h < 60) {
23 | rPrime = c;
24 | gPrime = x;
25 | bPrime = 0;
26 | } else if (h < 120) {
27 | rPrime = x;
28 | gPrime = c;
29 | bPrime = 0;
30 | } else if (h < 180) {
31 | rPrime = 0;
32 | gPrime = c;
33 | bPrime = x;
34 | } else if (h < 240) {
35 | rPrime = 0;
36 | gPrime = x;
37 | bPrime = c;
38 | } else if (h < 300) {
39 | rPrime = x;
40 | gPrime = 0;
41 | bPrime = c;
42 | } else {
43 | rPrime = c;
44 | gPrime = 0;
45 | bPrime = x;
46 | }
47 | this.r = (rPrime + m);
48 | this.g = (gPrime + m);
49 | this.b = (bPrime + m);
50 | }
51 | public float[] getHSV() {
52 | float min = Math.min(Math.min(r, g), b);
53 | float max = Math.max(Math.max(r, g), b);
54 | float delta = max - min;
55 | float h, s;
56 | float v = max * 100;
57 | if (max != 0)
58 | s = (delta / max) * 100;
59 | else {
60 | s = 0;
61 | h = 0;
62 | return new float[]{h, s, v};
63 | }
64 | if (r == max)
65 | h = (g - b) / delta;
66 | else if (g == max)
67 | h = 2 + (b - r) / delta;
68 | else
69 | h = 4 + (r - g) / delta;
70 | h *= 60;
71 | if (h < 0)
72 | h += 360;
73 | if (Float.isNaN(h))
74 | h = 0;
75 | if (Float.isNaN(s))
76 | s = 0;
77 | if (Float.isNaN(v))
78 | v = 0;
79 | h = Float.parseFloat(String.format("%.1f", h).replace(",", "."));
80 | s = Float.parseFloat(String.format("%.1f", s).replace(",", "."));
81 | v = Float.parseFloat(String.format("%.1f", v).replace(",", "."));
82 | return new float[]{h, s, v};
83 | }
84 | public int getHex(){
85 | int red = (int) (r * 255);
86 | int green = (int) (g * 255);
87 | int blue = (int) (b * 255);
88 | return (255 << 24) | (red << 16) | (green << 8) | blue;
89 | }
90 | public String getHexNoAlpha(){
91 | int red = (int) (r * 255);
92 | int green = (int) (g * 255);
93 | int blue = (int) (b * 255);
94 | return String.format("%02X%02X%02X", red, green, blue);
95 | }
96 | public void set(String hex) {
97 | if(hex.length() == 6 && hex.matches("[a-zA-Z0-9]+")){
98 | hex = hex.replace("#", "");
99 | String redHex = hex.substring(0, 2);
100 | String greenHex = hex.substring(2, 4);
101 | String blueHex = hex.substring(4, 6);
102 | int red = -1;
103 | int green = -1;
104 | int blue = -1;
105 | try{
106 | red = Integer.parseInt(redHex, 16);
107 | green = Integer.parseInt(greenHex, 16);
108 | blue = Integer.parseInt(blueHex, 16);
109 | }
110 | catch (NumberFormatException ignored){}
111 | if(red != -1 && green != -1 && blue != -1){
112 | this.r = red / 255.0f;
113 | this.g = green / 255.0f;
114 | this.b = blue / 255.0f;
115 | }
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListWaypointConfig.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import com.mojang.blaze3d.opengl.GlStateManager;
4 | import com.mojang.blaze3d.systems.RenderSystem;
5 | import net.minecraft.client.gui.DrawContext;
6 | import net.minecraft.client.gui.screen.Screen;
7 | import net.minecraft.client.gui.widget.*;
8 | import net.minecraft.client.render.*;
9 | import net.minecraft.text.Text;
10 | import net.minecraft.util.Identifier;
11 | import net.minecraft.util.math.MathHelper;
12 | import org.joml.Matrix4f;
13 | import org.lwjgl.glfw.GLFW;
14 |
15 | import java.awt.*;
16 |
17 | public class CListWaypointConfig extends Screen {
18 | private static int id;
19 | private boolean render_color_picker = false;
20 | private final CListWaypoint waypoint;
21 | private TextFieldWidget waypoint_name;
22 | private static TextFieldWidget waypoint_color;
23 | private TextFieldWidget x, y, z;
24 | private SpriteButton change_color;
25 | private HSVSlider h, s, v;
26 | private static float[] hsv;
27 | public CListWaypointConfig(Text title, int waypoint_id){
28 | super(title);
29 | id = waypoint_id;
30 | this.waypoint = CListClient.variables.waypoints.get(id);
31 | }
32 | @Override
33 | protected void init(){
34 | GridWidget gridWidget = new GridWidget();
35 | hsv = CListClient.variables.colors.get(id).getHSV();
36 | gridWidget.getMainPositioner().margin(4, 4, 4, 0);
37 | GridWidget.Adder adder = gridWidget.createAdder(2);
38 | adder.add(ButtonWidget.builder(Text.translatable("selectWorld.delete"), button -> {
39 | CListClient.deleteWaypoint(id);
40 | CListVariables.minecraft_client.setScreen(new CListWaypointScreen(Text.literal("Waypoints")));
41 | }).width(150).build(),1, gridWidget.copyPositioner().marginBottom(10));
42 | adder.add(ButtonWidget.builder(Text.translatable("gui.done"), button -> {CListVariables.minecraft_client.setScreen(new CListWaypointScreen(Text.literal("Waypoints")));CListClient.variables.saved_since_last_update = false;}).width(150).build(),1, gridWidget.copyPositioner().marginBottom(10));
43 | this.waypoint_name = new TextFieldWidget(textRenderer, (this.width-150)/2, (this.height-20)/2-80, 150, 20, Text.literal(""));
44 | this.waypoint_name.setFocusUnlocked(true);
45 | this.waypoint_name.setMaxLength(25);
46 | this.waypoint_name.setText(waypoint.name);
47 | waypoint_color = new TextFieldWidget(textRenderer, (this.width-70)/2, (this.height-20)/2+50, 70, 20, Text.literal(""));
48 | waypoint_color.setFocusUnlocked(true);
49 | waypoint_color.setMaxLength(6);
50 | waypoint_color.setText(CListClient.variables.colors.get(id).getHexNoAlpha());
51 | this.x = new TextFieldWidget(textRenderer, (this.width-50)/2-60, (this.height-20)/2-50, 50, 20, Text.literal(""));
52 | this.x.setFocusUnlocked(true);
53 | this.x.setText(String.valueOf(waypoint.x));
54 | this.y = new TextFieldWidget(textRenderer, (this.width-50)/2, (this.height-20)/2-50, 50, 20, Text.literal(""));
55 | this.y.setFocusUnlocked(true);
56 | this.y.setText(String.valueOf(waypoint.y));
57 | this.z = new TextFieldWidget(textRenderer, (this.width-50)/2+60, (this.height-20)/2-50, 50, 20, Text.literal(""));
58 | this.z.setFocusUnlocked(true);
59 | this.z.setText(String.valueOf(waypoint.z));
60 | gridWidget.refreshPositions();
61 | SimplePositioningWidget.setPos(gridWidget, 0, 0, this.width, this.height, 0.5f, 1f);
62 | gridWidget.forEachChild(this::addDrawableChild);
63 | addDrawableChild(this.waypoint_name);
64 | addDrawableChild(waypoint_color);
65 | addDrawableChild(this.x);
66 | addDrawableChild(this.y);
67 | addDrawableChild(this.z);
68 | change_color = new SpriteButton((this.width-50)/2+38,(this.height-20)/2-15,12,12, button -> render_color_picker = !render_color_picker);
69 | this.h = new HSVSlider((this.width-50)/2,(this.height-20)/2-15,110,15,Text.literal("H: " + hsv[0]),hsv[0] / 360,0);
70 | this.s = new HSVSlider((this.width-50)/2,(this.height-20)/2+3,110,15,Text.literal("S: " + hsv[1]),hsv[1] / 100, 1);
71 | this.v = new HSVSlider((this.width-50)/2,(this.height-20)/2+20,110,15,Text.literal("V: " + hsv[2]),hsv[2] / 100, 2);
72 | this.h.visible = false;
73 | this.s.visible = false;
74 | this.v.visible = false;
75 | addDrawableChild(change_color);
76 | addDrawableChild(this.h);
77 | addDrawableChild(this.s);
78 | addDrawableChild(this.v);
79 | }
80 | public static class HSVSlider extends SliderWidget {
81 | private float true_value;
82 | private final int max;
83 | private final int type;
84 | private final String prefix;
85 | private boolean force = false;
86 | private static final Identifier HANDLE_TEXTURE = Identifier.ofVanilla("widget/slider_handle");
87 | private static final Identifier HANDLE_HIGHLIGHTED_TEXTURE = Identifier.ofVanilla("widget/slider_handle_highlighted");
88 | private boolean sliderFocused;
89 | public HSVSlider(int x, int y, int width, int height, Text text, float value, int type) {
90 | super(x, y, width, height, text, value);
91 | this.type = type;
92 | this.max = type == 0 ? 360 : 100;
93 | this.prefix = type == 0 ? "H: " : type == 1 ? "S: " : "V: ";
94 | }
95 | public void setValue(float value){
96 | double d = this.value;
97 | this.value = MathHelper.clamp(value, 0.0, 1.0);
98 | if (d != this.value) {
99 | this.force = true;
100 | this.applyValue();
101 | }
102 | this.updateMessage();
103 | }
104 | @Override
105 | protected void updateMessage() {
106 | this.setMessage(Text.literal(prefix + true_value));
107 | }
108 | @Override
109 | protected void applyValue() {
110 | this.true_value = (float)Math.round((this.value * (this.max)) * (double)((float)100)) / (float)100;
111 | hsv[type] = this.true_value;
112 | if(!this.force){
113 | CListClient.variables.colors.get(id).set(hsv);
114 | waypoint_color.setText(CListClient.variables.colors.get(id).getHexNoAlpha());
115 | CListClient.variables.saved_since_last_update = false;
116 | }
117 | else{
118 | this.force = false;
119 | }
120 | }
121 | private Identifier getHandleTexture() {
122 | return !this.hovered && !this.sliderFocused ? HANDLE_TEXTURE : HANDLE_HIGHLIGHTED_TEXTURE;
123 | }
124 | @Override
125 | public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta){
126 | Matrix4f matrix4f = context.getMatrices().peek().getPositionMatrix();
127 | VertexConsumer vertexConsumer = CListVariables.minecraft_client.getBufferBuilders().getEntityVertexConsumers().getBuffer(RenderLayer.getGui());
128 | RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha);
129 | GlStateManager._enableBlend();
130 | GlStateManager._enableDepthTest();
131 | int color = CListClient.variables.colors.get(id).getHex();
132 | float[] color_float = Color.RGBtoHSB((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, null);
133 | if(type == 0){
134 | for (int i = 0; i < this.width; i++) {
135 | float hue = i / (float) this.width;
136 | int color_h = Color.HSBtoRGB(hue, color_float[1], color_float[2]);
137 | vertexConsumer.vertex(matrix4f, this.getX() + i, this.getY(), 0).color((color_h >> 16) & 0xFF, (color_h >> 8) & 0xFF, color_h & 0xFF, 0xFF);
138 | vertexConsumer.vertex(matrix4f, this.getX() + i, this.getY() + this.getHeight(), 0).color((color_h >> 16) & 0xFF, (color_h >> 8) & 0xFF, color_h & 0xFF, 0xFF);
139 | vertexConsumer.vertex(matrix4f, this.getX() + i + 1, this.getY() + this.getHeight(), 0).color((color_h >> 16) & 0xFF, (color_h >> 8) & 0xFF, color_h & 0xFF, 0xFF);
140 | vertexConsumer.vertex(matrix4f, this.getX() + i + 1, this.getY(), 0).color((color_h >> 16) & 0xFF, (color_h >> 8) & 0xFF, color_h & 0xFF, 0xFF);
141 | }
142 | }
143 | else{
144 | int color_s = Color.HSBtoRGB(color_float[0], 1.0f, color_float[2]);
145 | int color_v = Color.HSBtoRGB(color_float[0], color_float[1], 1.0f);
146 | int color_s_start = Color.HSBtoRGB(1.0f, 0.0f, color_float[2]);
147 | vertexConsumer.vertex(matrix4f, this.getX(), this.getY(), 0).color(type == 1 ? color_s_start : 0xFF000000);
148 | vertexConsumer.vertex(matrix4f, this.getX(), this.getY() + this.getHeight(), 0).color(type == 1 ? color_s_start : 0xFF000000);
149 | vertexConsumer.vertex(matrix4f, this.getX() + this.width, this.getY() + this.getHeight(), 0).color(type == 1 ? color_s : color_v);
150 | vertexConsumer.vertex(matrix4f, this.getX() + this.width, this.getY(), 0).color(type == 1 ? color_s : color_v);
151 | }
152 | context.drawGuiTexture(RenderLayer::getGuiTextured, this.getHandleTexture(), this.getX() + (int)(this.value * (double)(this.width - 8)), this.getY(), 8, this.getHeight());
153 | RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
154 | int i = this.active ? 16777215 : 10526880;
155 | this.drawScrollableText(context, CListVariables.minecraft_client.textRenderer, 2, i | MathHelper.ceil(this.alpha * 255.0F) << 24);
156 | }
157 | }
158 | private static class SpriteButton extends ButtonWidget {
159 | public SpriteButton(int x, int y, int width, int height, PressAction onPress) {
160 | super(x, y, width, height, Text.literal(""), onPress, DEFAULT_NARRATION_SUPPLIER);
161 | }
162 | @Override
163 | public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
164 | Identifier icon = Identifier.of("coordinatelist", "icon/change");
165 | GlStateManager._enableBlend();
166 | context.drawGuiTexture(RenderLayer::getGuiTextured, icon, getX(), getY(), width, height);
167 | GlStateManager._disableBlend();
168 | }
169 | }
170 | @Override
171 | public void render(DrawContext context, int mouseX, int mouseY, float delta) {
172 | int SQUARE_SIZE = 50;
173 | int centerX = this.width / 2;
174 | int centerY = this.height / 2;
175 | if(render_color_picker){
176 | centerX = width / 2 - 60;
177 | change_color.setX((this.width-50)/2-22);
178 | }
179 | else{
180 | change_color.setX((this.width-50)/2+38);
181 | }
182 | int left = centerX - SQUARE_SIZE / 2;
183 | int top = centerY - SQUARE_SIZE / 2;
184 | int right = centerX + SQUARE_SIZE / 2;
185 | int bottom = centerY + SQUARE_SIZE / 2;
186 | super.render(context, mouseX, mouseY, delta);
187 | context.fill(left, top, right, bottom, CListClient.variables.colors.get(id).getHex());
188 | change_color.renderWidget(context,mouseX,mouseY,delta);
189 | if(render_color_picker){
190 | this.h.visible = true;
191 | this.s.visible = true;
192 | this.v.visible = true;
193 | }
194 | else{
195 | this.h.visible = false;
196 | this.s.visible = false;
197 | this.v.visible = false;
198 | }
199 | }
200 | private static boolean isParsableToInt(String str) {
201 | try {
202 | Integer.parseInt(str);
203 | return true;
204 | } catch (NumberFormatException e) {
205 | return false;
206 | }
207 | }
208 | @Override
209 | public boolean charTyped(char chr, int keyCode) {
210 | boolean result = super.charTyped(chr, keyCode);
211 | if(this.waypoint_name.isFocused()){
212 | waypoint.name = waypoint_name.getText();
213 | }
214 | if(waypoint_color.isFocused()){
215 | CListClient.variables.colors.get(id).set(waypoint_color.getText());
216 | hsv = CListClient.variables.colors.get(id).getHSV();
217 | h.setValue(hsv[0] / 360);
218 | s.setValue(hsv[1] / 100);
219 | v.setValue(hsv[2] / 100);
220 | }
221 | if(this.x.isFocused() && isParsableToInt(x.getText())){
222 | waypoint.x = Integer.parseInt(x.getText());
223 | }
224 | if(this.y.isFocused() && isParsableToInt(y.getText())){
225 | waypoint.y = Integer.parseInt(y.getText());
226 | }
227 | if(this.z.isFocused() && isParsableToInt(z.getText())){
228 | waypoint.z = Integer.parseInt(z.getText());
229 | }
230 | CListClient.variables.saved_since_last_update = false;
231 | return true;
232 | }
233 | @Override
234 | public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
235 | super.keyPressed(keyCode, scanCode, modifiers);
236 | if(keyCode == GLFW.GLFW_KEY_V && modifiers == GLFW.GLFW_MOD_CONTROL){
237 | if(this.waypoint_name.isFocused()){
238 | waypoint.name = waypoint_name.getText();
239 | }
240 | if(waypoint_color.isFocused()){
241 | CListClient.variables.colors.get(id).set(waypoint_color.getText());
242 | hsv = CListClient.variables.colors.get(id).getHSV();
243 | h.setValue(hsv[0] / 360);
244 | s.setValue(hsv[1] / 100);
245 | v.setValue(hsv[2] / 100);
246 | }
247 | if(this.x.isFocused() && isParsableToInt(x.getText())){
248 | waypoint.x = Integer.parseInt(x.getText());
249 | }
250 | if(this.y.isFocused() && isParsableToInt(y.getText())){
251 | waypoint.y = Integer.parseInt(y.getText());
252 | }
253 | if(this.z.isFocused() && isParsableToInt(z.getText())){
254 | waypoint.z = Integer.parseInt(z.getText());
255 | }
256 | CListClient.variables.saved_since_last_update = false;
257 | }
258 | if (keyCode == GLFW.GLFW_KEY_BACKSPACE) {
259 | if(this.waypoint_name.isFocused()){
260 | waypoint.name = waypoint_name.getText();
261 | }
262 | if(waypoint_color.isFocused()){
263 | CListClient.variables.colors.get(id).set(waypoint_color.getText());
264 | hsv = CListClient.variables.colors.get(id).getHSV();
265 | h.setValue(hsv[0] / 360);
266 | s.setValue(hsv[1] / 100);
267 | v.setValue(hsv[2] / 100);
268 | }
269 | if(this.x.isFocused() && isParsableToInt(x.getText())){
270 | waypoint.x = Integer.parseInt(x.getText());
271 | }
272 | if(this.y.isFocused() && isParsableToInt(y.getText())){
273 | waypoint.y = Integer.parseInt(y.getText());
274 | }
275 | if(this.z.isFocused() && isParsableToInt(z.getText())){
276 | waypoint.z = Integer.parseInt(z.getText());
277 | }
278 | CListClient.variables.saved_since_last_update = false;
279 | }
280 | return true;
281 | }
282 | }
283 |
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/CListWaypointScreen.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist;
2 |
3 | import com.mojang.blaze3d.opengl.GlStateManager;
4 | import net.minecraft.client.gui.DrawContext;
5 | import net.minecraft.client.gui.Element;
6 | import net.minecraft.client.gui.screen.Screen;
7 | import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
8 | import net.minecraft.client.gui.tooltip.Tooltip;
9 | import net.minecraft.client.gui.widget.*;
10 | import net.minecraft.client.render.RenderLayer;
11 | import net.minecraft.entity.player.PlayerEntity;
12 | import net.minecraft.text.Text;
13 | import net.minecraft.util.Identifier;
14 | import org.apache.commons.compress.utils.Lists;
15 | import org.lwjgl.glfw.GLFW;
16 |
17 | import java.util.List;
18 |
19 | public class CListWaypointScreen extends Screen {
20 | public CListWaypointScreen(Text title) {
21 | super(title);
22 | }
23 | private ScrollList list;
24 | private int selected_waypoint_id = -1;
25 | private ButtonWidget copy_coordinates_button;
26 | private ButtonWidget edit_waypoint_button;
27 | private ButtonWidget delete_waypoint_button;
28 | @Override
29 | protected void init() {
30 | GridWidget gridWidget = new GridWidget();
31 | GridWidget gridWidgetBottom = new GridWidget();
32 | gridWidget.getMainPositioner().margin(4, 4, 4, 0);
33 | gridWidgetBottom.getMainPositioner().margin(4, 4, 4, 0);
34 | GridWidget.Adder adder = gridWidget.createAdder(2);
35 | GridWidget.Adder adderBottom = gridWidgetBottom.createAdder(3);
36 | adder.add(ButtonWidget.builder(Text.translatable("buttons.add.new.waypoint"), button -> {
37 | PlayerEntity player = CListVariables.minecraft_client.player;
38 | CListClient.addNewWaypoint((int) Math.round(player.getX()), (int) Math.round(player.getY()), (int) Math.round(player.getZ()),false);
39 | list.RefreshElements();
40 | }).width(300).build(),2, gridWidget.copyPositioner().marginTop(10));
41 | copy_coordinates_button = ButtonWidget.builder(Text.literal("---"), button -> {
42 | long window = CListVariables.minecraft_client.getWindow().getHandle();
43 | CListWaypoint waypoint = CListClient.variables.waypoints.get(selected_waypoint_id);
44 | GLFW.glfwSetClipboardString(window, waypoint.x + " " + waypoint.y + " " + waypoint.z);
45 | }).width(150).build();
46 | copy_coordinates_button.setTooltip(Tooltip.of(Text.translatable("tooltip.copy.waypoint.coordinates")));
47 | edit_waypoint_button = ButtonWidget.builder(Text.translatable("selectWorld.edit"), button -> CListVariables.minecraft_client.setScreen(new CListWaypointConfig(Text.literal("Config"),selected_waypoint_id))).width(100).build();
48 | delete_waypoint_button = ButtonWidget.builder(Text.translatable("selectWorld.delete"), button -> {
49 | CListClient.deleteWaypoint(selected_waypoint_id);
50 | if(selected_waypoint_id >= CListClient.variables.waypoints.size()){
51 | selected_waypoint_id -= 1;
52 | }
53 | list.RefreshElements();
54 | }).width(100).build();
55 | adderBottom.add(delete_waypoint_button,1, gridWidgetBottom.copyPositioner().marginBottom(10));
56 | adderBottom.add(copy_coordinates_button,1, gridWidgetBottom.copyPositioner().marginBottom(10));
57 | adderBottom.add(edit_waypoint_button,1, gridWidgetBottom.copyPositioner().marginBottom(10));
58 | list = new ScrollList();
59 | list.SetupElements();
60 | addDrawableChild(list);
61 | gridWidget.refreshPositions();
62 | gridWidgetBottom.refreshPositions();
63 | SimplePositioningWidget.setPos(gridWidget, 0, 0, this.width, this.height, 0.5f, 0f);
64 | SimplePositioningWidget.setPos(gridWidgetBottom, 0, 0, this.width, this.height, 0.5f, 1f);
65 | gridWidget.forEachChild(this::addDrawableChild);
66 | gridWidgetBottom.forEachChild(this::addDrawableChild);
67 | }
68 | @Override
69 | public void render(DrawContext context, int mouseX, int mouseY, float delta) {
70 | super.render(context, mouseX, mouseY, delta);
71 | if(selected_waypoint_id != -1){
72 | list.setSelected(list.children().get(selected_waypoint_id));
73 | }
74 | if(selected_waypoint_id >= 0){
75 | copy_coordinates_button.active = true;
76 | edit_waypoint_button.active = true;
77 | delete_waypoint_button.active = true;
78 | }
79 | else{
80 | copy_coordinates_button.active = false;
81 | edit_waypoint_button.active = false;
82 | delete_waypoint_button.active = false;
83 | }
84 | }
85 | @Override
86 | public boolean mouseClicked(double mouseX, double mouseY, int button) {
87 | list.mouseClicked(mouseX, mouseY, button);
88 | return super.mouseClicked(mouseX, mouseY, button);
89 | }
90 | @Override
91 | public boolean mouseReleased(double mouseX, double mouseY, int button) {
92 | list.mouseReleased(mouseX, mouseY, button);
93 | return super.mouseReleased(mouseX, mouseY, button);
94 | }
95 | @Override
96 | public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
97 | list.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
98 | return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
99 | }
100 | private class ScrollList extends EntryListWidget {
101 | public ScrollList(){
102 | super(CListWaypointScreen.this.client, CListWaypointScreen.this.width, CListWaypointScreen.this.height-64, 32, 25);//32
103 | }
104 | public void SetupElements(){
105 | for(int i = 0; i < CListClient.variables.waypoints.size(); i++){
106 | ScrollList.ScrollListEntry Coordinate = new ScrollList.ScrollListEntry(i);
107 | list.addEntry(Coordinate);
108 | }
109 | }
110 | public void RefreshElements(){
111 | clearEntries();
112 | SetupElements();
113 | }
114 | @Override
115 | public int getRowWidth() {
116 | return 245;
117 | }
118 | public void appendClickableNarrations(NarrationMessageBuilder builder){}
119 | private static class InvisibleButton extends ButtonWidget{
120 | public InvisibleButton(int x, int y, int width, int height, PressAction onPress){
121 | super(x, y, width, height, Text.literal(""), onPress,DEFAULT_NARRATION_SUPPLIER);
122 | }
123 | @Override
124 | public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {}
125 | }
126 | private static class SpriteButton extends ButtonWidget {
127 | private final int id;
128 | public SpriteButton(int x, int y, int width, int height, PressAction onPress, int coordinate_id) {
129 | super(x, y, width, height, Text.literal(""), onPress,DEFAULT_NARRATION_SUPPLIER);
130 | this.id = coordinate_id;
131 | }
132 | @Override
133 | public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
134 | Identifier eye_icon;
135 | if(CListClient.variables.waypoints.get(id).render){
136 | eye_icon = Identifier.of("coordinatelist", "icon/visible");
137 | }
138 | else{
139 | eye_icon = Identifier.of("coordinatelist", "icon/not_visible");
140 | }
141 | GlStateManager._enableBlend();
142 | context.drawGuiTexture(RenderLayer::getGuiTextured, eye_icon, getX(), getY(), width, height);
143 | GlStateManager._disableBlend();
144 | }
145 | }
146 | private class ScrollListEntry extends EntryListWidget.Entry{
147 | private final Text waypoint_name;
148 | private final Text dimension;
149 | private final SpriteButton sh;
150 | private final InvisibleButton select;
151 | private final List children;
152 | private final int id;
153 | public ScrollListEntry(int id){
154 | this.id = id;
155 | this.waypoint_name = Text.of(CListClient.variables.waypoints.get(id).name);
156 | this.dimension = CListClient.variables.waypoints.get(id).getDimensionText();
157 | this.sh = new SpriteButton(0, 0, 16, 12, button -> {
158 | CListClient.variables.waypoints.get(id).toggleVisibility();
159 | selected_waypoint_id = id;
160 | CListWaypoint waypoint = CListClient.variables.waypoints.get(selected_waypoint_id);
161 | copy_coordinates_button.setMessage(Text.literal(waypoint.x + " " + waypoint.y + " " + waypoint.z));
162 | }, id);
163 | this.select = new InvisibleButton(0, 0, 240, 25, button -> {
164 | selected_waypoint_id = id;
165 | CListWaypoint waypoint = CListClient.variables.waypoints.get(selected_waypoint_id);
166 | copy_coordinates_button.setMessage(Text.literal(waypoint.x + " " + waypoint.y + " " + waypoint.z));
167 | });
168 | this.children = Lists.newArrayList();
169 | this.children.add(sh);
170 | this.children.add(select);
171 | }
172 | @Override
173 | public void render(DrawContext context, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovered, float delta) {
174 | sh.setX(x+2);
175 | sh.setY(y+4);
176 | select.setX(x);
177 | select.setY(y);
178 | sh.render(context, mouseX, mouseY, delta);
179 | select.render(context, mouseX, mouseY, delta);
180 | context.drawTextWithShadow(CListVariables.minecraft_client.textRenderer, dimension.getString(), x+180, y+6, 0xFFFFFF);
181 | context.drawTextWithShadow(CListVariables.minecraft_client.textRenderer, waypoint_name.getString(), x+22, y+6, CListClient.variables.colors.get(id).getHex());
182 | }
183 | @Override
184 | public boolean mouseClicked(double mouseX, double mouseY, int button) {
185 | boolean handled = false;
186 | for (Element E : children) {
187 | if (E.mouseClicked(mouseX, mouseY, button)) {
188 | handled = true;
189 | break;
190 | }
191 | }
192 | return handled || super.mouseClicked(mouseX, mouseY, button);
193 | }
194 | @Override
195 | public boolean mouseReleased(double mouseX, double mouseY, int button) {
196 | boolean handled = false;
197 | for (Element E : children) {
198 | if (E.mouseReleased(mouseX, mouseY, button)) {
199 | handled = true;
200 | break;
201 | }
202 | }
203 | return handled || super.mouseReleased(mouseX, mouseY, button);
204 | }
205 | }
206 | }
207 | }
--------------------------------------------------------------------------------
/src/main/java/one/pouekdev/coordinatelist/mixin/CListChatGrabber.java:
--------------------------------------------------------------------------------
1 | package one.pouekdev.coordinatelist.mixin;
2 |
3 | import net.minecraft.client.gui.hud.ChatHud;
4 | import net.minecraft.client.gui.hud.ChatHudLine;
5 | import net.minecraft.text.ClickEvent;
6 | import net.minecraft.text.Text;
7 | import net.minecraft.util.Formatting;
8 | import one.pouekdev.coordinatelist.CListDelayedEvent;
9 | import one.pouekdev.coordinatelist.CListVariables;
10 | import org.apache.commons.compress.utils.Lists;
11 | import org.apache.commons.lang3.StringUtils;
12 | import org.spongepowered.asm.mixin.Mixin;
13 | import org.spongepowered.asm.mixin.injection.At;
14 | import org.spongepowered.asm.mixin.injection.Inject;
15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
16 |
17 | import java.util.List;
18 | import java.util.regex.Matcher;
19 | import java.util.regex.Pattern;
20 |
21 | @Mixin(ChatHud.class)
22 | public abstract class CListChatGrabber {
23 | @Inject(method = "logChatMessage", at = @At("RETURN"))
24 | private void getCoordsFromChat(ChatHudLine message, CallbackInfo ci) {
25 | List numbersList = Lists.newArrayList();
26 | String player;
27 | try{
28 | String content = message.content().getString().replaceAll("\r", "\\\\r").replaceAll("\n", "\\\\n");
29 | player = StringUtils.substringBetween(content, "<", ">");
30 | content = content.replace("<","").replace(">","").replace(player,"");
31 | Pattern pattern = Pattern.compile("-?\\b(?![A-Za-z])\\d+(\\.\\d+)?\\b");
32 | Matcher matcher = pattern.matcher(content);
33 | while (matcher.find()) {
34 | numbersList.add(matcher.group());
35 | }
36 | }
37 | catch (NullPointerException ignored){}
38 | if(numbersList.size() >= 3){
39 | int x = Math.round(Float.parseFloat(numbersList.get(0)));
40 | int y = Math.round(Float.parseFloat(numbersList.get(1)));
41 | int z = Math.round(Float.parseFloat(numbersList.get(2)));
42 | Text clickableMessage = Text.translatable("chat.create.waypoint.message").formatted(Formatting.GREEN).styled(style -> style.withClickEvent(new ClickEvent.RunCommand("/clist " + x + " " + y + " " + z)));
43 | CListVariables.delayed_events.add(new CListDelayedEvent(0.1f,() -> CListVariables.minecraft_client.inGameHud.getChatHud().addMessage(clickableMessage)));
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PouekDEV/CList/0b29e293fb68139f4c4803f1102d12351f0bea13/src/main/resources/assets/coordinatelist/icon.png
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/lang/de_de.json:
--------------------------------------------------------------------------------
1 | {
2 | "keybinds.category.name": "CList Tastenkombinationen",
3 | "keybinds.waypoint.add": "Wegpunkt hier erstellen",
4 | "keybinds.waypoints.menu": "Wegpunkte Menü öffnen",
5 | "keybinds.waypoints.toggle": "Sichtbarkeit der Wegpunkte umschalten",
6 | "coordinatelist.midnightconfig.title": "CList Konfiguration",
7 | "coordinatelist.midnightconfig.multiplier": "Größe der Wegpunkte",
8 | "coordinatelist.midnightconfig.render_distance": "Sichtweite der Wegpunkte (0 für unendliche Sichtweite)",
9 | "coordinatelist.midnightconfig.waypoints_toggled": "Wegpunkte anzeigen",
10 | "coordinatelist.midnightconfig.can_place_deathpoints": "Automatisch Wegpunkte bei Tod erstellen",
11 | "waypoint.last.death": "Letzter Todespunkt",
12 | "waypoint.new.waypoint": "Neuer Wegpunkt",
13 | "buttons.add.new.waypoint": "Wegpunkt hier erstellen",
14 | "tooltip.copy.waypoint.coordinates": "Koordinaten des gewählen Punktes kopieren",
15 | "chat.create.waypoint.message": "[Wegpunkt erstellen]"
16 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/lang/en_us.json:
--------------------------------------------------------------------------------
1 | {
2 | "keybinds.category.name": "CList Keybinds",
3 | "keybinds.waypoint.add": "Add a waypoint in current position",
4 | "keybinds.waypoints.menu": "Open waypoints menu",
5 | "keybinds.waypoints.toggle": "Toggle waypoints visibility",
6 | "coordinatelist.midnightconfig.title": "CList configuration",
7 | "coordinatelist.midnightconfig.multiplier": "Waypoints' size",
8 | "coordinatelist.midnightconfig.render_distance": "The distance to which the waypoint is visible (0 means no limit)",
9 | "coordinatelist.midnightconfig.waypoints_toggled": "Show waypoints",
10 | "coordinatelist.midnightconfig.can_place_deathpoints": "Create waypoints on death",
11 | "coordinatelist.midnightconfig.waypoint_text_background": "Show background behind the waypoint name",
12 | "modmenu.summaryTranslation.coordinatelist": "A simple minimalistic fabric mod for saving your coordinates.",
13 | "modmenu.descriptionTranslation.coordinatelist": "Coordinate List (CList for short) is a simple minimalistic fabric mod for saving your coordinates. No minimaps. Just a list with in-game waypoints.",
14 | "waypoint.last.death": "Last death",
15 | "waypoint.new.waypoint": "New Waypoint",
16 | "buttons.add.new.waypoint": "Add a new waypoint in current position",
17 | "tooltip.copy.waypoint.coordinates": "Click to copy selected waypoints coordinates",
18 | "chat.create.waypoint.message": "[Create a waypoint]"
19 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/lang/ja_jp.json:
--------------------------------------------------------------------------------
1 | {
2 | "keybinds.category.name": "CList",
3 | "keybinds.waypoint.add": "現在位置をウェイポイントに追加",
4 | "keybinds.waypoints.menu": "ウェイポイントのメニューを開く",
5 | "keybinds.waypoints.toggle": "ウェイポイントの表示 ・非表示",
6 | "coordinatelist.midnightconfig.title": "CList 設定",
7 | "coordinatelist.midnightconfig.multiplier": "ウェイポイントの表示サイズ",
8 | "coordinatelist.midnightconfig.render_distance": "ウェイポイントが見える距離(0は制限なし)",
9 | "coordinatelist.midnightconfig.waypoints_toggled": "ウェイポイントを表示する",
10 | "coordinatelist.midnightconfig.can_place_deathpoints": "死亡時にウェイポイントを作成する",
11 | "coordinatelist.midnightconfig.waypoint_text_background": "ウェイポイント名の後ろに背景を表示する",
12 | "modmenu.summaryTranslation.coordinatelist": "シンプルでミニマルなファブリックMODで座標を保存。",
13 | "modmenu.descriptionTranslation.coordinatelist": "Coordinate List (略してCList)は、座標を保存するためのシンプルでミニマルなファブリックMODです。ミニマップはありません。ただゲーム内のウェイポイントをリスト表示するだけです。",
14 | "waypoint.last.death": "死亡地点",
15 | "waypoint.new.waypoint": "新しいウェイポイント",
16 | "buttons.add.new.waypoint": "現在位置を新しいウェイポイントに追加する",
17 | "tooltip.copy.waypoint.coordinates": "クリックすると、選択したウェイポイントの座標がコピーされます。",
18 | "chat.create.waypoint.message": "[ウェイポイントの作成]"
19 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/lang/pl_pl.json:
--------------------------------------------------------------------------------
1 | {
2 | "keybinds.category.name": "Skróty klawiszowe CList",
3 | "keybinds.waypoint.add": "Dodaj punkt orientacyjny w obecnym miejscu",
4 | "keybinds.waypoints.menu": "Otwórz menu punktów orientacyjnych",
5 | "keybinds.waypoints.toggle": "Zmień widoczność punktów orientacyjnych",
6 | "coordinatelist.midnightconfig.title": "Konfiguracja CList",
7 | "coordinatelist.midnightconfig.multiplier": "Rozmiar punktów orientacyjnych",
8 | "coordinatelist.midnightconfig.render_distance": "Odległość na jaką jest widoczny punkt orientacyjny (0 oznacza bez limitu)",
9 | "coordinatelist.midnightconfig.waypoints_toggled": "Pokaż punkty orientacyjne",
10 | "coordinatelist.midnightconfig.can_place_deathpoints": "Twórz punkty orientacyjne przy śmierci",
11 | "coordinatelist.midnightconfig.waypoint_text_background": "Wyświetlaj tło za nazwą punktu orientacyjnego",
12 | "modmenu.summaryTranslation.coordinatelist": "Prosty i minimalistyczny mod na fabric'a do zapisywania swojej pozycji",
13 | "modmenu.descriptionTranslation.coordinatelist": "Coordinate List (w skrócie CList) to prosty i minimalistyczny mod na fabric'a do zapisywania swojej pozycji. Zero minimap. Tylko prosta lista z wyświetlanymi punktami orientacyjnymi w grze.",
14 | "waypoint.last.death": "Ostatnia śmierć",
15 | "waypoint.new.waypoint": "Nowy Punkt Orientacyjny",
16 | "buttons.add.new.waypoint": "Dodaj nowy punkt orientacyjny w obecnym miejscu",
17 | "tooltip.copy.waypoint.coordinates": "Kliknij aby skopiować współrzędne wybranego punktu orientacyjnego",
18 | "chat.create.waypoint.message": "[Stwórz punkt orientacyjny]"
19 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/lang/pt_br.json:
--------------------------------------------------------------------------------
1 | {
2 | "keybinds.category.name": "Teclas de Atalho do CList",
3 | "keybinds.waypoint.add": "Adicionar um ponto de referência na posição atual",
4 | "keybinds.waypoints.menu": "Abrir menu de pontos de referência",
5 | "keybinds.waypoints.toggle": "Alternar visibilidade dos pontos de referência",
6 | "coordinatelist.midnightconfig.title": "Configuração do CList",
7 | "coordinatelist.midnightconfig.multiplier": "Tamanho dos pontos de referência",
8 | "coordinatelist.midnightconfig.render_distance": "A distância até a qual o ponto de referência é visível (0 significa sem limite)",
9 | "coordinatelist.midnightconfig.waypoints_toggled": "Mostrar pontos de referência",
10 | "coordinatelist.midnightconfig.can_place_deathpoints": "Criar pontos de referência ao morrer",
11 | "coordinatelist.midnightconfig.waypoint_text_background": "Mostrar fundo atrás do nome do ponto de referência",
12 | "modmenu.summaryTranslation.coordinatelist": "Um mod fabric simples e minimalista para salvar suas coordenadas.",
13 | "modmenu.descriptionTranslation.coordinatelist": "Coordinate List (Lista de Coordenadas ou CList para abreviar) é um mod fabric simples e minimalista para salvar suas coordenadas. Sem mini-mapas. Apenas uma lista com pontos de referência no jogo.",
14 | "waypoint.last.death": "Última morte",
15 | "waypoint.new.waypoint": "Novo Ponto de Referência",
16 | "buttons.add.new.waypoint": "Adicionar um novo ponto de referência na posição atual",
17 | "tooltip.copy.waypoint.coordinates": "Clique para copiar as coordenadas dos pontos de referência selecionados",
18 | "chat.create.waypoint.message": "[Criar um ponto de referência]"
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/lang/ru_ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "keybinds.category.name": "Сочетания Клавиш CList",
3 | "keybinds.waypoint.add": "Добавить путевую точку в текущей позиции",
4 | "keybinds.waypoints.menu": "Открыть меню путевых точек",
5 | "waypoint.last.death": "Последняя смерть",
6 | "waypoint.new.waypoint": "Новая Путевая Точка",
7 | "buttons.add.new.waypoint": "Создать новую путевую точку в текущей позиции"
8 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/lang/zh_cn.json:
--------------------------------------------------------------------------------
1 | {
2 | "keybinds.category.name": "CList 快捷键",
3 | "keybinds.waypoint.add": "在当前位置添加路径点",
4 | "keybinds.waypoints.menu": "打开路径点菜单",
5 | "keybinds.waypoints.toggle": "切换路径点可见性",
6 | "coordinatelist.midnightconfig.title": "CList 配置",
7 | "coordinatelist.midnightconfig.multiplier": "路径点大小",
8 | "coordinatelist.midnightconfig.render_distance": "路径点可见的距离(0 表示无限制)",
9 | "coordinatelist.midnightconfig.waypoints_toggled": "显示路径点",
10 | "coordinatelist.midnightconfig.can_place_deathpoints": "死亡时创建路径点",
11 | "coordinatelist.midnightconfig.waypoint_text_background": "在路径点名称后面显示背景",
12 | "modmenu.summaryTranslation.coordinatelist": "一个简单的极简主义Fabric模组,用于保存您的坐标。",
13 | "modmenu.descriptionTranslation.coordinatelist": "CoordinateList(简称CList)是一个简单的极简主义Fabric模组,用于保存您的坐标。没有小地图。只有一个包含于游戏的内路径点的列表。",
14 | "waypoint.last.death": "最后死亡点",
15 | "waypoint.new.waypoint": "新路径点",
16 | "buttons.add.new.waypoint": "在当前位置添加一个新路径点",
17 | "tooltip.copy.waypoint.coordinates": "点击复制选中的路径点坐标",
18 | "chat.create.waypoint.message": "[创建路径点]"
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/skull.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PouekDEV/CList/0b29e293fb68139f4c4803f1102d12351f0bea13/src/main/resources/assets/coordinatelist/skull.png
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/textures/gui/sprites/icon/change.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PouekDEV/CList/0b29e293fb68139f4c4803f1102d12351f0bea13/src/main/resources/assets/coordinatelist/textures/gui/sprites/icon/change.png
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/textures/gui/sprites/icon/not_visible.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PouekDEV/CList/0b29e293fb68139f4c4803f1102d12351f0bea13/src/main/resources/assets/coordinatelist/textures/gui/sprites/icon/not_visible.png
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/textures/gui/sprites/icon/visible.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PouekDEV/CList/0b29e293fb68139f4c4803f1102d12351f0bea13/src/main/resources/assets/coordinatelist/textures/gui/sprites/icon/visible.png
--------------------------------------------------------------------------------
/src/main/resources/assets/coordinatelist/waypoint_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PouekDEV/CList/0b29e293fb68139f4c4803f1102d12351f0bea13/src/main/resources/assets/coordinatelist/waypoint_icon.png
--------------------------------------------------------------------------------
/src/main/resources/coordinatelist.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "one.pouekdev.coordinatelist.mixin",
5 | "compatibilityLevel": "JAVA_21",
6 | "mixins": [
7 | "CListChatGrabber"
8 | ],
9 | "injectors": {
10 | "defaultRequire": 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/resources/fabric.mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": 1,
3 | "id": "coordinatelist",
4 | "version": "${version}",
5 |
6 | "name": "CList",
7 | "description": "Coordinate List (CList for short) is a simple minimalistic fabric mod for saving your coordinates. No minimaps. Just a list with in-game waypoints.",
8 | "authors": [
9 | "PouekDEV"
10 | ],
11 | "contact": {
12 | "homepage": "https://modrinth.com/mod/clist",
13 | "sources": "https://github.com/PouekDEV/CList",
14 | "issues": "https://github.com/PouekDEV/CList/issues"
15 | },
16 |
17 | "license": "MIT License",
18 | "icon": "assets/coordinatelist/icon.png",
19 |
20 | "environment": "client",
21 | "entrypoints": {
22 | "main": [
23 | "one.pouekdev.coordinatelist.CList"
24 | ],
25 | "client": [
26 | "one.pouekdev.coordinatelist.CListClient"
27 | ]
28 | },
29 | "mixins": [
30 | "coordinatelist.mixins.json"
31 | ],
32 |
33 | "depends": {
34 | "fabricloader": ">=0.16.10",
35 | "fabric-api": "*",
36 | "minecraft": "~1.21.5",
37 | "java": ">=21",
38 | "midnightlib": ">=1.7.1"
39 | },
40 |
41 | "suggests": {
42 | "another-mod": "*"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------