├── icon.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── src
└── main
│ ├── resources
│ ├── assets
│ │ └── trajectoryfabric
│ │ │ ├── icon.png
│ │ │ └── lang
│ │ │ ├── en_us.json
│ │ │ └── pt_br.json
│ └── fabric.mod.json
│ └── java
│ └── net
│ └── Segovo
│ └── TrajectoryFabric
│ ├── RenderUtils.java
│ ├── TrajectoryFabric.java
│ └── TrajectoryCommands.java
├── settings.gradle
├── .gitignore
├── README.md
├── gradle.properties
├── .github
└── workflows
│ └── gradle.yml
├── LICENSE
├── gradlew.bat
└── gradlew
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/segovo/TrajectoryFabric/HEAD/icon.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/segovo/TrajectoryFabric/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/src/main/resources/assets/trajectoryfabric/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/segovo/TrajectoryFabric/HEAD/src/main/resources/assets/trajectoryfabric/icon.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | jcenter()
4 | maven {
5 | name = 'Fabric'
6 | url = 'https://maven.fabricmc.net/'
7 | }
8 | gradlePluginPortal()
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/resources/assets/trajectoryfabric/lang/en_us.json:
--------------------------------------------------------------------------------
1 | {
2 | "lineRes.set": "Line resolution set to %s",
3 | "lineColor.set": "Line color set to %s",
4 | "arrowTrajectory.true": "Arrow trajectory visualization turned on",
5 | "arrowTrajectory.false": "Arrow trajectory visualization turned off"
6 | }
--------------------------------------------------------------------------------
/.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 | # fabric
28 |
29 | run/
30 |
--------------------------------------------------------------------------------
/src/main/resources/assets/trajectoryfabric/lang/pt_br.json:
--------------------------------------------------------------------------------
1 | {
2 | "lineRes.set": "Resolução da linha definida para %s",
3 | "lineColor.set": "Cor da linha definida para %s",
4 | "arrowTrajectory.true": "Visualização de trajetória da flecha ativada",
5 | "arrowTrajectory.false": "Visualização de trajetória da flecha desativada"
6 | }
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TrajectoryFabric
2 | Renders an estimated Trajectory of projectiles
3 |
4 | https://www.curseforge.com/minecraft/mc-mods/trajectoryfabric
5 |
6 | ### Config
7 | Uses the command /trajectory to set color (RGBA) of the line and resolution (Low, Medium or High)
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Done to increase the memory available to gradle.
2 | org.gradle.jvmargs=-Xmx1G
3 |
4 | # Fabric Properties
5 | # check these on https://fabricmc.net/use
6 | minecraft_version=1.20.1
7 | yarn_mappings=1.20.1+build.9
8 | loader_version=0.14.21
9 |
10 | # Mod Properties
11 | mod_version = 1.1.2
12 | maven_group = net.fabricmc
13 | archives_base_name = TrajectoryFabric
14 |
15 | # Dependencies
16 | # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
17 | fabric_version=0.85.0+1.20.1
18 | night_config_version=3.6.6
19 | # cloth_events_version=1.2.0
20 | # cloth_config_version=4.5.6
21 |
--------------------------------------------------------------------------------
/.github/workflows/gradle.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Gradle
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
3 |
4 | name: Java CI with Gradle
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | pull_request:
10 | branches: [ master ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 | strategy:
17 | matrix:
18 | java: [18, 17]
19 |
20 | steps:
21 | - uses: actions/checkout@v2
22 | - name: Set up JDK ${{ matrix.java }}
23 | uses: actions/setup-java@v1
24 | with:
25 | java-version: ${{ matrix.java }}
26 | - name: Grant execute permission for gradlew
27 | run: chmod +x gradlew
28 | - name: Build with Gradle
29 | run: ./gradlew build
30 |
--------------------------------------------------------------------------------
/src/main/resources/fabric.mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": 1,
3 | "id": "trajectoryfabric",
4 | "version": "${version}",
5 |
6 | "name": "Trajectory Fabric",
7 | "description": "Predicts the Trajectory of projectiles",
8 | "authors": [
9 | "Segovo"
10 | ],
11 | "contact": {
12 | "homepage": "https://github.com/segovo/TrajectoryFabric",
13 | "sources": "https://github.com/segovo/TrajectoryFabric"
14 | },
15 |
16 | "license": "MIT",
17 | "icon": "assets/trajectoryfabric/icon.png",
18 |
19 | "environment": "client",
20 | "entrypoints": {
21 | "client": [ "net.Segovo.TrajectoryFabric.TrajectoryFabric" ]
22 | },
23 | "mixins": [],
24 | "depends": {
25 | "fabricloader": ">=0.14.21",
26 | "fabric": "*",
27 | "minecraft": "~1.20.1",
28 | "java": ">=17"
29 | },
30 | "suggests": {
31 | "flamingo": "*"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 segovo
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 |
--------------------------------------------------------------------------------
/src/main/java/net/Segovo/TrajectoryFabric/RenderUtils.java:
--------------------------------------------------------------------------------
1 | package net.Segovo.TrajectoryFabric;
2 |
3 | //shamelessly ripped from https://github.com/ate47/Xray/blob/fabric-1.19/src/main/java/fr/atesab/xray/utils/RenderUtils.java
4 | import net.minecraft.client.render.VertexConsumer;
5 | import net.minecraft.client.util.math.MatrixStack;
6 | import org.joml.Matrix3f;
7 | import org.joml.Matrix4f;
8 | import org.joml.Vector3f;
9 |
10 | public class RenderUtils {
11 |
12 | public static void renderSingleLine(MatrixStack stack, VertexConsumer buffer, float x1, float y1, float z1,
13 | float x2, float y2,
14 | float z2, float r, float g, float b, float a) {
15 | Vector3f normal = new Vector3f(x2 - x1, y2 - y1, z2 - z1);
16 | normal.normalize();
17 | renderSingleLine(stack, buffer, x1, y1, z1, x2, y2, z2, r, g, b, a, normal.x(), normal.y(),
18 | normal.z());
19 | }
20 |
21 | public static void renderSingleLine(MatrixStack stack, VertexConsumer buffer, float x1, float y1, float z1,
22 | float x2, float y2,
23 | float z2, float r, float g, float b, float a, float normalX, float normalY, float normalZ) {
24 | Matrix4f matrix4f = stack.peek().getPositionMatrix();
25 | Matrix3f matrix3f = stack.peek().getNormalMatrix();
26 | buffer.vertex(matrix4f, x1, y1, z1).color(r, g, b, a)
27 | .normal(matrix3f, normalX, normalY, normalZ).next();
28 | buffer.vertex(matrix4f, x2, y2, z2).color(r, g, b, a)
29 | .normal(matrix3f, normalX, normalY, normalZ).next();
30 | }
31 | }
--------------------------------------------------------------------------------
/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 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto init
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto init
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :init
68 | @rem Get command-line arguments, handling Windows variants
69 |
70 | if not "%OS%" == "Windows_NT" goto win9xME_args
71 |
72 | :win9xME_args
73 | @rem Slurp the command line arguments.
74 | set CMD_LINE_ARGS=
75 | set _SKIP=2
76 |
77 | :win9xME_args_slurp
78 | if "x%~1" == "x" goto execute
79 |
80 | set CMD_LINE_ARGS=%*
81 |
82 | :execute
83 | @rem Setup the command line
84 |
85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
86 |
87 |
88 | @rem Execute Gradle
89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
90 |
91 | :end
92 | @rem End local scope for the variables with windows NT shell
93 | if "%ERRORLEVEL%"=="0" goto mainEnd
94 |
95 | :fail
96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
97 | rem the _cmd.exe /c_ return code!
98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
99 | exit /b 1
100 |
101 | :mainEnd
102 | if "%OS%"=="Windows_NT" endlocal
103 |
104 | :omega
105 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or 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 UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/src/main/java/net/Segovo/TrajectoryFabric/TrajectoryFabric.java:
--------------------------------------------------------------------------------
1 | package net.Segovo.TrajectoryFabric;
2 |
3 | import com.electronwill.nightconfig.core.ConfigSpec;
4 | import com.electronwill.nightconfig.core.file.FileConfig;
5 | import com.mojang.blaze3d.systems.RenderSystem;
6 | import net.fabricmc.api.ClientModInitializer;
7 | import net.fabricmc.loader.api.FabricLoader;
8 | import net.minecraft.client.MinecraftClient;
9 | import net.minecraft.client.render.*;
10 | import net.minecraft.client.util.math.MatrixStack;
11 | import net.minecraft.entity.player.PlayerEntity;
12 | import net.minecraft.entity.projectile.thrown.SnowballEntity;
13 | import net.minecraft.item.Item;
14 | import net.minecraft.item.ItemStack;
15 | import net.minecraft.item.Items;
16 | import net.minecraft.util.hit.HitResult;
17 | import net.minecraft.util.math.BlockPos;
18 | import net.minecraft.util.math.MathHelper;
19 | import net.minecraft.util.math.Vec3d;
20 | import net.minecraft.world.RaycastContext;
21 | import net.minecraft.world.World;
22 | import org.lwjgl.opengl.GL11;
23 | import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
24 | import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
25 | import java.io.File;
26 | import java.util.HashSet;
27 | import java.util.Set;
28 | import net.minecraft.client.render.WorldRenderer;
29 | import net.minecraft.util.math.Box;
30 |
31 | //Code snippets from https://github.com/shedaniel/LightOverlay/blob/1.16/src/main/java/me/shedaniel/lightoverlay/fabric/LightOverlay.java
32 |
33 | //###########
34 | //The main functionality of the mod, including rendering/simulating the line and checking/repairing the config.
35 | //###########
36 |
37 | public class TrajectoryFabric implements ClientModInitializer {
38 |
39 | final boolean smoothLines = true;
40 | static File configFile = new File(FabricLoader.getInstance().getConfigDirectory() + "/trajectoryconfig.json");
41 | static FileConfig config = FileConfig.of(configFile);
42 | static double angleToHit = 0;
43 |
44 | public static FileConfig getConfigRef() {
45 | return config;
46 | }
47 |
48 | public static void remoteLoadConfig() {
49 | config.load();
50 | }
51 |
52 | public int[] getConfigColor() {
53 | return new int[] {config.get("lineColorR"), config.get("lineColorG"), config.get("lineColorB"), config.get("lineColorA")};
54 | }
55 |
56 | public boolean[] getConfigBooleans() {
57 | return new boolean[] {config.get("lineVisibility"), config.get("boxVisibility"), config.get("approxBoxVisibility")};
58 | }
59 |
60 | public int[] getConfigIntegers() {
61 | return new int[] {config.get("lineOrigin")};
62 | }
63 |
64 | public static void renderBox(MatrixStack stack, VertexConsumer buffer, double x1, double y1, double z1, double x2, double y2, double z2, int[] color) {
65 | Box aabb = new Box(x1, y1, z1, x2, y2, z2);
66 | WorldRenderer.drawBox(stack, buffer, aabb, color[0]/255, color[1]/255, color[2]/255, color[3]/100);
67 | }
68 |
69 | public static void renderCurve(MatrixStack stack, VertexConsumer buffer, Camera camera, World world, BlockPos pos, float pitch, float yaw, double eye, PlayerEntity player, int[] color, float speed, float gravity, boolean[] booleans, int[] integers, boolean mainHand) {
70 | double d0 = camera.getPos().x;
71 | double d1 = camera.getPos().y - .005D;
72 | double d2 = camera.getPos().z;
73 | double accurateX = player.getX();
74 | double accurateY = player.getY();
75 | double accurateZ = player.getZ();
76 |
77 | float drag = 0.99f;
78 |
79 | float entityVelX = -MathHelper.sin(yaw * 0.017453292F) * MathHelper.cos(pitch * 0.017453292F);
80 | float entityVelY = -MathHelper.sin(pitch * 0.017453292F);
81 | float entityVelZ = MathHelper.cos(yaw * 0.017453292F) * MathHelper.cos(pitch * 0.017453292F);
82 | Vec3d vec3d = (new Vec3d(entityVelX, entityVelY, entityVelZ)).normalize().multiply(speed);
83 | Vec3d entityVelocity = new Vec3d(vec3d.x, vec3d.y, vec3d.z);
84 | Vec3d entityPosition = new Vec3d(0, 0 + 1.5, 0);
85 |
86 | int playerside = 1;
87 | if (integers[0] != 2) {
88 | playerside = (integers[0] == 3 ? 1 : -1);
89 | } else {
90 | playerside = (mainHand ? 1 : -1);
91 | }
92 |
93 | var preferredHand = MinecraftClient.getInstance().player.getMainArm();
94 | if (preferredHand.getId()==0){
95 | playerside = playerside*(-1);
96 | }
97 |
98 | double offsetX = 0 * Math.cos(Math.toRadians((yaw + 90) * -1)) + playerside * Math.sin(Math.toRadians((yaw + 90) * -1));
99 | double offsetZ = 0 * Math.sin(Math.toRadians((yaw + 90) * -1)) + playerside * Math.cos(Math.toRadians((yaw + 90) * -1));
100 |
101 | double prevX = 0;
102 | double prevZ = 0;
103 |
104 | SnowballEntity tempEntity = new SnowballEntity(world, player);
105 |
106 | for (int i=0; i < 100; i++) {
107 | HitResult hitResult = world.raycast(new RaycastContext(new Vec3d(accurateX + entityPosition.x, accurateY + entityPosition.y, accurateZ + entityPosition.z), new Vec3d(accurateX + entityPosition.x, accurateY + entityPosition.y, accurateZ + entityPosition.z).add(entityVelocity), RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, tempEntity));
108 | if (hitResult.getType() != HitResult.Type.MISS) {
109 | double hitDistance = hitResult.getPos().distanceTo(player.getPos());
110 | double boxSize = hitDistance > 30 ? hitDistance/70 : 0.5;
111 | double defaultBoxSize = 0.5; // 0.5 = full block
112 | if (booleans[1]) { //Box visibility
113 | renderBox(stack, buffer, hitResult.getPos().x - defaultBoxSize - d0, hitResult.getPos().y - defaultBoxSize - d1, hitResult.getPos().z - defaultBoxSize - d2, hitResult.getPos().x + defaultBoxSize - d0, hitResult.getPos().y + defaultBoxSize - d1, hitResult.getPos().z + defaultBoxSize - d2, color);
114 | }
115 | if (booleans[2]) { //ApproxBox visibility
116 | renderBox(stack, buffer, hitResult.getPos().x - boxSize - d0, hitResult.getPos().y - boxSize - d1, hitResult.getPos().z - boxSize - d2, hitResult.getPos().x + boxSize - d0, hitResult.getPos().y + boxSize - d1, hitResult.getPos().z + boxSize - d2, color);
117 | }
118 | angleToHit = Math.acos(playerside / hitDistance); //finds the angle the line needs to point at to hit the target (since it's coming from the side, and changes depending on distance),
119 | // the "1" represents the opposite side, which we know. (opposite/adjacent).
120 | //
121 | // Good reference: https://www.khanacademy.org/math/geometry/hs-geo-trig/hs-geo-solve-for-an-angle/a/inverse-trig-functions-intro
122 | break;
123 | }
124 |
125 |
126 | double startx = prevX + offsetX + (accurateX - d0);
127 | double starty = entityPosition.y + (accurateY - d1);
128 | double startz = prevZ + offsetZ + (accurateZ - d2);
129 |
130 | entityPosition = entityPosition.add(entityVelocity);
131 | entityVelocity = entityVelocity.multiply(drag);
132 | entityVelocity = new Vec3d(entityVelocity.x, entityVelocity.y - gravity, entityVelocity.z);
133 | double newX = entityPosition.x * Math.cos(angleToHit-1.5708) - entityPosition.z * Math.sin(angleToHit-1.5708); // Rotation to point trajectory curve towards hit mark.
134 | double newZ = entityPosition.x * Math.sin(angleToHit-1.5708) + entityPosition.z * Math.cos(angleToHit-1.5708); //
135 |
136 | if (booleans[0]) { //Line visibility
137 | double endx = newX + offsetX + (accurateX-d0);
138 | double endy = entityPosition.y + (accurateY - d1);
139 | double endz = newZ + offsetZ + (accurateZ - d2);
140 | RenderUtils.renderSingleLine(stack, buffer, (float) startx, (float) starty, (float) startz, (float) endx, (float) endy, (float) endz, color[0] / 255f, color[1] / 255f, color[2] / 255f, (float)color[3]/100);
141 |
142 | }
143 |
144 | prevX = newX;
145 | prevZ = newZ;
146 | }
147 |
148 | }
149 |
150 | @Override
151 | public void onInitializeClient() {
152 | //Night Config
153 | System.out.println("Config path: " + FabricLoader.getInstance().getConfigDirectory());
154 | config.load();
155 |
156 | ConfigSpec spec = new ConfigSpec();
157 | spec.defineInRange("lineOrigin", 3, 1, 3);
158 | spec.define("lineVisibility", true);
159 | spec.define("boxVisibility", true);
160 | spec.define("approxBoxVisibility", true);
161 | spec.define("arrowTrajectory", true);
162 | spec.defineInRange("lineColorR", 255, 0, 255);
163 | spec.defineInRange("lineColorG", 255, 0, 255);
164 | spec.defineInRange("lineColorB", 255, 0, 255);
165 | spec.defineInRange("lineColorA", 100, 0, 100);
166 |
167 | ConfigSpec.CorrectionListener listener = (action, path, incorrectValue, correctedValue) -> {
168 | String pathString = String.join(",", path);
169 | System.out.println("Corrected " + pathString + ": was " + incorrectValue + ", is now " + correctedValue);
170 | };
171 | int numberOfCorrections = spec.correct(config, listener);
172 |
173 | if (numberOfCorrections >= 1) {
174 | System.out.println("Saved config");
175 | config.save();
176 | }
177 |
178 | // Rendering
179 | Set- itemsSimple = new HashSet<>();
180 | itemsSimple.add(Items.ENDER_PEARL.asItem());
181 | itemsSimple.add(Items.SNOWBALL.asItem());
182 | itemsSimple.add(Items.EGG.asItem());
183 |
184 | Set
- itemsComplex = new HashSet<>();
185 | itemsComplex.add(Items.BOW.asItem());
186 |
187 | MinecraftClient client = MinecraftClient.getInstance();
188 |
189 | WorldRenderEvents.END.register((WorldRenderContext context) -> {
190 | MatrixStack stack = context.matrixStack();
191 |
192 | RenderSystem.setShader(GameRenderer::getPositionColorProgram);
193 | RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
194 | RenderSystem.depthMask(false);
195 | RenderSystem.enableBlend();
196 | RenderSystem.defaultBlendFunc();
197 | if (smoothLines) GL11.glEnable(GL11.GL_LINE_SMOOTH);
198 |
199 | stack.push();
200 | Tessellator tessellator = Tessellator.getInstance();
201 | BufferBuilder buffer = tessellator.getBuffer();
202 | buffer.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR);
203 |
204 | RenderSystem.applyModelViewMatrix();
205 | Camera camera = client.gameRenderer.getCamera();
206 | Vec3d cameraPos = camera.getPos();
207 |
208 | PlayerEntity playerEntity = client.player;
209 | World world = client.world;
210 | BlockPos blockPos = new BlockPos((int)playerEntity.getX(), (int)playerEntity.getY(), (int)playerEntity.getZ());
211 | float pitch = playerEntity.getPitch();
212 | float yaw = playerEntity.getYaw();
213 | double eye = playerEntity.getEyeY();
214 | ItemStack itemStack = playerEntity.getMainHandStack();
215 | ItemStack itemStackAlt = playerEntity.getOffHandStack();
216 |
217 | // Set mainHand to true/false based on which hand is holding a item which is a projectile.
218 | boolean mainHand = true;
219 | if (itemsSimple.contains(itemStack.getItem()) || itemsComplex.contains(itemStack.getItem())) { mainHand = true; }
220 | else if (itemsSimple.contains(itemStackAlt.getItem()) || itemsComplex.contains(itemStackAlt.getItem())) { mainHand = false; };
221 |
222 | if (itemsSimple.contains(itemStack.getItem()) || itemsSimple.contains(itemStackAlt.getItem())) {
223 | float speed = 1.5f;
224 | int[] color = getConfigColor();
225 | boolean[] booleans = getConfigBooleans();
226 | int[] integers = getConfigIntegers();
227 | TrajectoryFabric.renderCurve(stack, buffer, camera, world, blockPos, pitch, yaw, eye, playerEntity, color, speed, 0.03f, booleans, integers, mainHand);
228 | } else if ((itemsComplex.contains(itemStack.getItem()) || itemsComplex.contains(itemStackAlt.getItem())) && ((boolean)config.get("arrowTrajectory"))) {
229 | float bowMultiplier = (72000.0f - playerEntity.getItemUseTimeLeft()) / 20.0f;
230 | bowMultiplier = (bowMultiplier * bowMultiplier + bowMultiplier * 2.0f) / 3.0f;
231 | if (bowMultiplier > 1.0f) {
232 | bowMultiplier = 1.0f;
233 | }
234 |
235 | float speed = bowMultiplier * 3.0f;
236 | int[] color = getConfigColor();
237 | boolean[] booleans = getConfigBooleans();
238 | int[] integers = getConfigIntegers();
239 | TrajectoryFabric.renderCurve(stack, buffer, camera, world, blockPos, pitch, yaw, eye, playerEntity, color, speed, 0.05f, booleans, integers, mainHand);
240 | }
241 |
242 | tessellator.draw();
243 | stack.pop();
244 | RenderSystem.applyModelViewMatrix();
245 | RenderSystem.setShaderColor(1, 1, 1, 1);
246 |
247 | RenderSystem.disableBlend();
248 | if (smoothLines) GL11.glDisable(GL11.GL_LINE_SMOOTH);
249 | });
250 | TrajectoryCommands.registerCommands();
251 |
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/src/main/java/net/Segovo/TrajectoryFabric/TrajectoryCommands.java:
--------------------------------------------------------------------------------
1 | package net.Segovo.TrajectoryFabric;
2 |
3 | import com.electronwill.nightconfig.core.file.FileConfig;
4 | import com.mojang.brigadier.CommandDispatcher;
5 | import com.mojang.brigadier.arguments.IntegerArgumentType;
6 | import net.fabricmc.loader.api.FabricLoader;
7 | import net.minecraft.client.MinecraftClient;
8 | import net.minecraft.network.message.MessageType;
9 | import net.minecraft.text.Text;
10 | import com.mojang.brigadier.arguments.BoolArgumentType;
11 | import java.awt.*;
12 | import java.io.File;
13 |
14 | import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
15 | import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
16 | import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
17 |
18 | //###########
19 | //Registers the commands and defines their functionality.
20 | //###########
21 |
22 | public class TrajectoryCommands {
23 |
24 | static FileConfig config = getConfigReference();
25 |
26 | public static void registerCommands() {
27 |
28 | ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
29 | dispatcher.register(
30 | ClientCommandManager.literal("trajectory")
31 | .then(ClientCommandManager.literal("lineColor")
32 | .then(ClientCommandManager.argument("red", IntegerArgumentType.integer(0, 255))
33 | .then(ClientCommandManager.argument("green", IntegerArgumentType.integer(0, 255))
34 | .then(ClientCommandManager.argument("blue", IntegerArgumentType.integer(0, 255))
35 | .then(ClientCommandManager.argument("alpha", IntegerArgumentType.integer(0, 100)).executes(context -> {
36 | config.set("lineColorR", getInteger(context, "red"));
37 | config.set("lineColorG", getInteger(context, "green"));
38 | config.set("lineColorB", getInteger(context, "blue"));
39 | config.set("lineColorA", getInteger(context, "alpha"));
40 | config.save();
41 | TrajectoryFabric.remoteLoadConfig();
42 | sendPrivateMessage(Text.translatable("lineColor.set", describeColor(getInteger(context, "red"), getInteger(context, "green"), getInteger(context, "blue"))));
43 | return 1;
44 | })
45 |
46 | )))))
47 | .then(ClientCommandManager.literal("arrowTrajectory")
48 | .then(ClientCommandManager.literal("true").executes(context -> {
49 | config.set("arrowTrajectory", true);
50 | config.save();
51 | TrajectoryFabric.remoteLoadConfig();
52 | sendPrivateMessage(Text.translatable("arrowTrajectory.true"));
53 | return 1;
54 | }))
55 | .then(ClientCommandManager.literal("false").executes(context -> {
56 | config.set("arrowTrajectory", false);
57 | config.save();
58 | TrajectoryFabric.remoteLoadConfig();
59 | sendPrivateMessage(Text.translatable("arrowTrajectory.false"));
60 | return 1;
61 | }))
62 | )
63 | .then(ClientCommandManager.literal("componentVisibility")
64 | .then(ClientCommandManager.literal("line")
65 | .then(ClientCommandManager.literal("true").executes(context -> {
66 | config.set("lineVisibility", true);
67 | config.save();
68 | TrajectoryFabric.remoteLoadConfig();
69 | sendPrivateMessage(Text.translatable("lineVisibility.true"));
70 | return 1;
71 | }))
72 | .then(ClientCommandManager.literal("false").executes(context -> {
73 | config.set("lineVisibility", false);
74 | config.save();
75 | TrajectoryFabric.remoteLoadConfig();
76 | sendPrivateMessage(Text.translatable("lineVisibility.false"));
77 | return 1;
78 | }))
79 | )
80 | .then(ClientCommandManager.literal("box")
81 | .then(ClientCommandManager.literal("true").executes(context -> {
82 | config.set("boxVisibility", true);
83 | config.save();
84 | TrajectoryFabric.remoteLoadConfig();
85 | sendPrivateMessage(Text.translatable("boxVisibility.true"));
86 | return 1;
87 | }))
88 | .then(ClientCommandManager.literal("false").executes(context -> {
89 | config.set("boxVisibility", false);
90 | config.save();
91 | TrajectoryFabric.remoteLoadConfig();
92 | sendPrivateMessage(Text.translatable("boxVisibility.false"));
93 | return 1;
94 | }))
95 | )
96 | .then(ClientCommandManager.literal("approxBox")
97 | .then(ClientCommandManager.literal("true").executes(context -> {
98 | config.set("approxBoxVisibility", true);
99 | config.save();
100 | TrajectoryFabric.remoteLoadConfig();
101 | sendPrivateMessage(Text.translatable("approxBoxVisibility.true"));
102 | return 1;
103 | }))
104 | .then(ClientCommandManager.literal("false").executes(context -> {
105 | config.set("approxBoxVisibility", false);
106 | config.save();
107 | TrajectoryFabric.remoteLoadConfig();
108 | sendPrivateMessage(Text.translatable("approxBoxVisibility.false"));
109 | return 1;
110 | }))
111 | )
112 | )
113 | .then(ClientCommandManager.literal("lineOrigin")
114 | .then(ClientCommandManager.literal("left").executes(context -> {
115 | config.set("lineOrigin", 1);
116 | config.save();
117 | TrajectoryFabric.remoteLoadConfig();
118 | sendPrivateMessage(Text.translatable("lineOrigin.left"));
119 | return 1;
120 | }))
121 | .then(ClientCommandManager.literal("auto").executes(context -> {
122 | config.set("lineOrigin", 2);
123 | config.save();
124 | TrajectoryFabric.remoteLoadConfig();
125 | sendPrivateMessage(Text.translatable("lineOrigin.auto"));
126 | return 1;
127 | }))
128 | .then(ClientCommandManager.literal("right").executes(context -> {
129 | config.set("lineOrigin", 3);
130 | config.save();
131 | TrajectoryFabric.remoteLoadConfig();
132 | sendPrivateMessage(Text.translatable("lineOrigin.right"));
133 | return 1;
134 | }))
135 | )
136 |
137 | );
138 | });
139 | }
140 |
141 | // https://github.com/AMereBagatelle/AFKPeace/blob/1.16.x/src/main/java/amerebagatelle/github/io/afkpeace/commands/ConfigCommand.java
142 | public static void sendPrivateMessage(Text message) {
143 | MinecraftClient mc = MinecraftClient.getInstance();
144 | mc.inGameHud.getChatHud().addMessage( message);
145 | }
146 |
147 | public static FileConfig getConfigReference() {
148 | return TrajectoryFabric.getConfigRef();
149 | }
150 |
151 | public static String describeColor(int r, int g, int b) {
152 | double lastSmallestDistance = Double.MAX_VALUE;
153 | String returnColor = "null";
154 | for (int i = 0, color_i = 0; color_i < colorNames.length; i=i+3, color_i++) {
155 | //float rgbDistance = Math.abs(r - colorRGBs[i]) +
156 | // Math.abs(g - colorRGBs[i+1]) +
157 | //Math.abs(b - colorRGBs[i+2]);
158 | double rgbDistance = Math.pow((r-colorRGBs[i]), 2)
159 | + Math.pow((g-colorRGBs[i+1]), 2)
160 | + Math.pow((b-colorRGBs[i+2]), 2);
161 | if (rgbDistance < lastSmallestDistance) {
162 | lastSmallestDistance = rgbDistance;
163 | returnColor = colorNames[color_i];
164 | }
165 | }
166 | return returnColor;
167 | }
168 |
169 | static String[] colorNames = {
170 | "maroon",
171 | "dark red",
172 | "brown",
173 | "firebrick",
174 | "crimson",
175 | "red",
176 | "tomato",
177 | "coral reaf",
178 | "indian red",
179 | "light coral",
180 | "dark salmon",
181 | "salmon fish",
182 | "light salmon",
183 | "orange red",
184 | "dark orange",
185 | "orange",
186 | "gold bar",
187 | "dark golden rod",
188 | "golden rod",
189 | "pale golden rod",
190 | "dark khaki pants",
191 | "khaki",
192 | "olive",
193 | "mellow yellow",
194 | "mellow yellow green",
195 | "dark olive green",
196 | "olive drab",
197 | "lawn green",
198 | "chart reuse",
199 | "green yellow",
200 | "dark green",
201 | "green",
202 | "forest green",
203 | "lime",
204 | "lime green",
205 | "light green",
206 | "pale green",
207 | "dark sea green",
208 | "medium spring green",
209 | "spring green",
210 | "sea green",
211 | "medium aqua marine",
212 | "medium sea green",
213 | "light sea green",
214 | "dark slate gray",
215 | "teal",
216 | "dark cyan cup",
217 | "ocean",
218 | "cyan cup",
219 | "light cyan",
220 | "dark turquoise",
221 | "turquoise",
222 | "medium turquoise",
223 | "pale turquoise",
224 | "aqua marine",
225 | "powder blue",
226 | "cadet blue",
227 | "steel blue",
228 | "corn flower blue",
229 | "deep sky blue",
230 | "dodger blue",
231 | "calm sky color",
232 | "sky blue",
233 | "light sky blue",
234 | "midnight blue",
235 | "navy",
236 | "dark blue",
237 | "medium blue",
238 | "blue",
239 | "royal blue",
240 | "blue violet",
241 | "indigo",
242 | "dark slate blue",
243 | "slate blue",
244 | "medium slate blue",
245 | "medium purple plum",
246 | "dark magenta",
247 | "dark violet",
248 | "dark orchid",
249 | "medium orchid",
250 | "fresh purple plum",
251 | "thistle",
252 | "plum",
253 | "violet",
254 | "magenta",
255 | "orchid",
256 | "medium violet red",
257 | "pale violet red",
258 | "deep pink",
259 | "hot pink",
260 | "light pink",
261 | "pink",
262 | "antique white",
263 | "beige.",
264 | "bisque",
265 | "blanched almond",
266 | "wheat",
267 | "corn silk",
268 | "lemon chiffon",
269 | "light golden rod yellow",
270 | "light yellow",
271 | "saddle brown",
272 | "sienna",
273 | "chocolate bar",
274 | "peru",
275 | "sandy brown",
276 | "burly wood",
277 | "boring tan",
278 | "rosy brown",
279 | "moccasin",
280 | "navajo white",
281 | "peach puff",
282 | "misty rose",
283 | "lavender blush",
284 | "linen",
285 | "old lace",
286 | "papaya whip",
287 | "sea shell",
288 | "mint cream",
289 | "slate gray",
290 | "light slate gray",
291 | "light steel blue",
292 | "lavender",
293 | "floral white",
294 | "alice blue",
295 | "ghost white",
296 | "honeydew, yuck",
297 | "ivory",
298 | "azure",
299 | "snow",
300 | "black",
301 | "dim gray",
302 | "gray",
303 | "dark gray",
304 | "silver from the mines",
305 | "light gray",
306 | "gainsboro",
307 | "white smoke",
308 | "white"
309 | };
310 |
311 | static int[] colorRGBs = {
312 | 128,0,0,
313 | 139,0,0,
314 | 165,42,42,
315 | 178,34,34,
316 | 220,20,60,
317 | 255,0,0,
318 | 255,99,71,
319 | 255,127,80,
320 | 205,92,92,
321 | 240,128,128,
322 | 233,150,122,
323 | 250,128,114,
324 | 255,160,122,
325 | 255,69,0,
326 | 255,140,0,
327 | 255,165,0,
328 | 255,215,0,
329 | 184,134,11,
330 | 218,165,32,
331 | 238,232,170,
332 | 189,183,107,
333 | 240,230,140,
334 | 128,128,0,
335 | 255,255,0,
336 | 154,205,50,
337 | 85,107,47,
338 | 107,142,35,
339 | 124,252,0,
340 | 127,255,0,
341 | 173,255,47,
342 | 0,100,0,
343 | 0,128,0,
344 | 34,139,34,
345 | 0,255,0,
346 | 50,205,50,
347 | 144,238,144,
348 | 152,251,152,
349 | 143,188,143,
350 | 0,250,154,
351 | 0,255,127,
352 | 46,139,87,
353 | 102,205,170,
354 | 60,179,113,
355 | 32,178,170,
356 | 47,79,79,
357 | 0,128,128,
358 | 0,139,139,
359 | 0,255,255,
360 | 0,255,255,
361 | 224,255,255,
362 | 0,206,209,
363 | 64,224,208,
364 | 72,209,204,
365 | 175,238,238,
366 | 127,255,212,
367 | 176,224,230,
368 | 95,158,160,
369 | 70,130,180,
370 | 100,149,237,
371 | 0,191,255,
372 | 30,144,255,
373 | 173,216,230,
374 | 135,206,235,
375 | 135,206,250,
376 | 25,25,112,
377 | 0,0,128,
378 | 0,0,139,
379 | 0,0,205,
380 | 0,0,255,
381 | 65,105,225,
382 | 138,43,226,
383 | 75,0,130,
384 | 72,61,139,
385 | 106,90,205,
386 | 123,104,238,
387 | 147,112,219,
388 | 139,0,139,
389 | 148,0,211,
390 | 153,50,204,
391 | 186,85,211,
392 | 128,0,128,
393 | 216,191,216,
394 | 221,160,221,
395 | 238,130,238,
396 | 255,0,255,
397 | 218,112,214,
398 | 199,21,133,
399 | 219,112,147,
400 | 255,20,147,
401 | 255,105,180,
402 | 255,182,193,
403 | 255,192,203,
404 | 250,235,215,
405 | 245,245,220,
406 | 255,228,196,
407 | 255,235,205,
408 | 245,222,179,
409 | 255,248,220,
410 | 255,250,205,
411 | 250,250,210,
412 | 255,255,224,
413 | 139,69,19,
414 | 160,82,45,
415 | 210,105,30,
416 | 205,133,63,
417 | 244,164,96,
418 | 222,184,135,
419 | 210,180,140,
420 | 188,143,143,
421 | 255,228,181,
422 | 255,222,173,
423 | 255,218,185,
424 | 255,228,225,
425 | 255,240,245,
426 | 250,240,230,
427 | 253,245,230,
428 | 255,239,213,
429 | 255,245,238,
430 | 245,255,250,
431 | 112,128,144,
432 | 119,136,153,
433 | 176,196,222,
434 | 230,230,250,
435 | 255,250,240,
436 | 240,248,255,
437 | 248,248,255,
438 | 240,255,240,
439 | 255,255,240,
440 | 240,255,255,
441 | 255,250,250,
442 | 0,0,0,
443 | 105,105,105,
444 | 128,128,128,
445 | 169,169,169,
446 | 192,192,192,
447 | 211,211,211,
448 | 220,220,220,
449 | 245,245,245,
450 | 255,255,255
451 | };
452 |
453 |
454 | }
455 |
--------------------------------------------------------------------------------