9
.gitattributes
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
37
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
# Automatically build the project and run any configured tests for every push
|
||||
# and submitted pull request. This can help catch issues that only occur on
|
||||
# certain platforms or Java versions, and provides a first line of defence
|
||||
# against bad commits.
|
||||
|
||||
name: build
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
# Use these Java versions
|
||||
java: [
|
||||
21, # Current Java LTS
|
||||
]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: validate gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
- name: setup jdk ${{ matrix.java }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: 'microsoft'
|
||||
- name: make gradle wrapper executable
|
||||
run: chmod +x ./gradlew
|
||||
- name: build
|
||||
run: ./gradlew build
|
||||
- name: capture build artifacts
|
||||
if: ${{ matrix.java == '21' }} # Only upload artifacts built from latest java
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Artifacts
|
||||
path: build/libs/
|
44
.gitignore
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# gradle
|
||||
|
||||
.gradle/
|
||||
build/
|
||||
out/
|
||||
classes/
|
||||
|
||||
# eclipse
|
||||
|
||||
*.launch
|
||||
|
||||
# Doxygen ignores
|
||||
**html/*
|
||||
**latex/*
|
||||
|
||||
# idea
|
||||
|
||||
.idea/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# vscode
|
||||
|
||||
.settings/
|
||||
.vscode/
|
||||
bin/
|
||||
.classpath
|
||||
.project
|
||||
|
||||
# macos
|
||||
|
||||
*.DS_Store
|
||||
|
||||
# fabric
|
||||
|
||||
run/
|
||||
|
||||
# java
|
||||
|
||||
hs_err_*.log
|
||||
replay_*.log
|
||||
*.hprof
|
||||
*.jfr
|
121
LICENSE
Normal file
@ -0,0 +1,121 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
95
build.gradle
Normal file
@ -0,0 +1,95 @@
|
||||
plugins {
|
||||
id 'fabric-loom' version '1.7-SNAPSHOT'
|
||||
id 'maven-publish'
|
||||
}
|
||||
|
||||
version = project.mod_version
|
||||
group = project.maven_group
|
||||
|
||||
base {
|
||||
archivesName = project.archives_base_name
|
||||
}
|
||||
|
||||
repositories {
|
||||
// Add repositories to retrieve artifacts from in here.
|
||||
// You should only use this when depending on other mods because
|
||||
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
|
||||
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
|
||||
// for more information about repositories.
|
||||
// maven {
|
||||
// url "https://maven.squiddev.cc"
|
||||
// content {
|
||||
// includeGroup("cc.tweaked")
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
loom {
|
||||
splitEnvironmentSourceSets()
|
||||
|
||||
mods {
|
||||
"keeblarcraft" {
|
||||
sourceSet sourceSets.main
|
||||
sourceSet sourceSets.client
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// To change the versions see the gradle.properties file
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
|
||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
//modCompileOnly "cc.tweaked:cc-tweaked-1.20-fabric-api:1.105.0"
|
||||
//modRuntimeOnly "cc.tweaked:cc-tweaked-1.20-fabric-api:1.105.0"
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "version", project.version
|
||||
|
||||
filesMatching("fabric.mod.json") {
|
||||
expand "version": project.version
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
it.options.release = 17
|
||||
}
|
||||
|
||||
java {
|
||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
||||
// if it is present.
|
||||
// If you remove this line, sources will not be generated.
|
||||
withSourcesJar()
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
jar {
|
||||
from("LICENSE") {
|
||||
rename { "${it}_${project.base.archivesName.get()}"}
|
||||
}
|
||||
}
|
||||
|
||||
// configure the maven publication
|
||||
publishing {
|
||||
publications {
|
||||
create("mavenJava", MavenPublication) {
|
||||
artifactId = project.archives_base_name
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
|
||||
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
||||
repositories {
|
||||
// Add repositories to publish to here.
|
||||
// Notice: This block does NOT have the same function as the block in the top level.
|
||||
// The repositories here will be used for publishing your artifact, not for
|
||||
// retrieving dependencies.
|
||||
}
|
||||
}
|
17
gradle.properties
Normal file
@ -0,0 +1,17 @@
|
||||
# Done to increase the memory available to gradle.
|
||||
org.gradle.jvmargs=-Xmx1G
|
||||
org.gradle.parallel=true
|
||||
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.20
|
||||
yarn_mappings=1.20+build.1
|
||||
loader_version=0.15.11
|
||||
|
||||
# Mod Properties
|
||||
mod_version=0.0.1
|
||||
maven_group=jesse.keeblarcraft
|
||||
archives_base_name=keeblarcraft
|
||||
|
||||
# Dependencies
|
||||
fabric_version=0.83.0+1.20
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
249
gradlew
vendored
Executable file
@ -0,0 +1,249 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
92
gradlew.bat
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
4
installmod.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
rm ~/.minecraft/mods/keeblarcraft* # What else could be named this? Really now?
|
||||
cp build/devlibs/*sources.jar ~/.minecraft/mods
|
||||
echo Moved minecraft to mods dir
|
10
settings.gradle
Normal file
@ -0,0 +1,10 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
maven {
|
||||
name = 'Fabric'
|
||||
url = 'https://maven.fabricmc.net/'
|
||||
}
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
21
src/client/java/jesse/keeblarcraft/KeeblarcraftClient.java
Normal file
@ -0,0 +1,21 @@
|
||||
package jesse.keeblarcraft;
|
||||
|
||||
import jesse.keeblarcraft.gui.ClientHandlers;
|
||||
import jesse.keeblarcraft.gui.ScreenManager;
|
||||
import jesse.keeblarcraft.gui.widgets.TreeWidget;
|
||||
import jesse.keeblarcraft.Shortcuts.ShortcutManager;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
|
||||
|
||||
public class KeeblarcraftClient implements ClientModInitializer {
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
ShortcutManager.RegisterKeybinds();
|
||||
ClientHandlers.RegisterHandlers();
|
||||
|
||||
ScreenManager.GetInstance();
|
||||
ScreenManager.AddWidget(TreeWidget.class, 10);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
*
|
||||
* ShortcutManager
|
||||
*
|
||||
* This is the client-side shortcut keybind manager
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.Shortcuts;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
// import jesse.keeblarcraft.Keeblarcraft;
|
||||
import jesse.keeblarcraft.gui.ScreenManager;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class ShortcutManager {
|
||||
private static KeyBinding skillTreeShortcut;
|
||||
private static KeyBinding globalConfig;
|
||||
private static Boolean toggleTreeGui = true; // Initialized to true for first time pressing keybind to actually display gui
|
||||
// private static ScreenManager treeGui = null;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterKeybinds
|
||||
///
|
||||
/// @brief Registers all player keybinds and callbacks to them
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// All callbacks for keyboard shortcuts are put here
|
||||
public static void RegisterKeybinds() {
|
||||
// Keybindings are registered here
|
||||
skillTreeShortcut = KeyBindingHelper.registerKeyBinding(new KeyBinding(
|
||||
"key.keeblarcraft.treemap",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_K,
|
||||
"category.keeblarcraft.test"
|
||||
));
|
||||
|
||||
globalConfig = KeyBindingHelper.registerKeyBinding(new KeyBinding(
|
||||
"key.keeblarcraft.globalconfig",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_M,
|
||||
"category.keeblarcraft.test"
|
||||
));
|
||||
|
||||
/// Callbacks are down here
|
||||
|
||||
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
||||
// The keybinding util does 2 things in one, if I check the state of the key press it flips a bit and deducts from
|
||||
// the actual pressed amount - which we don't want to do. We will call the callbacks for keybinding functions here,
|
||||
// and let them check the keybind themselves. NOTE: These functions are called at the end of every tick! Future us
|
||||
// should see if there is a less expensive way to check this on just the keybind itself being flipped
|
||||
DrawTreeGui(client);
|
||||
|
||||
if (globalConfig.wasPressed()) {
|
||||
client.player.sendMessage(Text.of("Keeblarcraft recognizes you pressed the config button, but this option doesn't do anything yet"), false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn DrawTreeGui
|
||||
///
|
||||
/// @arg[in] client is the minecraft client instance that is passed in
|
||||
/// so we have context of the client itself
|
||||
///
|
||||
/// @brief Draws the attribute tree GUI
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@SuppressWarnings("resource")
|
||||
public static void DrawTreeGui(MinecraftClient client) {
|
||||
while (skillTreeShortcut.wasPressed()) { // Constant loop required to redraw screen continuously
|
||||
System.out.println("Key pressed detected"); /// TODO: When we figure out how to get key presses to still work when a screen opens; then we can toggle menus with buttons...
|
||||
if (toggleTreeGui) {
|
||||
// There is a technical resource leak that current screen is never closed when defining it here; which is ok I think because we want to return to it anyways
|
||||
Screen currentScreen = MinecraftClient.getInstance().currentScreen;
|
||||
client.player.sendMessage(Text.of("You pressed the GUI key!"));
|
||||
// treeGui = new ScreenManager(Keeblarcraft.TREE_HANDLER.create(0, client.player.getInventory()), client.player.getInventory(), Text.of("Test"));
|
||||
// treeGui.AddParent(currentScreen); ///TODO: Put this in the constructor when you figure out how the hell the magic is happening with registration
|
||||
|
||||
ScreenManager treeGui = ScreenManager.GetInstance();
|
||||
treeGui.AddParent(currentScreen);
|
||||
|
||||
MinecraftClient.getInstance().setScreen(treeGui);
|
||||
|
||||
// toggleTreeGui intentionally never bit-flipped to false as a slight implementation bug exists such that pressing the keybind again
|
||||
// does NOT call this callback function until the previous screen is CLOSED (which is why this isn't resource leaking...). This will
|
||||
// need a slight rework or an extra subcall - but is fine for now since this is just how screens work.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
/*
|
||||
*
|
||||
* IndividualAttribute
|
||||
*
|
||||
* This will be the handler class for each little attribute on the attribute tree itself.
|
||||
* It will be fully implemented in the ticket that finishes the TreeWidget ticket (NOT GuiMgr)
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.gui.AttributeTree;
|
||||
|
||||
// This represents a single node in the tree of attributes drawn to the gui!!!
|
||||
public class IndividualAttribute {
|
||||
|
||||
}
|
11
src/client/java/jesse/keeblarcraft/gui/ClientHandlers.java
Normal file
@ -0,0 +1,11 @@
|
||||
package jesse.keeblarcraft.gui;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreens;
|
||||
|
||||
public class ClientHandlers {
|
||||
public static void RegisterHandlers() {
|
||||
System.out.println("Registering tree handler screen");
|
||||
HandledScreens.register(Keeblarcraft.TREE_HANDLER, ScreenManager::new);
|
||||
}
|
||||
}
|
74
src/client/java/jesse/keeblarcraft/gui/GenericLayerT.java
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
*
|
||||
* GenericLayerT
|
||||
*
|
||||
* GenericLayerT is the class that all layers must inherit from in order to be drawn. This allows for the GUI to properly
|
||||
* draw the layers on which you want your canvas to exist!
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.gui;
|
||||
|
||||
import jesse.keeblarcraft.Utils.CommonStructures.Position2d;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
||||
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
abstract public class GenericLayerT extends ClickableWidget {
|
||||
// These are the box bounds of the widget
|
||||
public int startX;
|
||||
public int startY;
|
||||
public int endX;
|
||||
public int endY;
|
||||
|
||||
public GenericLayerT() {
|
||||
// default constructor
|
||||
super(0, 0, 0, 0, Text.of(""));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GenericLayerT
|
||||
///
|
||||
/// @brief Constructor for class. This is setup directly by the screen
|
||||
/// manager object and it is not recommended to change the x/y
|
||||
/// positions or you may break the relation of your widget to
|
||||
/// others on the screen at the same time!
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public GenericLayerT(int x, int y, int width, int height, Text message) {
|
||||
super(x, y, width, height, message);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn DrawLayer
|
||||
///
|
||||
/// @brief Draw on a layer! This is an early implementation of being
|
||||
/// able to choose the layer you are drawing on and making sure
|
||||
/// you can customize which layer your context will draw on.
|
||||
/// This will be called by the overall screen manager so the
|
||||
/// layer id will be passed in. You will need to handle the layer
|
||||
/// id yourself.
|
||||
///
|
||||
/// @note It is possible to get passed any layer id and you handle each
|
||||
/// layer respectively; however, it is possible to draw on the
|
||||
/// wrong layer if handled wrong. For example, you could be
|
||||
/// passed layer '3' but this function is called for every layer
|
||||
/// drawn on screen; so you must handle this to only draw on a
|
||||
/// specific layer. Be careful!
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public abstract void DrawLayer(DrawContext context, int layer);
|
||||
|
||||
public void UpdateAnchorValues(int x, int y) {
|
||||
this.startX = x;
|
||||
this.startY = y;
|
||||
}
|
||||
|
||||
// Calculated based on center of box values
|
||||
public Position2d GetScreenCenter() {
|
||||
return new Position2d((this.endX - this.startX) / 2, (this.endY - this.startY) / 2);
|
||||
}
|
||||
|
||||
public abstract void renderButton(DrawContext context, int mouseX, int mouseY, float delta);
|
||||
protected abstract void appendClickableNarrations(NarrationMessageBuilder builder);
|
||||
}
|
381
src/client/java/jesse/keeblarcraft/gui/ScreenManager.java
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
*
|
||||
* ScreenManager
|
||||
*
|
||||
* This is the screen manager for the global screen handler of `TreeHandler` type
|
||||
* Please note: `TreeHandler` is suited for a more broad range of things; however
|
||||
* its initial implementation is for the skill tree. It will be renamed to a more
|
||||
* generic name so this class is more obviously re-usable after its implementation
|
||||
* is complete AND we verify this class can be made more generic for it. Since this
|
||||
* is unknown, it will remain the name it has currently.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.gui;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import jesse.keeblarcraft.GuiMgr.TreeHandler;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
// Client side renderer
|
||||
public class ScreenManager extends HandledScreen<TreeHandler> {
|
||||
private static ScreenManager static_inst;
|
||||
@SuppressWarnings("resource")
|
||||
private static PlayerInventory static_inventory = new PlayerInventory(null);// = MinecraftClient.getInstance().player.getInventory();
|
||||
|
||||
public static ScreenManager GetInstance() {
|
||||
if (static_inst == null) {
|
||||
static_inst = new ScreenManager(Keeblarcraft.TREE_HANDLER.create(0, static_inventory), static_inventory, Text.of("Test"));
|
||||
}
|
||||
return static_inst;
|
||||
}
|
||||
|
||||
private static HashMap<Integer, ArrayList<Class<? extends GenericLayerT>>> layerMap = new HashMap<Integer, ArrayList<Class<? extends GenericLayerT>>>();
|
||||
private static HashMap<Integer, ArrayList<GenericLayerT>> layers = new HashMap<Integer, ArrayList<GenericLayerT>>(); // key: layer id; value: list of classes to draw
|
||||
|
||||
// private TreeWidget treeWidget = null;
|
||||
private Screen parent;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn ScreenManager
|
||||
///
|
||||
/// @arg[in] handler is the TreeHandler (ScreenHandler) object
|
||||
///
|
||||
/// @arg[in] inventory is the players inventory. Required by HandledScreen
|
||||
/// object however is unused currently in this Screen
|
||||
///
|
||||
/// @arg[in] title is the title of the screen window
|
||||
///
|
||||
/// @brief Class constructor
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public ScreenManager(TreeHandler handler, PlayerInventory inventory, Text title) {
|
||||
super(handler, inventory, title);
|
||||
System.out.println("Called constructor of screen manager!");
|
||||
|
||||
// Initialize layers in map
|
||||
// for (int i = 0; i < NUMBER_DRAW_LAYERS; i++) {
|
||||
// layers.put(i, new ArrayList<Class<? extends GenericLayerT>>());
|
||||
// }
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn AddParent
|
||||
///
|
||||
/// @arg[in] parent is the parent screen object
|
||||
///
|
||||
/// @brief Add a parent screen to the screen object. This is useful if
|
||||
/// you want to return to the previous screen when this one gets
|
||||
/// closed by the user
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void AddParent(Screen parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public static void AddWidget(Class<? extends GenericLayerT> widget, int drawLayer) {
|
||||
if (layerMap.containsKey(drawLayer)) {
|
||||
// Just append the widget to the draw layer
|
||||
var layerList = layerMap.get(drawLayer);
|
||||
layerList.add(widget);
|
||||
} else {
|
||||
// Brand new layer!
|
||||
layerMap.put(drawLayer, new ArrayList<>(List.of(widget)));
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn init
|
||||
///
|
||||
/// @brief Initialize method; called one-time to setup class variables
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public void init() {
|
||||
// initialize screen size to the global background picture
|
||||
this.width = MinecraftClient.getInstance().getWindow().getScaledWidth();
|
||||
this.height = MinecraftClient.getInstance().getWindow().getScaledHeight();
|
||||
|
||||
// Let's go through and initialize all the screen types now in our active memory
|
||||
for (Entry<Integer, ArrayList<Class<? extends GenericLayerT>>> layerEntry : layerMap.entrySet()) {
|
||||
var layerList = layerEntry.getValue();
|
||||
|
||||
layers.put(layerEntry.getKey(), new ArrayList<>());
|
||||
var activeLayerList = layers.get(layerEntry.getKey());
|
||||
for (int i = 0; i < layerList.size(); i++) {
|
||||
try {
|
||||
System.out.println("Attempting to initialize widget with information: LAYER I-VAL W H: " + layerEntry.getKey() + " " + i + " " + this.width + " " + this.height);
|
||||
GenericLayerT initializedWidget = layerList.get(i).getDeclaredConstructor(int.class, int.class, int.class, int.class, Text.class).newInstance(0, 0, this.width, this.height, Text.of(""));
|
||||
activeLayerList.add(initializedWidget);
|
||||
} catch (InstantiationException e) {
|
||||
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of IntantiationException");
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of IllegalAccessException");
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of IllegalArgumentException");
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of InvocationTargetException");
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of NoSuchMethodException");
|
||||
e.printStackTrace();
|
||||
} catch (SecurityException e) {
|
||||
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of SecurityException");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Initialize child widgets with correct screen values so they can draw themselves in the right area on the screen (duh!)
|
||||
// treeWidget = new TreeWidget(GLOBAL_SCREEN_START_X + 24, GLOBAL_SCREEN_START_Y + 24, GLOBAL_SCREEN_WIDTH - 24, GLOBAL_SCREEN_HEIGHT - 24);
|
||||
// this.addDrawableChild(treeWidget);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn render
|
||||
///
|
||||
/// @arg[in] context is the drawing context of super class
|
||||
///
|
||||
/// @arg[in] mouseX is passed to parent class but unused here
|
||||
///
|
||||
/// @arg[in] mouseY is passed to parent class but unused here
|
||||
///
|
||||
/// @brief Render is called every frame while the screen is open
|
||||
///
|
||||
/// @note This is a pure abstract in parent and is required
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
super.render(context, mouseX, mouseY, delta); // This takes care of calling drawBackground which calls DrawMainScreen
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn drawForeground
|
||||
///
|
||||
/// @arg[in] context is the drawing context of super class
|
||||
///
|
||||
/// @arg[in] mouseX is unused
|
||||
///
|
||||
/// @arg[in] mouseY is unused
|
||||
///
|
||||
/// @brief Draw foreground exists to draw the titles; however we
|
||||
/// intentionally override it so the superclass object does not
|
||||
/// draw the overlay over the background screen
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public void drawForeground(DrawContext context, int mouseX, int mouseY) {
|
||||
// We override this function to intentionally do nothing
|
||||
// If in the future we want, we would draw the foreground and TITLES with this!
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn close
|
||||
///
|
||||
/// @brief Called when the screen closes
|
||||
///
|
||||
/// @note This is a pure abstract in parent and is required
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public void close() {
|
||||
this.client.setScreen(parent); // return to previous screen or null
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn mouseDragged
|
||||
///
|
||||
/// @arg[in] mouseX is x-axis position of original mouse click
|
||||
///
|
||||
/// @arg[in] mouseY is y-axis position of original mouse click
|
||||
///
|
||||
/// @arg[in] button is the int value of button pressed for mouse dragging
|
||||
///
|
||||
/// @arg[in] deltaX is the change in the X position from the previous
|
||||
/// mouse click
|
||||
///
|
||||
/// @arg[in] deltaY is the change in the Y position from the previous
|
||||
/// mouse click
|
||||
///
|
||||
/// @brief The drag event is called on all widgets on the screen so
|
||||
/// long as the initial position of the drag is within the
|
||||
/// bounds of the widget box itself. Widgets themselves will need
|
||||
/// to handle any sub-widgets since the bound check is only
|
||||
/// there to verify if the event happened ANYWHERE within a
|
||||
/// widget box
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||
super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
||||
// UpdateAnchorValues();
|
||||
|
||||
for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
|
||||
var layerList = layerEntry.getValue();
|
||||
|
||||
for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
|
||||
var layer = layerList.get(layerListIterator);
|
||||
|
||||
// Check to make sure scroll is within the context of the widget then deliver information
|
||||
if (InBounds(layer.startX, layer.startY, layer.endX, layer.endY, (int) mouseX, (int) mouseY)) {
|
||||
layer.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn mouseScrolled
|
||||
///
|
||||
/// @arg[in] mouseX is the initial X position of the cursor on a scroll
|
||||
///
|
||||
/// @arg[in] mouseY is the initial Y position of the cursor on a scroll
|
||||
///
|
||||
/// @arg[in] amount is a normalized value that indicates scroll direction
|
||||
///
|
||||
/// @brief The scroll event is called on all widgets on the screen so
|
||||
/// long as the initial position of the scroll is within the
|
||||
/// bounds of the widget box itself. Widgets themselves will need
|
||||
/// to handle any sub-widgets since the bound check is only
|
||||
/// there to verify if the event happened ANYWHERE within a
|
||||
/// widget box
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
|
||||
super.mouseScrolled(mouseX, mouseY, amount);
|
||||
|
||||
for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
|
||||
var layerList = layerEntry.getValue();
|
||||
|
||||
for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
|
||||
var layer = layerList.get(layerListIterator);
|
||||
|
||||
// Check to make sure scroll is within the context of the widget then deliver information
|
||||
if (InBounds(layer.startX, layer.startY, layer.endX, layer.endY, (int) mouseX, (int) mouseY)) {
|
||||
layer.mouseScrolled(mouseX, mouseY, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true; // The parent function defines this to be boolean; but I have no idea when I would want to return false from this
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn mouseClicked
|
||||
///
|
||||
/// @arg[in] mouseX is the initial X position of the mouse click event
|
||||
///
|
||||
/// @arg[in] mouseY is the initial Y position of the mouse click event
|
||||
///
|
||||
/// @arg[in] button is the mouse click button (left/right click value)
|
||||
///
|
||||
/// @brief The mouse click is called on all widgets on the screen so
|
||||
/// long as the initial position of the click is within the
|
||||
/// bounds of the widget box itself. Widgets themselves will need
|
||||
/// to handle any sub-widgets since the bound check is only
|
||||
/// there to verify if the event happened ANYWHERE within a
|
||||
/// widget box
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
super.mouseClicked(mouseX, mouseY, button);
|
||||
|
||||
for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
|
||||
var layerList = layerEntry.getValue();
|
||||
|
||||
for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
|
||||
var layer = layerList.get(layerListIterator);
|
||||
|
||||
// Check to make sure scroll is within the context of the widget then deliver information
|
||||
if (InBounds(layer.startX, layer.startY, layer.endX, layer.endY, (int) mouseX, (int) mouseY)) {
|
||||
layer.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn DrawLayers
|
||||
///
|
||||
/// @arg[in] context is the global drawing context for the screen
|
||||
///
|
||||
/// @arg[in] delta is passed in from background draw
|
||||
///
|
||||
/// @brief This is the primary drawing function so that all the texture
|
||||
/// draws can be done in one place in this class. We want as
|
||||
/// little distance as possible between redraws when possible!
|
||||
///
|
||||
/// @note Currently the foreground is not drawn in the custom screen
|
||||
/// manager. This is because the foreground features the general
|
||||
/// inventory manager that this screen handler is based on and we
|
||||
/// do not want to see those text pop ups.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void DrawLayers(DrawContext context, float delta) {
|
||||
for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
|
||||
var layerList = layerEntry.getValue();
|
||||
|
||||
for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
|
||||
var layer = layerList.get(layerListIterator);
|
||||
System.out.println("Drawing layer " + layerEntry.getKey() + " for class type " + layer.getClass().toString());
|
||||
layer.DrawLayer(context, layerEntry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn InBounds
|
||||
///
|
||||
/// @arg[in] initX is initial position of X axis
|
||||
///
|
||||
/// @arg[in] initY is initial position of Y axis
|
||||
///
|
||||
/// @arg[in] endX is the end position of X axis
|
||||
///
|
||||
/// @arg[in] endY is the end position of Y axis
|
||||
///
|
||||
/// @arg[in] x is the current X value we are comparing in the X axis
|
||||
///
|
||||
/// @arg[in] y is the current Y value we are comparing in the Y axis
|
||||
///
|
||||
/// @brief Checks if an x,y coordinate position falls within the bounds
|
||||
/// of a bounded box
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private boolean InBounds(int initX, int initY, int endX, int endY, int x, int y) {
|
||||
return (x >= initX && x <= endX) && (y >= initY && y <= endY);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn drawBackground
|
||||
///
|
||||
/// @arg[in] context is the drawing context of super class
|
||||
///
|
||||
/// @arg[in] delta is the change in background draw
|
||||
///
|
||||
/// @arg[in] mouseX is the mouse x-axis position
|
||||
///
|
||||
/// @arg[in] mouseY is the mouse y-axis position
|
||||
///
|
||||
/// @brief This function is an abstract parent class and must be
|
||||
/// implemented. This is "hijacked" and just being used as our
|
||||
/// main drawing method of all the background images. There isn't
|
||||
/// a huge difference of drawing our stuff in background vs the
|
||||
/// foreground - except possibly foreground is drawn first.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {
|
||||
DrawLayers(context, delta);
|
||||
}
|
||||
}
|
165
src/client/java/jesse/keeblarcraft/gui/widgets/TreeWidget.java
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
*
|
||||
* TreeWidget
|
||||
*
|
||||
* Handles the skill tree widget
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.gui.widgets;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import jesse.keeblarcraft.Utils.CommonStructures.Position2d;
|
||||
import jesse.keeblarcraft.gui.GenericLayerT;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class TreeWidget extends GenericLayerT {
|
||||
private static Identifier BACKGROUND_TEXTURE = new Identifier(Keeblarcraft.MOD_ID + ":" + "textures/gui/attribute_tree_background.png");
|
||||
private static int maxHeight = 320;
|
||||
private static int maxLength = 640;
|
||||
private int zoomScale = 1;
|
||||
// private static Identifier FLIGHT_ATTRIBUTE = new Identifier(Keeblarcraft.MOD_ID + ":" + "textures/gui/attribute_flight.png");
|
||||
|
||||
///TODO: Make this THE root node in the attribute tree! Rename in future
|
||||
// private static Identifier EXAMPLE_NODE = new Identifier(Keeblarcraft.MOD_ID + ":" + "textures/gui/attribute_tree_example_node.png"); ///TODO: Make a way to make this programmatic (Proabably extend AbstractNode to carry this var)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn TreeWidget
|
||||
///
|
||||
/// @brief Class constructor for constructing a tree widget. This will
|
||||
/// be deprecated in a future version but exists for testing
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public TreeWidget() {
|
||||
this(0, 0, 0, 0, Text.of("Test"));
|
||||
System.out.println("Calling empty tree constructor");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn TreeWidget
|
||||
///
|
||||
/// @brief Class constructor for constructing a tree widget
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public TreeWidget(int x, int y, int width, int height, Text message) {
|
||||
super(x, y, width, height, message);
|
||||
|
||||
this.startX = x;
|
||||
this.startY = y;
|
||||
this.endX = x + width;
|
||||
this.endY = y + height;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn renderButton
|
||||
///
|
||||
/// @param[in] context is the drawing pane
|
||||
///
|
||||
/// @param[in] x is the X position to draw at
|
||||
///
|
||||
/// @param[in] y is the Y position to draw at
|
||||
///
|
||||
/// @param[in] delta is unused in this version
|
||||
///
|
||||
/// @brief Primary call to draw the GUI for this widget
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public void renderButton(DrawContext context, int x, int y, float delta) {
|
||||
context.drawTexture(BACKGROUND_TEXTURE, x, y, 0, 0, maxLength, maxHeight, maxLength, maxHeight);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn appendClickableNarrations
|
||||
///
|
||||
/// @param[in] builder is the narration builder. This is pure virtual in
|
||||
/// the parent but is unused in this widget currently
|
||||
///
|
||||
/// @brief Handles the narrator
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
protected void appendClickableNarrations(NarrationMessageBuilder builder) {
|
||||
return;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn mouseClicked
|
||||
///
|
||||
/// @param[in] mouseX is where on the x-axis the mouse was clicked
|
||||
///
|
||||
/// @param[in] mouseY is where on the y-axis the mouse was clicked
|
||||
///
|
||||
/// @param[in] button is the button clicked with (think of a mouse...)
|
||||
///
|
||||
/// @brief Handler for mouse click events
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn mouseDragged
|
||||
///
|
||||
/// @param[in] mouseX is where on the x-axis the mouse was dragged
|
||||
///
|
||||
/// @param[in] mouseY is where on the y-axis the mouse was dragged
|
||||
///
|
||||
/// @param[in] button is the button dragged with (think of a mouse...)
|
||||
///
|
||||
/// @brief Handler for mouse drag events. delta's unused currently
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||
boolean ret = false;
|
||||
if (this.isValidClickButton(button)) {
|
||||
// Do camera panning magic stuff here
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn mouseDragged
|
||||
///
|
||||
/// @param[in] mouseX is where on the x-axis the mouse was dragged
|
||||
///
|
||||
/// @param[in] mouseY is where on the y-axis the mouse was dragged
|
||||
///
|
||||
/// @param[in] amount represents scroll direction. If the value is negative
|
||||
/// we scale out. If positive, we scale in
|
||||
///
|
||||
/// @brief Handler for mouse scroll events
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
|
||||
// Zooming INWARDS on scroll wheel produces 1.0 (which means zoom in)
|
||||
// Zooming BACKWARDS on scroll wheel produces -1.0 (which means zoom out)
|
||||
// We enforce a max scroll of 10 in either direction here
|
||||
if (amount > 0 && zoomScale <= 10) {
|
||||
// Zoom in
|
||||
zoomScale++;
|
||||
} else if (amount < 0 && zoomScale >= -10) {
|
||||
// Zoom out
|
||||
zoomScale--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn DrawLayer
|
||||
///
|
||||
/// @param[in] context is the drawing pane
|
||||
///
|
||||
/// @param[in] layer is the layer in which this widget is being drawn in
|
||||
///
|
||||
/// @brief This calls renderButton and gives it the valid drawing
|
||||
/// context to use. This function is called by a ScreenManager<T>
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public void DrawLayer(DrawContext context, int layer) {
|
||||
Position2d pos = GetScreenCenter();
|
||||
this.renderButton(context, pos.x - (maxLength / 2), pos.y - (maxHeight / 2), 0);
|
||||
}
|
||||
}
|
17
src/main/java/jesse/CommonServerUtils.java
Normal file
@ -0,0 +1,17 @@
|
||||
package jesse;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class CommonServerUtils {
|
||||
//the config is gonna hold the server instance change it if you want but dont reject my code cause its here
|
||||
private static MinecraftServer server;
|
||||
|
||||
public void SetServerInstance(MinecraftServer inputServer) {
|
||||
server = inputServer;
|
||||
}
|
||||
|
||||
public static MinecraftServer GetServerInstance() {
|
||||
return server;
|
||||
}
|
||||
|
||||
}
|
81
src/main/java/jesse/keeblarcraft/Armor/MetalJacketArmor.java
Normal file
@ -0,0 +1,81 @@
|
||||
package jesse.keeblarcraft.Armor;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import net.minecraft.item.ArmorItem;
|
||||
import net.minecraft.item.ArmorMaterial;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
|
||||
public class MetalJacketArmor implements ArmorMaterial {
|
||||
// All references to this class must refer to this
|
||||
public static final MetalJacketArmor INSTANCE = new MetalJacketArmor();
|
||||
|
||||
int defaultArmorModifier = 3;
|
||||
|
||||
/// FUNCTIONS BELOW
|
||||
|
||||
public MetalJacketArmor() {
|
||||
System.out.println("Constructor for armor called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDurability(ArmorItem.Type type) {
|
||||
System.out.println("durability for armor called");
|
||||
// Replace this multiplier by a constant value for the durability of the armor.
|
||||
// For reference, diamond uses 33 for all armor pieces, whilst leather uses 5.
|
||||
return switch (type) { // All from ArmorItem.Type
|
||||
case BOOTS -> Integer.MAX_VALUE;
|
||||
case LEGGINGS -> Integer.MAX_VALUE;
|
||||
case CHESTPLATE -> Integer.MAX_VALUE;
|
||||
case HELMET -> Integer.MAX_VALUE;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtection(ArmorItem.Type type) {
|
||||
System.out.println("Protection called");
|
||||
// Protection values for all the slots.
|
||||
// For reference, diamond uses 3 for boots, 6 for leggings, 8 for chestplate, and 3 for helmet,
|
||||
// whilst leather uses 1, 2, 3 and 1 respectively.
|
||||
return switch (type) {
|
||||
case BOOTS -> defaultArmorModifier;
|
||||
case HELMET -> defaultArmorModifier;
|
||||
case LEGGINGS -> defaultArmorModifier;
|
||||
case CHESTPLATE -> defaultArmorModifier;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnchantability() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundEvent getEquipSound() {
|
||||
// Example for Iron Armor
|
||||
return SoundEvents.ITEM_ARMOR_EQUIP_IRON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ingredient getRepairIngredient() {
|
||||
return Ingredient.ofItems(Items.BEDROCK); // prayfully impossible repair or just not worth it
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return Keeblarcraft.MOD_ID + ":" + "metaljacket";
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getToughness() {
|
||||
// Toughness is the actual "resistance" the armor provides to HIGH damage attacks
|
||||
return (float) defaultArmorModifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getKnockbackResistance() {
|
||||
return 0;
|
||||
}
|
||||
}
|
118
src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeMgr.java
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
*
|
||||
* AttributeMgr
|
||||
*
|
||||
* Central point for the attribute skill system in the mod
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.AttributeMgr;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
||||
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeFlight;
|
||||
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeMetalJacket;
|
||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||
|
||||
public class AttributeMgr {
|
||||
ConfigManager config;
|
||||
|
||||
// Global list of attributes
|
||||
// Key: node title
|
||||
// Val: The node class itself
|
||||
public static final HashMap<String, Class<? extends AbstractNode>> attributes = new HashMap<String, Class<? extends AbstractNode>>();
|
||||
|
||||
// This is a list of all logged in player tree's. These are kept in memory until either the mod is torn down or
|
||||
// players log out for optimization reasons
|
||||
public static final HashMap<String, AttributeTree> activeTrees = new HashMap<String, AttributeTree>();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterAttributeClass
|
||||
///
|
||||
/// @brief All generic class objects for attributes should be
|
||||
/// registered via this function
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void RegisterAttributeClass(Class<? extends AbstractNode> classObj) {
|
||||
AbstractNode verifyNode = null;
|
||||
try {
|
||||
// We spin up an instance of this node; but it will be dead after this function. We need this for name
|
||||
verifyNode = classObj.newInstance();
|
||||
} catch (Exception e) {
|
||||
Keeblarcraft.LOGGER.error("Attempted to assign AbstractNode class type when registering object but could not call .newInstance()! Constructs must be empty");
|
||||
e.printStackTrace();
|
||||
}
|
||||
ChatUtil.LoggerColored("Registring attribute called", ChatUtil.CONSOLE_COLOR.CYAN, Keeblarcraft.LOGGER);
|
||||
|
||||
try {
|
||||
if (attributes.containsKey(verifyNode.GetNodeTitle())) {
|
||||
Keeblarcraft.LOGGER.warn("Could not register attribute with duplicate name '" + verifyNode.GetNodeTitle() + "'");
|
||||
} else {
|
||||
ChatUtil.LoggerColored("REGISTERING ATTRIBUTE " + verifyNode.GetNodeTitle(), ChatUtil.CONSOLE_COLOR.YELLOW, Keeblarcraft.LOGGER);
|
||||
attributes.put(verifyNode.GetNodeTitle(), classObj);
|
||||
}
|
||||
} catch (Exception e) {} // Left empty since previous try-catch will throw error-message
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn ApplyAttribute
|
||||
///
|
||||
/// @arg[in] uuid is the players uuid
|
||||
///
|
||||
/// @arg[in] attributeName is the node title of the attribute class object
|
||||
///
|
||||
/// @brief Used to apply an attribute to a player's attribute tree
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@SuppressWarnings("deprecation")
|
||||
public static String ApplyAttribute(String uuid, String attributeName) {
|
||||
String msg = "";
|
||||
if (attributes.containsKey(attributeName)) {
|
||||
AttributeTree playerTree = activeTrees.get(uuid);
|
||||
AbstractNode node = null;
|
||||
try {
|
||||
node = attributes.get(attributeName).newInstance();
|
||||
} catch (Exception e) {
|
||||
Keeblarcraft.LOGGER.error("Could not successfully apply attribute. String of attribute name could not be successfully cast to actual java object");
|
||||
}
|
||||
|
||||
if (playerTree != null && node != null) {
|
||||
///////////
|
||||
// debug testing
|
||||
String isNull = (node == null ? "NULL" : "NOT NULL");
|
||||
System.out.println("Node is " + isNull);
|
||||
if (isNull.equals("NOT NULL")) { System.out.println("Node name: " + node.GetNodeTitle()); }
|
||||
// end debug testing
|
||||
///////////
|
||||
|
||||
playerTree.AddNewNode(node, 1, null, null);
|
||||
msg = "Applied attribute '" + attributeName + "' successfully";
|
||||
} else {
|
||||
msg = "Player tree not found!";
|
||||
}
|
||||
} else {
|
||||
msg = "Could not apply attribute, attribute name does not exist!";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterAttributes
|
||||
///
|
||||
/// @brief This registers all attribute classes to the global attribute
|
||||
/// class. Individual classes can be added here that call the
|
||||
/// more braod "RegisterAttributeClass"
|
||||
/// @see RegisterAttributeClass
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public static void RegisterAttributes() {
|
||||
// Manually register all attribute node classes here
|
||||
/// TODO: Find a better way to do this more dynamically in the future
|
||||
/// hint: make it an API for other modders to add to
|
||||
|
||||
RegisterAttributeClass(AttributeFlight.class);
|
||||
RegisterAttributeClass(AttributeMetalJacket.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
*
|
||||
* AbstractNode
|
||||
*
|
||||
* This is the general definition of everything that is allowed inside a node and is called by our system
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.AttributeMgr.AttributeNodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
abstract public class AbstractNode {
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GetNodeTitle
|
||||
///
|
||||
/// @brief The title of your node/skill!
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public abstract String GetNodeTitle();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GetNodeDescription
|
||||
///
|
||||
/// @brief This will become the hover-over text display of a skill in
|
||||
/// the skill tree
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public abstract String GetNodeDescription();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GetDetails
|
||||
///
|
||||
/// @brief This is the general details that may be displayed inside the
|
||||
/// GUI when the skill tree becomes available to a player. The
|
||||
/// object is suggested to be treated as such:
|
||||
///
|
||||
/// KEY (String) -> The title of an effect/attribute
|
||||
/// VAL (List<String>) -> Treated as a list of description
|
||||
/// attributes. 1 string per description
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public abstract HashMap<String, List<String>> GetDetails();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterCallbacks
|
||||
///
|
||||
/// @brief If your node has responsive callbacks; then this is the area
|
||||
/// you will register your callbacks for everything
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public abstract void RegisterCallbacks();
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
*
|
||||
* AttributeFlight
|
||||
*
|
||||
* The flight attribute
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.AttributeMgr.AttributeNodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.ActionResult;
|
||||
|
||||
public class AttributeFlight extends AbstractNode {
|
||||
|
||||
Boolean registeredHitCallback = false;
|
||||
|
||||
public AttributeFlight() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String GetNodeTitle() {
|
||||
return "attribute_low_health_flight";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String GetNodeDescription() {
|
||||
return "Gives player flight with low health";
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, List<String>> GetDetails() {
|
||||
HashMap<String, List<String>> ret = new HashMap<String, List<String>>();
|
||||
|
||||
// Filling out description item stuff here
|
||||
ret.put("Flight", List.of (
|
||||
"Gives a player natural flight if they have less than or equal to two hearts remaining"
|
||||
));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void RegisterCallbacks() {
|
||||
// Register events here
|
||||
if (registeredHitCallback == false) {
|
||||
AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
|
||||
// Manual spectator check is necessary because AttackBlockCallbacks fire before the spectator check
|
||||
if (!player.isSpectator() && player.getMainHandStack().isEmpty() && state.isToolRequired()) {
|
||||
player.damage(world.getDamageSources().generic(), 1.0F);
|
||||
}
|
||||
|
||||
return ActionResult.PASS;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
registeredHitCallback = true;
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package jesse.keeblarcraft.AttributeMgr.AttributeNodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import jesse.keeblarcraft.Armor.MetalJacketArmor;
|
||||
import jesse.keeblarcraft.CustomItems.ItemManager;
|
||||
import net.minecraft.item.ArmorItem;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
public final class AttributeMetalJacket extends AbstractNode {
|
||||
// This is the custom armor set that players will receive if no armor is on & attribute is equipped
|
||||
public final Item jacketHelm = new ArmorItem(MetalJacketArmor.INSTANCE, ArmorItem.Type.HELMET, new Item.Settings());
|
||||
public final Item jacketChest = new ArmorItem(MetalJacketArmor.INSTANCE, ArmorItem.Type.CHESTPLATE, new Item.Settings());
|
||||
public final Item jacketLegs = new ArmorItem(MetalJacketArmor.INSTANCE, ArmorItem.Type.LEGGINGS, new Item.Settings());
|
||||
public final Item jacketBoots = new ArmorItem(MetalJacketArmor.INSTANCE, ArmorItem.Type.BOOTS, new Item.Settings());
|
||||
|
||||
public AttributeMetalJacket() {
|
||||
// Finally register items with game
|
||||
Keeblarcraft.LOGGER.debug("Registering metaljackets");
|
||||
ItemManager.RegisterItem("metaljacket_helmet", jacketHelm);
|
||||
ItemManager.RegisterItem("metaljacket_chestplate", jacketChest);
|
||||
ItemManager.RegisterItem("metaljacket_leggings", jacketLegs);
|
||||
ItemManager.RegisterItem("metaljacket_boots", jacketBoots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String GetNodeTitle() {
|
||||
return "MetalJacket";
|
||||
}
|
||||
|
||||
// Short description of node on hover-event in GUI
|
||||
@Override
|
||||
public String GetNodeDescription() {
|
||||
return "MetalJacket affects armor value modifiers or gives player base armor when none is worn";
|
||||
}
|
||||
|
||||
// Detailed description of node on click-event in GUI
|
||||
@Override
|
||||
public HashMap<String, List<String>> GetDetails() {
|
||||
HashMap<String, List<String>> ret = new HashMap<String, List<String>>();
|
||||
|
||||
// Filling out description item stuff here
|
||||
ret.put("durability", List.of (
|
||||
"Gives player a base armor set with 3 protection and resistance",
|
||||
"If armor is being worn, this attribute multiplies each pieces armor value by 120% (rounding up to nearest integer)"
|
||||
));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void RegisterCallbacks() {
|
||||
}
|
||||
}
|
322
src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeTree.java
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
*
|
||||
* AttributeTree
|
||||
*
|
||||
* Handles a players individual attribute tree
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.AttributeMgr;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.HashMap;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||
import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION;
|
||||
|
||||
public class AttributeTree {
|
||||
|
||||
PlayerTree playerAttributeTree = new PlayerTree();
|
||||
ConfigManager config = new ConfigManager();
|
||||
private AbstractNode root = new RootNode();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @class TreeNode
|
||||
///
|
||||
/// @brief This is an individual node that goes within the larger
|
||||
/// PlayerTree class object
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private class TreeNode {
|
||||
public TreeNode(AbstractNode node, Integer maxLevel, List<String> parents, List<String> children) {
|
||||
thisNode = node;
|
||||
parentNodes = parents;
|
||||
childrenNodes = children;
|
||||
maxNodeLevel = maxLevel;
|
||||
currentNodeLevel = 1;
|
||||
}
|
||||
|
||||
AbstractNode thisNode;
|
||||
Integer currentNodeLevel;
|
||||
Integer maxNodeLevel;
|
||||
|
||||
// Store the names of the parent and children nodes; this lets a node have any number of parents and children
|
||||
// NOTE TO DEVELOPERS: Be aware! The more nodes the harrier the tree will look in the GUI!!! Always test your
|
||||
// code before just adding stuff willy-nilly!
|
||||
List<String> parentNodes;
|
||||
List<String> childrenNodes;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @class PlayerTree
|
||||
///
|
||||
/// @brief This is the tree object of a given player. It contains all
|
||||
/// valid attribute information for a player that is statically
|
||||
/// stored inside the AttributeMgr class
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private class PlayerTree {
|
||||
String uuid;
|
||||
// Key = name of AbstractNode
|
||||
// Val = The attribute itself
|
||||
HashMap<String, TreeNode> tree = new HashMap<String, TreeNode>();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @class RootNode
|
||||
///
|
||||
/// @brief This is the default root node of a tree. It is mostly left
|
||||
/// blank and used to code around as an "anchor" object
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private class RootNode extends AbstractNode {
|
||||
@Override
|
||||
public String GetNodeTitle() {
|
||||
return "root";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String GetNodeDescription() {
|
||||
return "This is the players tree root! All attributes extend from here";
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, List<String>> GetDetails() {
|
||||
HashMap<String, List<String>> ret = new HashMap<String, List<String>>();
|
||||
|
||||
ret.put("First Attribute", List.of("This is your skill tree", "All attributes grow from this root! Unlocking nodes requires all nodes connected to that previously to be unlocked first"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void RegisterCallbacks() {
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterActiveCallbacks
|
||||
///
|
||||
/// @brief This will register all the active callbacks on all nodes that
|
||||
/// are unlocked within a players tree instance
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void RegisterActiveCallbacks() {
|
||||
for(Entry<String, TreeNode> tree : playerAttributeTree.tree.entrySet()) {
|
||||
if (tree.getValue().currentNodeLevel != 0) {
|
||||
|
||||
// We need to construct the node object if it's null. If it's not null; we assume
|
||||
// the callback registration process has already happened
|
||||
if (tree.getValue().thisNode == null) {
|
||||
System.out.println("REGISTERACTIVECALLBACKS - NULL NODE");
|
||||
tree.getValue().thisNode.RegisterCallbacks();
|
||||
} else {
|
||||
System.out.println("REGISTERACTIVECALLBACKS - NOT NULL NODE");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn AddNewNode
|
||||
///
|
||||
/// @arg[in] newNode is the attribute node to be added to the player tree
|
||||
///
|
||||
/// @arg[in] maxNodeLevel is the max level of the node
|
||||
///
|
||||
/// @arg[in] parents is the list of parent attributes. If empty,
|
||||
/// root is default
|
||||
///
|
||||
/// @arg[in] children is the list of children attributes.
|
||||
/// Root cannot be child
|
||||
///
|
||||
/// @brief Add a new node to the tree arbitrarily. Root can never be a
|
||||
/// child node parents can never be empty or null (null or empty
|
||||
/// would imply you are adding root)
|
||||
///
|
||||
/// @note developer warning: you must personally verify your nodes are
|
||||
/// in the tree. anywhere is fine, and the tree is very dynamic
|
||||
/// (which is why self verification is required). When the tree
|
||||
/// is drawn in the GUI, it starts from the root node. As long as
|
||||
/// your node is attached to this node anywhere in the indirected
|
||||
/// graph; then your attribute will be drawn in the gui
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public Boolean AddNewNode(AbstractNode newNode, Integer maxNodeLevel, List<String> parents, List<String> children) {
|
||||
Boolean ret = false;
|
||||
TreeNode nodeReference = playerAttributeTree.tree.get(newNode.GetNodeTitle());
|
||||
|
||||
System.out.println("Is node reference null? -> " + (nodeReference == null ? "YES":"NO"));
|
||||
System.out.println("Is root reference null? -> " + (root == null ? "YES":"NO"));
|
||||
System.out.println("Is parents null? -> " + (parents == null ? "YES":"NO"));
|
||||
|
||||
// Some special handling is required on checking child list in case it is null
|
||||
Boolean validChildren = true;
|
||||
if (children != null) {
|
||||
validChildren = !children.contains(root.GetNodeTitle());
|
||||
}
|
||||
|
||||
if (nodeReference == null && validChildren) {
|
||||
// Since these values can be left as null, we want to guarentee they are at least initialized here
|
||||
maxNodeLevel = (maxNodeLevel == null ? 1 : maxNodeLevel);
|
||||
parents = (parents == null ? new ArrayList<String>() : parents);
|
||||
children = (children == null ? new ArrayList<String>() : children);
|
||||
|
||||
if (parents.size() == 0) {
|
||||
parents.add(root.GetNodeTitle()); // No disconnected nodes allowed! All parentless nodes are adopted by root by default
|
||||
}
|
||||
|
||||
// Node implementation here
|
||||
playerAttributeTree.tree.put(newNode.GetNodeTitle(), new TreeNode(newNode, maxNodeLevel, parents, children));
|
||||
|
||||
// if the new nodes level is not 0 we need to manually register the callbacks
|
||||
if (playerAttributeTree.tree.get(newNode.GetNodeTitle()).currentNodeLevel != 0) {
|
||||
System.out.println("Registering new callback for new node");
|
||||
playerAttributeTree.tree.get(newNode.GetNodeTitle()).thisNode.RegisterCallbacks();
|
||||
}
|
||||
} else {
|
||||
// Some fancy error handling for console log
|
||||
if (nodeReference != null) {
|
||||
Keeblarcraft.LOGGER.error("Attribute with name " + newNode.GetNodeTitle() + " was already found within the tree! Rename your node to add it");
|
||||
} else {
|
||||
Keeblarcraft.LOGGER.error("The attribute you attempted to add (name: " + newNode.GetNodeTitle() + "), has root in the children");
|
||||
}
|
||||
ret = false;
|
||||
}
|
||||
|
||||
FlashConfig();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn ChangeNodeLevel
|
||||
///
|
||||
/// @arg[in] nodeName is the attribute node title
|
||||
///
|
||||
/// @arg[in] newLevel is the new level you wish to grant the node
|
||||
///
|
||||
/// @brief If you wish to change the level of an attribute, you can use
|
||||
/// this function to do so
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void ChangeNodeLevel(String nodeName, Integer newLevel) {
|
||||
TreeNode nodeReference = playerAttributeTree.tree.get(nodeName);
|
||||
|
||||
if (nodeReference != null) {
|
||||
if (newLevel <= nodeReference.maxNodeLevel) {
|
||||
nodeReference.currentNodeLevel = newLevel;
|
||||
}
|
||||
}
|
||||
|
||||
FlashConfig();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn DeleteNode
|
||||
///
|
||||
/// @arg[in] nodeName is the attribute node title
|
||||
///
|
||||
/// @brief Delete a node via the name
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void DeleteNode(String nodeName) {
|
||||
// Do not delete root!
|
||||
if (nodeName != root.GetNodeTitle()) {
|
||||
playerAttributeTree.tree.remove(nodeName);
|
||||
}
|
||||
|
||||
FlashConfig();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GetNodeDetails
|
||||
///
|
||||
/// @arg[in] nodeName is the attribute node title
|
||||
///
|
||||
/// @brief Returns the detail map from the attribute if it has any
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public HashMap<String, List<String>> GetNodeDetails(String nodeName) {
|
||||
HashMap<String, List<String>> ret = null;
|
||||
|
||||
TreeNode nodeReference = playerAttributeTree.tree.get(nodeName);
|
||||
|
||||
if (nodeReference != null) {
|
||||
ret = nodeReference.thisNode.GetDetails();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GetPlayerTree
|
||||
///
|
||||
/// @brief Returns the player tree. Will be deprecated in use of the
|
||||
/// static active user map list instead for performance reasons
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Deprecated
|
||||
public PlayerTree GetPlayerTree() {
|
||||
return playerAttributeTree;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn AttributeTree
|
||||
///
|
||||
/// @arg[in] uuid is the player uuid
|
||||
///
|
||||
/// @brief Constructor for class
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public AttributeTree(String uuid) {
|
||||
// DEVELOPER NOTE:
|
||||
// If you are testing this part of the code, please be reminded that anonymous testing starts a new
|
||||
// player instance everytime you launch. This means the UUID CAN CHANGE when you launch the
|
||||
// game! This is not an issue with proper registered accounts in production
|
||||
Boolean existingFile = false;
|
||||
try {
|
||||
playerAttributeTree = config.GetJsonObjectFromFile("attributes/" + uuid + ".json", PlayerTree.class);
|
||||
existingFile = true;
|
||||
} catch (Exception e) {
|
||||
// Do nothing. This means the file does not exist
|
||||
}
|
||||
|
||||
// In the event the above code failed out, this means a new file has to be created for the player's uuid
|
||||
if (!existingFile)
|
||||
{
|
||||
System.out.println(ChatUtil.ColoredString("Trying to create new file", CONSOLE_COLOR.BLUE));
|
||||
try {
|
||||
playerAttributeTree.uuid = uuid;
|
||||
FlashConfig();
|
||||
} catch (Exception e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not write to file", CONSOLE_COLOR.RED));
|
||||
}
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("Moving on", CONSOLE_COLOR.BLUE));
|
||||
}
|
||||
|
||||
// It's possible the above code will return a blank class if a file doesn't exist. This will make
|
||||
// a new file with this players uuid
|
||||
if ("".equals(playerAttributeTree.uuid)) {
|
||||
System.out.println(ChatUtil.ColoredString("Assigning new config file for this uuid. No previous existing", CONSOLE_COLOR.BLUE));
|
||||
playerAttributeTree.uuid = uuid;
|
||||
}
|
||||
|
||||
// If the tree is empty or missing root, add it!
|
||||
if (playerAttributeTree.tree.size() == 0 || playerAttributeTree.tree.containsKey(root.GetNodeTitle()) == false) {
|
||||
playerAttributeTree.tree.put(root.GetNodeTitle(), new TreeNode(root, 1, null, null));
|
||||
}
|
||||
|
||||
RegisterActiveCallbacks();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn FlashConfig
|
||||
///
|
||||
/// @brief Flashes the config to the disk
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void FlashConfig() {
|
||||
try {
|
||||
config.WriteToJsonFile("attributes/" + playerAttributeTree.uuid + ".json", playerAttributeTree);
|
||||
} catch (FILE_WRITE_EXCEPTION e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
|
||||
}
|
||||
}
|
||||
}
|
256
src/main/java/jesse/keeblarcraft/BankMgr/BankManager.java
Normal file
@ -0,0 +1,256 @@
|
||||
package jesse.keeblarcraft.BankMgr;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import jesse.CommonServerUtils;
|
||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||
import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.PlayerManager;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
public class BankManager {
|
||||
BankManagerFile bankInfo = new BankManagerFile(); // not sure why we make another one but i guess so we
|
||||
ConfigManager config = new ConfigManager(); // for read and write privs
|
||||
CommonServerUtils commonServerUtils = new CommonServerUtils();
|
||||
|
||||
public BankManager(String uuid) {
|
||||
Boolean existingFile = false;
|
||||
try {
|
||||
bankInfo = config.GetJsonObjectFromFile("bank/" + uuid + ".json", BankManagerFile.class);
|
||||
existingFile = true;
|
||||
} catch (Exception e) {
|
||||
// Do nothing. This means the file does not exist
|
||||
}
|
||||
|
||||
// In the event the above code failed out, this means a new file has to be
|
||||
// created for the player's uuid
|
||||
if (!existingFile) {
|
||||
System.out.println(ChatUtil.ColoredString("Trying to create new file", CONSOLE_COLOR.BLUE));
|
||||
try {
|
||||
FlashConfig(bankInfo.uuid);
|
||||
} catch (Exception e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not write to file", CONSOLE_COLOR.RED));
|
||||
}
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("Moving on", CONSOLE_COLOR.BLUE));
|
||||
}
|
||||
|
||||
if ("".equals(bankInfo.uuid)) {
|
||||
System.out.println(ChatUtil.ColoredString("Assigning new config file for this uuid. No previous existing",
|
||||
CONSOLE_COLOR.BLUE));
|
||||
bankInfo.uuid = uuid;
|
||||
}
|
||||
}
|
||||
|
||||
//this class is the structure for the hashmap in BankManagerFile
|
||||
private class BankManagerMetaData {
|
||||
public BankManagerMetaData(long money, String reason, long payment, String otherParty, Integer time) {
|
||||
this.balance = money;
|
||||
this.reason = reason;
|
||||
this.payment = payment;
|
||||
this.otherParty = otherParty;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
long balance = 0;
|
||||
String reason; //not sure why my compiler is saying unused
|
||||
long payment;
|
||||
String otherParty;
|
||||
Integer time;
|
||||
}
|
||||
|
||||
// This is the general bank account of the read-in config for the player uuid ||| the class that gets converted into a json for the players file
|
||||
public class BankManagerFile {
|
||||
// Players uuid is the name of the file
|
||||
String uuid;
|
||||
|
||||
// Contents of file
|
||||
/*
|
||||
* Example:
|
||||
* player_uuid_here:
|
||||
* {
|
||||
* "1":
|
||||
* {
|
||||
* "balance": "10";
|
||||
* "reason": "tax evasion";
|
||||
* "payment": $-44
|
||||
* "other party": "jt";
|
||||
* "time": "30";
|
||||
* }
|
||||
* "2":
|
||||
* {
|
||||
* Etc.
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public HashMap<String, BankManagerMetaData> bank = new HashMap<String, BankManagerMetaData>();
|
||||
}
|
||||
|
||||
public long GetBalance() {
|
||||
long ret = 0;
|
||||
for (Entry<String, BankManagerMetaData> entry : bankInfo.bank.entrySet()) {
|
||||
ret = entry.getValue().balance;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
//https://maven.fabricmc.net/docs/fabric-api-0.34.8+1.17/net/fabricmc/fabric/api/networking/v1/PlayerLookup.html maybe this for getting the players im still not sure
|
||||
public void SetBalance(Integer newBalance, String reason, String otherParty) {
|
||||
Integer transactionNumber = bankInfo.bank.size();
|
||||
bankInfo.bank.put(transactionNumber.toString(),
|
||||
new BankManagerMetaData(newBalance, reason, newBalance, otherParty, 0));
|
||||
|
||||
FlashConfig(PlayerListNameChecker(otherParty));
|
||||
}
|
||||
|
||||
public void AddMoney(String reason, long payment, String otherParty) {
|
||||
if (bankInfo.bank.size() > 0) {
|
||||
for (Entry<String, BankManagerMetaData> entry : bankInfo.bank.entrySet()) {
|
||||
entry.getValue().balance += payment;
|
||||
entry.getValue().reason = "SERVER: " + reason;
|
||||
entry.getValue().payment = payment;
|
||||
entry.getValue().otherParty = otherParty;
|
||||
entry.getValue().time = 0;
|
||||
}
|
||||
} else {
|
||||
bankInfo.bank.put(bankInfo.uuid, new BankManagerMetaData(payment, reason, payment, otherParty, 0));
|
||||
}
|
||||
|
||||
FlashConfig(PlayerListNameChecker(otherParty));
|
||||
}
|
||||
|
||||
public void SubtractBalance(String reason, long payment, String otherParty) {
|
||||
if (bankInfo.bank.size() > 0) {
|
||||
for (Entry<String, BankManagerMetaData> entry : bankInfo.bank.entrySet()) {
|
||||
entry.getValue().balance -= payment;//not working?
|
||||
entry.getValue().reason = "SERVER: " + reason;
|
||||
entry.getValue().payment = payment;
|
||||
entry.getValue().otherParty = otherParty;
|
||||
entry.getValue().time = 0;
|
||||
}
|
||||
} else {
|
||||
bankInfo.bank.put(bankInfo.uuid, new BankManagerMetaData(0, reason, payment, otherParty, 0));
|
||||
}
|
||||
|
||||
FlashConfig(PlayerListNameChecker(otherParty));
|
||||
}
|
||||
|
||||
public void Wire(String reason, long payment, String otherParty) {
|
||||
if (bankInfo.bank.size() > 0) {
|
||||
for (Entry<String, BankManagerMetaData> entry : bankInfo.bank.entrySet()) {
|
||||
entry.getValue().balance -= payment;
|
||||
entry.getValue().reason = reason;
|
||||
entry.getValue().payment = payment;
|
||||
entry.getValue().otherParty = otherParty;
|
||||
entry.getValue().time = 0;
|
||||
|
||||
if (payment <= 0) {
|
||||
// add a error for the PLAYER not the server
|
||||
return;
|
||||
}
|
||||
}
|
||||
// make a server instance
|
||||
MinecraftServer server = CommonServerUtils.GetServerInstance();
|
||||
String[] playerList = server.getPlayerNames();
|
||||
//NOT SURE IF THIS FOR LOOP IS ONE OFF COULD POSSIBLEY BE SO IF NO ONE IS GETTING MONEY DOUBLE CHECK FOR LOOP
|
||||
for (int i = 0; i < playerList.length; i++) {
|
||||
System.out.println(ChatUtil.ColoredString("PLAYERS: " + playerList, CONSOLE_COLOR.YELLOW));
|
||||
if (playerList[i] == otherParty) {
|
||||
System.out.println(ChatUtil.ColoredString("Found Player: " + otherParty, CONSOLE_COLOR.GREEN));
|
||||
// we will use getuuidbyname then set the other VALID players bank BE SURE TO
|
||||
// MAKE THEM A BANK FIRST IF THEY DONT HAVE ONE fortnite forever
|
||||
if (config.GetFile("bank/" + GetUuidByName(server, otherParty) + ".json").size() < 1) {
|
||||
BankManagerFile newBankInfo = new BankManagerFile();
|
||||
BankManagerMetaData newBank = new BankManagerMetaData(0, "Account Created", 0, "Server", 0);
|
||||
newBankInfo.bank.put(GetUuidByName(server, otherParty).toString(), newBank);
|
||||
try {
|
||||
config.WriteToJsonFile("bank/" + newBankInfo.uuid + ".json", newBankInfo);
|
||||
} catch (FILE_WRITE_EXCEPTION e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//since the other player has a account now and we have access to it we can start fucking around
|
||||
BankManagerFile newBankInfo = new BankManagerFile();
|
||||
newBankInfo = config.GetJsonObjectFromFile("bank/" + GetUuidByName(server, otherParty) + ".json", BankManagerFile.class);
|
||||
// for now we will only use adding valance and not subtracting since that dosent make any sense
|
||||
for (Entry<String, BankManagerMetaData> entry : newBankInfo.bank.entrySet()) {
|
||||
entry.getValue().balance += payment;
|
||||
entry.getValue().reason = reason;
|
||||
entry.getValue().payment = payment;
|
||||
entry.getValue().otherParty = otherParty;
|
||||
entry.getValue().time = 0;
|
||||
}
|
||||
//cannot use regular flash config since the hard coded values need to add agurment for the uuid
|
||||
//needs to be inside the player check
|
||||
FlashConfig(newBankInfo.uuid);
|
||||
try {
|
||||
config.WriteToJsonFile("bank/" + newBankInfo.uuid + ".json", bankInfo);
|
||||
} catch (FILE_WRITE_EXCEPTION e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
|
||||
}
|
||||
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("Player Not Found: " + otherParty, CONSOLE_COLOR.RED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("You need to finance better", CONSOLE_COLOR.RED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String GetUuidByName(MinecraftServer server, String playerName) {
|
||||
PlayerManager playerManager = server.getPlayerManager();
|
||||
ServerPlayerEntity player = playerManager.getPlayer(playerName);
|
||||
if (player.getUuid() != null) {
|
||||
return player.getUuidAsString();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
String PlayerListNameChecker(String otherParty) {
|
||||
MinecraftServer server = CommonServerUtils.GetServerInstance();
|
||||
String[] playerList = server.getPlayerNames();
|
||||
|
||||
for (int i = 0; i < playerList.length; i++) {
|
||||
System.out.println(ChatUtil.ColoredString("PLAYERS: " + playerList, CONSOLE_COLOR.YELLOW));
|
||||
if (playerList[i] == otherParty) {
|
||||
System.out.println(ChatUtil.ColoredString("Found Player: " + otherParty, CONSOLE_COLOR.GREEN));
|
||||
// we will use getuuidbyname then set the other VALID players bank BE SURE TO
|
||||
// MAKE THEM A BANK FIRST IF THEY DONT HAVE ONE fortnite forever
|
||||
if (config.GetFile("bank/" + GetUuidByName(server, otherParty) + ".json").size() < 1) {
|
||||
BankManagerFile newBankInfo = new BankManagerFile();
|
||||
BankManagerMetaData newBank = new BankManagerMetaData(0, "Account Created", 0, "Server", 0);
|
||||
newBankInfo.bank.put(GetUuidByName(server, otherParty).toString(), newBank);
|
||||
try {
|
||||
config.WriteToJsonFile("bank/" + newBankInfo.uuid + ".json", newBankInfo);
|
||||
} catch (FILE_WRITE_EXCEPTION e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
else {
|
||||
System.out.println(ChatUtil.ColoredString("Bank Account Found", CONSOLE_COLOR.GREEN));
|
||||
}
|
||||
return GetUuidByName(server, otherParty);
|
||||
}
|
||||
}
|
||||
System.out.println(ChatUtil.ColoredString("For Loop condition bypassed Null Playerlist or Null Server instance", CONSOLE_COLOR.RED));
|
||||
return "";
|
||||
}
|
||||
|
||||
public void FlashConfig(String uuid) {
|
||||
try {
|
||||
config.WriteToJsonFile("bank/" + uuid + ".json", bankInfo);
|
||||
} catch (FILE_WRITE_EXCEPTION e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package jesse.keeblarcraft.CCTweakedExtension;
|
||||
|
||||
public class CCTweakedTest {
|
||||
|
||||
}
|
113
src/main/java/jesse/keeblarcraft/Commands/AttributeCommands.java
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
*
|
||||
* AttributeCommands
|
||||
*
|
||||
* This class handles all the possible in-game commands for the attribute system
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.Commands;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
|
||||
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.minecraft.command.argument.EntityArgumentType;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class AttributeCommands {
|
||||
public void RegisterCommands() {
|
||||
|
||||
// Command Root: "/attributes"
|
||||
// Subcommands: "apply <name> <attributename>", "remove <name> <attributename>"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
var attributeNode = CommandManager.literal("attributes").build();
|
||||
|
||||
var applyNode = CommandManager.literal("apply").build();
|
||||
var removeNode = CommandManager.literal("delete").build();
|
||||
var listNode = CommandManager.literal("list").executes(context -> ListAttributes(context)).build();
|
||||
|
||||
var playerArgAdd = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build();
|
||||
var playerArgRemove = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build();
|
||||
|
||||
var attributeNameAdd = CommandManager.argument("attributeName", StringArgumentType.greedyString())
|
||||
.executes(context -> ApplyAttribute
|
||||
(
|
||||
EntityArgumentType.getPlayer(context, "targetPlayer"),
|
||||
StringArgumentType.getString(context, "attributeName"),
|
||||
context)
|
||||
)
|
||||
.build();
|
||||
|
||||
var attributeNameDelete = CommandManager.argument("attributeName", StringArgumentType.greedyString())
|
||||
.executes(context -> DeleteAttribute
|
||||
(
|
||||
EntityArgumentType.getPlayer(context, "targetPlayer"),
|
||||
StringArgumentType.getString(context, "attributeName"),
|
||||
context)
|
||||
)
|
||||
.build();
|
||||
|
||||
// Build out the argument tree here
|
||||
dispatcher.getRoot().addChild(attributeNode);
|
||||
attributeNode.addChild(applyNode);
|
||||
attributeNode.addChild(listNode);
|
||||
attributeNode.addChild(removeNode);
|
||||
|
||||
// Subcommands "/apply playerArg", "/remove playerArg"
|
||||
applyNode.addChild(playerArgAdd);
|
||||
removeNode.addChild(playerArgRemove);
|
||||
|
||||
// name argument
|
||||
playerArgAdd.addChild(attributeNameAdd);
|
||||
playerArgRemove.addChild(attributeNameDelete);
|
||||
});
|
||||
}
|
||||
|
||||
public int ApplyAttribute(ServerPlayerEntity targetPlayer, String attributeName, CommandContext<ServerCommandSource> context) {
|
||||
int ret = -1;
|
||||
|
||||
System.out.println("Applying attribute");
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
System.out.println("Executed by player");
|
||||
String result = AttributeMgr.ApplyAttribute(targetPlayer.getUuidAsString(), attributeName);
|
||||
Keeblarcraft.LOGGER.info("[ApplyAttribute] -> " + result);
|
||||
context.getSource().getPlayer().sendMessage(Text.of(result));
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int DeleteAttribute(ServerPlayerEntity username, String attributeName, CommandContext<ServerCommandSource> context) {
|
||||
int ret = -1;
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int ListAttributes(CommandContext<ServerCommandSource> context) {
|
||||
int ret = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
for (Entry<String, Class<? extends AbstractNode>> entry : AttributeMgr.attributes.entrySet()) {
|
||||
Keeblarcraft.LOGGER.debug("ATTR-LIST: " + entry.getKey() + " LINKS " + entry.getValue());
|
||||
player.sendMessage(Text.of(entry.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
155
src/main/java/jesse/keeblarcraft/Commands/BankCommands.java
Normal file
@ -0,0 +1,155 @@
|
||||
package jesse.keeblarcraft.Commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.arguments.LongArgumentType;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
||||
import jesse.keeblarcraft.BankMgr.BankManager;
|
||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
|
||||
public class BankCommands {
|
||||
ConfigManager config = new ConfigManager();
|
||||
|
||||
public void RegisterCommands(){
|
||||
// Command: "/getbalance"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("getbalance")
|
||||
.executes(context -> GetBalance(context)));
|
||||
});
|
||||
|
||||
// Command: "/setbalance || rootSetBalance"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
final var rootSetBalance = dispatcher.register(CommandManager.literal("setbalance")
|
||||
.then(CommandManager.argument("newBalance", IntegerArgumentType.integer())
|
||||
.then(CommandManager.argument("reason", StringArgumentType.string())
|
||||
.then(CommandManager.argument("otherParty", StringArgumentType.string())
|
||||
.executes(context -> SetBalance(
|
||||
IntegerArgumentType.getInteger(context, "newBalance"),
|
||||
StringArgumentType.getString(context, "reason"),
|
||||
StringArgumentType.getString(context, "otherParty"),
|
||||
context))))));
|
||||
|
||||
dispatcher.register(CommandManager.literal("setbalance").redirect(rootSetBalance));
|
||||
});
|
||||
|
||||
// Command: "/AddMoney"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("AddMoney")
|
||||
.then(CommandManager.argument("reason", StringArgumentType.string())
|
||||
.then(CommandManager.argument("payment", LongArgumentType.longArg())
|
||||
.then(CommandManager.argument("otherParty", StringArgumentType.string())
|
||||
.executes(context -> AddMoney(
|
||||
StringArgumentType.getString(context, "reason"),
|
||||
LongArgumentType.getLong(context, "payment"),
|
||||
StringArgumentType.getString(context, "otherParty"),
|
||||
context))))));
|
||||
});
|
||||
|
||||
// Command: "/subtractbalance || /SubtractBalance"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
final var SubtractBalance = dispatcher.register(CommandManager.literal("subtractbalance")
|
||||
.then(CommandManager.argument("reason", StringArgumentType.string())
|
||||
.then(CommandManager.argument("payment", LongArgumentType.longArg())
|
||||
.then(CommandManager.argument("otherParty", StringArgumentType.string())
|
||||
.executes(context -> SubtractBalance(
|
||||
StringArgumentType.getString(context, "reason"),
|
||||
LongArgumentType.getLong(context, "payment"),
|
||||
StringArgumentType.getString(context, "otherParty"),
|
||||
context))))));
|
||||
|
||||
dispatcher.register(CommandManager.literal("subtractbalance").redirect(SubtractBalance));
|
||||
});
|
||||
|
||||
// Command: "/wire || /sendmoney"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
final var sendmoney = dispatcher.register(CommandManager.literal("wire")
|
||||
.then(CommandManager.argument("reason", StringArgumentType.string())
|
||||
.then(CommandManager.argument("payment", LongArgumentType.longArg())
|
||||
.then(CommandManager.argument("otherParty", StringArgumentType.string())
|
||||
.executes(context -> Wire(
|
||||
StringArgumentType.getString(context, "reason"),
|
||||
LongArgumentType.getLong(context, "payment"),
|
||||
StringArgumentType.getString(context, "otherParty"),
|
||||
context))))));
|
||||
|
||||
dispatcher.register(CommandManager.literal("wire").redirect(sendmoney));
|
||||
});
|
||||
}
|
||||
|
||||
public Integer GetBalance(CommandContext<ServerCommandSource> context) {
|
||||
Integer ret = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
BankManager playerBank = new BankManager(player.getUuidAsString());
|
||||
player.sendMessage(Text.literal(String.valueOf(playerBank.GetBalance())));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//SetBalance will be a ServerCommand only Perm level Op
|
||||
public Integer SetBalance(Integer newBalance, String reason, String otherParty, CommandContext<ServerCommandSource> context) {
|
||||
Integer ret = -1;
|
||||
|
||||
if (context.getSource().hasPermissionLevel(1)) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
BankManager playerBank = new BankManager(player.getUuidAsString());
|
||||
playerBank.SetBalance(newBalance, reason, otherParty);
|
||||
player.sendMessage(Text.literal(String.valueOf(playerBank.GetBalance())));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//AddMoney will be a ServerCommand Only Perm level Op
|
||||
public Integer AddMoney(String reason, long payment, String otherParty, CommandContext<ServerCommandSource> context) {
|
||||
Integer ret = -1;
|
||||
|
||||
if (context.getSource().hasPermissionLevel(1)) {
|
||||
ret = 0;
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
BankManager playerBank = new BankManager(player.getUuidAsString());
|
||||
playerBank.AddMoney(reason, payment, otherParty);
|
||||
player.sendMessage(Text.literal(String.valueOf(playerBank.GetBalance())));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//SubtractBalance will be a ServerCommand Perm leve Op
|
||||
public Integer SubtractBalance(String reason, long payment, String otherParty, CommandContext<ServerCommandSource> context) {
|
||||
Integer ret = -1;
|
||||
|
||||
if (context.getSource().hasPermissionLevel(1)) {
|
||||
ret = 0;
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
BankManager playerBank = new BankManager(player.getUuidAsString());
|
||||
playerBank.SubtractBalance(reason, payment, otherParty);
|
||||
player.sendMessage(Text.literal(String.valueOf(playerBank.GetBalance())));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Integer Wire(String reason, long payment, String otherParty, CommandContext<ServerCommandSource> context) {
|
||||
Integer ret = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ret = 0;
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
BankManager playerBank = new BankManager(player.getUuidAsString());
|
||||
playerBank.Wire(reason, payment, otherParty);
|
||||
player.sendMessage(Text.literal(String.valueOf(playerBank.GetBalance())));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
*
|
||||
* CommandManager
|
||||
*
|
||||
* This class maintains all custom commands and executions throughout the mod
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.Commands;
|
||||
|
||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||
|
||||
public class CustomCommandManager {
|
||||
// Intentionally empty constructor since at object definition time it may not be possible to register commands
|
||||
public CustomCommandManager() {}
|
||||
|
||||
// Registers all custom command classes here
|
||||
public void RegisterCustomCommands() {
|
||||
// CUSTOM COMMAND CLASS OBJECTS BELOW
|
||||
ShortcutCommands shortcuts = new ShortcutCommands();
|
||||
NoteCommands noteCommands = new NoteCommands();
|
||||
BankCommands bankCommands = new BankCommands();
|
||||
AttributeCommands attributeCommands = new AttributeCommands();
|
||||
|
||||
// REGISTER COMMANDS BELOW
|
||||
System.out.println(ChatUtil.ColoredString("REGISTERING CUSTOM COMMAND EXTENSIONS BELOW", CONSOLE_COLOR.BLUE));
|
||||
shortcuts.RegisterShortcutCommands();
|
||||
noteCommands.RegisterNoteCommands();
|
||||
bankCommands.RegisterCommands();
|
||||
attributeCommands.RegisterCommands();
|
||||
|
||||
}
|
||||
}
|
132
src/main/java/jesse/keeblarcraft/Commands/FactionCommands.java
Normal file
@ -0,0 +1,132 @@
|
||||
package jesse.keeblarcraft.Commands;
|
||||
|
||||
public class FactionCommands {
|
||||
|
||||
// Register function for commands
|
||||
public void RegisterFactionCommands() {
|
||||
|
||||
}
|
||||
|
||||
/// PRIVATE HANDLERS BELOW
|
||||
private int CreateFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int DeleteFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int AddPlayerToFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int KickPlayerFromFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int PromotePlayerInFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int DemotePlayerInFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int SetPlayerRoleInFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int DeclareFactionBase() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
// admin only
|
||||
private int SetFactionPower() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int DeclareFactionEvent() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int DeclareEnemyFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int DeclareAlliedFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int DeclareNeutralFaction() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int ListAllFactions() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int RegisterFactionChatChannel() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
// admin only
|
||||
private int DeleteFactionChatChannel() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int DepositToFactionBank() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int WithdrawFromFactionBank() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int FactionBankBalance() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int ListFactionBankTransactions() {
|
||||
int retValue = -1;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
}
|
301
src/main/java/jesse/keeblarcraft/Commands/NoteCommands.java
Normal file
@ -0,0 +1,301 @@
|
||||
package jesse.keeblarcraft.Commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||
import jesse.keeblarcraft.JsonClassObjects.PlayerNote;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||
import jesse.keeblarcraft.Utils.CustomExceptions.DIRECTORY_CREATE_EXCEPTION;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
public class NoteCommands {
|
||||
/// Class Variables
|
||||
ConfigManager notesConfig = new ConfigManager();
|
||||
String NOTES_GLOBAL_DIRECTORY = "notes"; // The overall "notes" dir inside cfg folder
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn NoteCommands
|
||||
///
|
||||
/// @brief This classes non-trivial constructor. Ensures creation
|
||||
// of notes directory exists before commands can be ran
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public NoteCommands() {
|
||||
// Check if directory exists
|
||||
if (notesConfig.DoesDirectoryExist(NOTES_GLOBAL_DIRECTORY) == false) {
|
||||
// Attempt to create the directory
|
||||
try {
|
||||
if (notesConfig.CreateDirectory(NOTES_GLOBAL_DIRECTORY) == true) {
|
||||
System.out.println(ChatUtil.ColoredString("Created notes directory successfully!", CONSOLE_COLOR.BLUE)); //TODO: Success!
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("ERROR: Notes directory FAILED to create!! Either the directory already exists or we are missing permissions!", CONSOLE_COLOR.RED)); //TODO: Critical failure --not specfic enough to mark it as a red or blue
|
||||
}
|
||||
} catch (DIRECTORY_CREATE_EXCEPTION e) {
|
||||
System.out.println(ChatUtil.ColoredString("Directory creation failed", CONSOLE_COLOR.RED));
|
||||
}
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("Notes directory already exists. Skipping creation...", CONSOLE_COLOR.BLUE)); //TODO: Success!
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterNoteCommands
|
||||
///
|
||||
/// @brief Registers all the commands for this class
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void RegisterNoteCommands() {
|
||||
// Command: "/addnote note goes here"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("addnote")
|
||||
.then(CommandManager.argument("value", StringArgumentType.greedyString())
|
||||
.executes(context -> AddNote(StringArgumentType.getString(context, "value"), context))));
|
||||
});
|
||||
|
||||
// Command: "/delnote noteIdHere"
|
||||
// CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
// dispatcher.register(CommandManager.literal("delnote")
|
||||
// .then(CommandManager.argument("value", StringArgumentType.greedyString())
|
||||
// .executes(context -> AddNote(StringArgumentType.getString(context, "value"), context))));
|
||||
// });
|
||||
|
||||
// Command: "/purgenotes"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("purgenotes")
|
||||
.executes(context -> PurgeAllNotes(context)));
|
||||
});
|
||||
|
||||
// Command: "/modifynote noteIdHere new_note_string_here"
|
||||
// Alises: "/editnote"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
final var mNote = dispatcher.register(CommandManager.literal("editnote")
|
||||
.then(CommandManager.argument("note_id", IntegerArgumentType.integer())
|
||||
.then(CommandManager.argument("new_note", StringArgumentType.string())
|
||||
.executes(context -> ModifyNote(
|
||||
IntegerArgumentType.getInteger(context, "note_id"),
|
||||
StringArgumentType.getString(context, "new_note"),
|
||||
context)))));
|
||||
|
||||
dispatcher.register(CommandManager.literal("editnote").redirect(mNote));
|
||||
});
|
||||
|
||||
// Command Root: "/delnote noteIdHere"
|
||||
// Aliases: "/rmnote", "/deletenote"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
final var rootDeleteCmd = dispatcher.register(CommandManager.literal("delnote")
|
||||
.then(CommandManager.argument("value", IntegerArgumentType.integer())
|
||||
.executes(context -> DeleteNote(IntegerArgumentType.getInteger(context, "value"), context))));
|
||||
|
||||
// Alias redirects
|
||||
dispatcher.register(CommandManager.literal("rmnote").redirect(rootDeleteCmd));
|
||||
dispatcher.register(CommandManager.literal("deletenote").redirect(rootDeleteCmd));
|
||||
});
|
||||
|
||||
// Command Root: "/notegui"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("notegui")
|
||||
.executes(context -> { OpenNoteGui(context);
|
||||
return 0;
|
||||
}));
|
||||
});
|
||||
|
||||
// Command Root: "/notelist"
|
||||
// Aliases: "/listnotes"
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
final var rootListNotes = dispatcher.register(CommandManager.literal("notelist")
|
||||
.executes(context -> { ListNotes(context);
|
||||
return 0;
|
||||
}));
|
||||
|
||||
dispatcher.register(CommandManager.literal("listnotes").redirect(rootListNotes));
|
||||
});
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn AddNote
|
||||
///
|
||||
/// @brief Adds a new note to the players notebook
|
||||
///
|
||||
/// @arg[in] value is the new note to be added
|
||||
///
|
||||
/// @arg[in] context is the context of the ServerCommandSource object
|
||||
/// the command was run with
|
||||
///
|
||||
/// @return 0 if success, -1 if not
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private Integer AddNote(String value, CommandContext<ServerCommandSource> context) {
|
||||
Integer ret = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
// Note mgmt
|
||||
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
||||
note.AddNote(value, 1, 1, 1, 1);
|
||||
ChatUtil.SendPlayerMsg(player, "New note logged to entry! View notes any time with /notegui");
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("Only a player can execute this command!", CONSOLE_COLOR.RED));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn DeleteNote
|
||||
///
|
||||
/// @brief Deletes a note by id
|
||||
///
|
||||
/// @arg[in] value is the integer ID of the note to be deleted
|
||||
///
|
||||
/// @arg[in] context is the context of the ServerCommandSource object
|
||||
/// the command was run with
|
||||
///
|
||||
/// @return 0 if success, -1 if not
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private int DeleteNote(int value, CommandContext<ServerCommandSource> context) {
|
||||
int ret = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
||||
ChatUtil.SendPlayerMsg(player, "Deleted note entry. View notes any time with /notegui");
|
||||
|
||||
ret = 0;
|
||||
note.DeleteNote(value);
|
||||
} else {
|
||||
System.out.println("Only a player can execute this command!");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn ModifyNote
|
||||
///
|
||||
/// @brief Modifies a single note by id value
|
||||
///
|
||||
/// @arg[in] value is the integer ID of the note to be modified
|
||||
///
|
||||
/// @arg[in] newNote is the new version of the edited note
|
||||
///
|
||||
/// @arg[in] context is the context of the ServerCommandSource object
|
||||
/// the command was run with
|
||||
///
|
||||
/// @return 0 if success, -1 if not
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private int ModifyNote(Integer value, String newNote, CommandContext<ServerCommandSource> context) {
|
||||
int ret = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer() && value > 0) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
||||
|
||||
long time = context.getSource().getWorld().getTime();
|
||||
// long day = ; ///TODO: Docs lack this for some reason? Add in future
|
||||
long epochTime = System.currentTimeMillis();
|
||||
long storyChapter = -1; // Intentional garbage until story is fleshed out later (TODO)
|
||||
long storyPart = -1; // Intentional garbage until story is fleshed out later (TODO)
|
||||
|
||||
note.ModifyNote(value, newNote, epochTime, storyChapter, storyPart);
|
||||
|
||||
ChatUtil.SendPlayerMsg(player, "Modified note entry. View notes any time with /notegui");
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn PurgeAllNotes
|
||||
///
|
||||
/// @brief Removes all notes from a players note file
|
||||
///
|
||||
/// @arg[in] context is the context of the ServerCommandSource object
|
||||
/// the command was run with
|
||||
///
|
||||
/// @return 0 if success, -1 if not
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private int PurgeAllNotes(CommandContext<ServerCommandSource> context) {
|
||||
int ret = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
||||
note.PurgeAllNotes();
|
||||
ChatUtil.SendPlayerMsg(player, "Purged all notes. View notes any time with /notegui");
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
System.out.println("Only a player can execute this command!");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn ListNotes
|
||||
///
|
||||
/// @brief Lists notes in pages in the players active chat
|
||||
///
|
||||
/// @arg[in] context is the context of the ServerCommandSource object
|
||||
/// the command was run with
|
||||
///
|
||||
/// @return 0 if success, -1 if not
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private int ListNotes(CommandContext<ServerCommandSource> context) {
|
||||
int ret = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
PlayerNote notes = new PlayerNote(player.getUuidAsString());
|
||||
ChatUtil.SendPlayerMsg(player, "Listing all notes...");
|
||||
for (int i = 0; i <= notes.GetNotebookSize(); i++) {
|
||||
String individualNote = notes.GetNoteString(i);
|
||||
if (individualNote != "") {
|
||||
ChatUtil.SendPlayerMsg(player, "Note " + i + ": " + individualNote);
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
System.out.println("Only a player can execute this command!");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
///TODO: Blocked until GUI manager is available
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn OpenNoteGui
|
||||
///
|
||||
/// @brief Opens up the graphical display of the note manager
|
||||
///
|
||||
/// @arg[in] context is the context of the ServerCommandSource object
|
||||
/// the command was run with
|
||||
///
|
||||
/// @return 0 if success, -1 if not
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private int OpenNoteGui(CommandContext<ServerCommandSource> context) {
|
||||
int ret = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
System.out.println("Only a player can execute this command!");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
259
src/main/java/jesse/keeblarcraft/Commands/ShortcutCommands.java
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
*
|
||||
* ShortcutCommands
|
||||
*
|
||||
* A class that simplifies some of the current vanilla commands with shortcut commands in the game. You may remember an old plugin
|
||||
* called "Essentials" (Or EssentialsEx in a later version) -> This file is re-creating a portion of that plugin but in mod-format
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.Commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.minecraft.entity.player.PlayerAbilities;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.command.TimeCommand;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class ShortcutCommands {
|
||||
|
||||
float DEFAULT_FLIGHT_SPEED = 0.05f; // Minecraft operates on a 0.0 -> 1.0 scale; with each .01 making a difference in speed. 0.05 is creative flight speed
|
||||
float SPEED_SCALAR = 20.0f; // For clamping speed down to half of its max output (So 0.5 will be max speed on a system that goes up in 0.05'ths)
|
||||
|
||||
public void RegisterShortcutCommands()
|
||||
{
|
||||
// Abstract handling "value" to parse gamemodes 0-2 (survival; creative; spectator)
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("gm")
|
||||
.then(CommandManager.argument("value", IntegerArgumentType.integer())
|
||||
.executes(context -> GamemodeShortcut(IntegerArgumentType.getInteger(context, "value"), context))));
|
||||
});
|
||||
|
||||
// Fly command
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("fly")
|
||||
.executes(context -> { FlightShortcut(context);
|
||||
return 0;
|
||||
}));
|
||||
});
|
||||
|
||||
// Fly command with speed
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("fly")
|
||||
.then(CommandManager.argument("value", IntegerArgumentType.integer())
|
||||
.executes(context -> FlightSpeedShortcut(IntegerArgumentType.getInteger(context, "value"), context))));
|
||||
});
|
||||
|
||||
///TODO: Read TODO on function
|
||||
// CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
// dispatcher.register(CommandManager.literal("walk")
|
||||
// .then(CommandManager.argument("value", IntegerArgumentType.integer())
|
||||
// .executes(context -> WalkSpeedShortcut(IntegerArgumentType.getInteger(context, "value"), context))));
|
||||
// });
|
||||
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("heal")
|
||||
.executes(context -> { HealShortcut(context);
|
||||
return 0;
|
||||
}));
|
||||
});
|
||||
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("day")
|
||||
.executes(context -> { DayShortcut(context);
|
||||
return 0;
|
||||
}));
|
||||
});
|
||||
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||
dispatcher.register(CommandManager.literal("night")
|
||||
.executes(context -> { NightShortcut(context);
|
||||
return 0;
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/// Command handlers below
|
||||
private int GamemodeShortcut(int value, CommandContext<ServerCommandSource> context)
|
||||
{
|
||||
int retValue = -1;
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
/// todo: change 4 to be OPERATOR level. 4 is DEFAULT operator level in Minecraft
|
||||
if(player.hasPermissionLevel(4)) {
|
||||
switch(value) {
|
||||
case 0:
|
||||
player.changeGameMode(net.minecraft.world.GameMode.SURVIVAL);
|
||||
player.sendMessage(Text.literal("Changing your game mode to SURVIVAL"));
|
||||
retValue = 0;
|
||||
break;
|
||||
case 1:
|
||||
player.changeGameMode(net.minecraft.world.GameMode.CREATIVE);
|
||||
player.sendMessage(Text.literal("Changing your game mode to CREATIVE"));
|
||||
retValue = 0;
|
||||
break;
|
||||
case 2:
|
||||
player.changeGameMode(net.minecraft.world.GameMode.SPECTATOR);
|
||||
player.sendMessage(Text.literal("Changing your game mode to SPECTATOR"));
|
||||
retValue = 0;
|
||||
break;
|
||||
default:
|
||||
player.sendMessage(Text.literal("Valid entries are 0=SURVIVAL, 1=CREATIVE, 2=SPECTATOR"));
|
||||
retValue = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
player.sendMessage(Text.literal("\033[31m You do not have permissions to run this command! \033[0m"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
System.out.println(ChatUtil.ColoredString("This command cannot be executed by a non-player entity!", CONSOLE_COLOR.RED));
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int FlightShortcut(CommandContext<ServerCommandSource> context) {
|
||||
int retValue = -1;
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
if (player.hasPermissionLevel(4)) {
|
||||
PlayerAbilities abilities = player.getAbilities();
|
||||
abilities.flying = !abilities.flying; // Toggle flying
|
||||
abilities.setFlySpeed(DEFAULT_FLIGHT_SPEED); // It seems flight speed is on a 0-1 scale
|
||||
player.sendAbilitiesUpdate();
|
||||
ChatUtil.SendPlayerMsg(player, "You can now fly! Flight speed is " + abilities.getFlySpeed());
|
||||
} else {
|
||||
player.sendMessage(Text.literal("You do not have permission for this command"));
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int FlightSpeedShortcut(int value, CommandContext<ServerCommandSource> context) {
|
||||
int retValue = -1;
|
||||
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
if (player.hasPermissionLevel(4)) {
|
||||
PlayerAbilities abilities = player.getAbilities();
|
||||
|
||||
if (value >= 1 && value <= 10) {
|
||||
abilities.allowFlying = true;
|
||||
abilities.setFlySpeed((float) (value / SPEED_SCALAR)); // Dividing by 20f yields max clamp value of 0.5 since MC does 0.0-> 1.0 flight. 0.1 flight is too fast!
|
||||
player.sendAbilitiesUpdate();
|
||||
ChatUtil.SendPlayerMsg(player, "Flight speed set to " + (value));
|
||||
} else {
|
||||
player.sendMessage(Text.literal("Only values from 1-10 are accepted"));
|
||||
}
|
||||
} else {
|
||||
player.sendMessage(Text.literal("You do not have permission for this command"));
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
///TODO: There is a bug with walk speed that causes the players speed to behave weirdly despite the value. It's either a crawl or mach 10
|
||||
///TODO: It's possible that the player may need to die first to reset speed; and reloading in the debugger does not count as resetting values. This
|
||||
///TODO: code may actually work; but I just did not die first in between testing speed changes.
|
||||
// private int WalkSpeedShortcut(int value, CommandContext<ServerCommandSource> context) {
|
||||
// int retValue = -1;
|
||||
// if (context.getSource().isExecutedByPlayer()) {
|
||||
// ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
// if (player.hasPermissionLevel(4)) {
|
||||
// PlayerAbilities abilities = player.getAbilities();
|
||||
|
||||
// if (value >= 1 && value <= 10) {
|
||||
// abilities.setWalkSpeed((float) 1.0f);
|
||||
// player.sendAbilitiesUpdate();
|
||||
// ChatUtil.SendPlayerMsg(player, "Set walk speed to " + (value));
|
||||
// } else {
|
||||
// player.sendMessage(Text.literal("Only values from 1-10 are accepted"));
|
||||
// }
|
||||
// } else {
|
||||
// player.sendMessage(Text.literal("You do not have permission for this command"));
|
||||
// }
|
||||
// }
|
||||
|
||||
// return retValue;
|
||||
// }
|
||||
|
||||
// TODO: Add when we can find where in the API to fill players hunger level
|
||||
// private int FeedShortcut(CommandContext<ServerCommandSource> context) {
|
||||
// int retValue = -1;
|
||||
// if (context.getSource().isExecutedByPlayer()) {
|
||||
// ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
// if (player.hasPermissionLevel(4)) {
|
||||
|
||||
// } else {
|
||||
// player.sendMessage(Text.literal("You do not have permission for this command"));
|
||||
// }
|
||||
// }
|
||||
|
||||
// return retValue;
|
||||
// }
|
||||
|
||||
private int HealShortcut(CommandContext<ServerCommandSource> context) {
|
||||
int retValue = -1;
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
if (player.hasPermissionLevel(4)) {
|
||||
player.setHealth(player.getMaxHealth());
|
||||
ChatUtil.SendPlayerMsg(player, "Healed!");
|
||||
} else {
|
||||
player.sendMessage(Text.literal("You do not have permission for this command"));
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
private int DayShortcut(CommandContext<ServerCommandSource> context) {
|
||||
int retValue = -1;
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
if (player.hasPermissionLevel(4)) {
|
||||
retValue=0;
|
||||
TimeCommand.executeSet(context.getSource(), retValue);
|
||||
} else {
|
||||
player.sendMessage(Text.literal("You do not have permission for this command"));
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
private int NightShortcut(CommandContext<ServerCommandSource> context) {
|
||||
int retValue = -1;
|
||||
if (context.getSource().isExecutedByPlayer()) {
|
||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||
|
||||
if (player.hasPermissionLevel(4)) {
|
||||
retValue=13000;
|
||||
TimeCommand.executeSet(context.getSource(), retValue);
|
||||
} else {
|
||||
player.sendMessage(Text.literal("You do not have permission for this command"));
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
}
|
239
src/main/java/jesse/keeblarcraft/ConfigMgr/ConfigManager.java
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
*
|
||||
* ConfigManager
|
||||
*
|
||||
* This class is the central configuration file manager for all other classes and acts as a utility class for other classes to use.
|
||||
* It is typical to define this class as a general object (not static instance) for each class in single-threaded actions. If you need
|
||||
* a special function or action from this class; it is recommended to add it to this class and not make your own.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.ConfigMgr;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonIOException;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||
import jesse.keeblarcraft.Utils.CustomExceptions.*;
|
||||
|
||||
public class ConfigManager {
|
||||
|
||||
// Pedantic empty constructor
|
||||
public ConfigManager() {}
|
||||
|
||||
// CreateFile
|
||||
//
|
||||
// Returns true if file is created, will return false if file cannot be created (returns true if already exists)
|
||||
public Boolean CreateFile(String fileName) throws FILE_CREATE_EXCEPTION {
|
||||
Boolean ret = false;
|
||||
File file = new File(fileName);
|
||||
|
||||
// Check 1: Does the file already exist?
|
||||
ret = file.exists();
|
||||
System.out.println(ChatUtil.ColoredString("Does file exist? ", CONSOLE_COLOR.BLUE) + (ret ? ChatUtil.ColoredString("YES", CONSOLE_COLOR.YELLOW) : ChatUtil.ColoredString("NO", CONSOLE_COLOR.YELLOW)));
|
||||
|
||||
// Check 2: If the file does not exist, attempt to create it
|
||||
if (ret == false) {
|
||||
try {
|
||||
ret = file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
// The file could not be created
|
||||
throw new FILE_CREATE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
ret = true; // This might be a hot fix, but technically the file already exists so would this be true or false? --?this statement is wild?
|
||||
System.out.println(ChatUtil.ColoredString("File (name: ", CONSOLE_COLOR.BLUE) + ChatUtil.ColoredString(fileName, CONSOLE_COLOR.YELLOW) + ChatUtil.ColoredString(" was determined to already exist. Exiting out", CONSOLE_COLOR.BLUE));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// DeleteFile
|
||||
//
|
||||
// Returns true if file is deleted, false if could not be deleted or does not exist
|
||||
public Boolean DeleteFile(String fileName) throws FILE_DELETE_EXCEPTION {
|
||||
Boolean ret = false;
|
||||
File file = new File(fileName);
|
||||
|
||||
// Step 1: Does file exist?
|
||||
ret = file.exists();
|
||||
|
||||
// Step 2: If file exists, attempt to delete
|
||||
if (ret == true) {
|
||||
try {
|
||||
ret = file.delete();
|
||||
} catch (SecurityException e) {
|
||||
throw new FILE_DELETE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("cannot delete file ", CONSOLE_COLOR.RED) + ChatUtil.ColoredString(fileName, CONSOLE_COLOR.YELLOW) + ChatUtil.ColoredString(" because file does not exist", CONSOLE_COLOR.BLUE));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// WriteToFile
|
||||
//
|
||||
// Will write or append to file (valid modes: "w" or "a") if file is available. Returns false if not
|
||||
public Boolean WriteToFile(String fileName, String data, String mode) {
|
||||
Boolean ret = false;
|
||||
|
||||
FileWriter file;
|
||||
try {
|
||||
file = new FileWriter(fileName);
|
||||
switch(mode) {
|
||||
case "w":
|
||||
file.write(data);
|
||||
ret = true;
|
||||
break;
|
||||
case "a":
|
||||
file.append(data);
|
||||
ret = true;
|
||||
break;
|
||||
default:
|
||||
System.out.println(ChatUtil.ColoredString("Invalid mode to WriteToFile!", CONSOLE_COLOR.RED));
|
||||
break;
|
||||
}
|
||||
|
||||
file.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not open file ", CONSOLE_COLOR.RED) + ChatUtil.ColoredString(fileName, CONSOLE_COLOR.YELLOW) + ChatUtil.ColoredString(" to write to it! Possibly permission issue?", CONSOLE_COLOR.RED));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// WriteToJsonFile
|
||||
//
|
||||
// Will write to or append to a json file. It will search if the key exists first & update the field;
|
||||
// or add a new entry. It should be noted that json objects *can* be buried inside each other. It is
|
||||
// considered best (and only) practice to call the "GetJsonStringFromFile" function first from this
|
||||
// class and simply iterate to what you would need and then update the entire entry alongside the
|
||||
// top-level key.
|
||||
//
|
||||
// NOTE: THIS DOES NOT SAFE UPDATE THE KEY OBJECT. PRE-EXISTING DATA WILL BE DELETED FOREVER
|
||||
public void WriteToJsonFile(String fileName, Object data) throws FILE_WRITE_EXCEPTION {
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
try {
|
||||
FileWriter writer = new FileWriter(fileName);
|
||||
gson.toJson(data, writer);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} catch (JsonIOException | IOException e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not successfully write to json file", CONSOLE_COLOR.RED));
|
||||
throw new FILE_WRITE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
|
||||
// GetJsonStringFromFile
|
||||
//
|
||||
// Retrieves json file and converts to desired object. Returns JsonSyntaxException if file could not be fitted to class input
|
||||
public <T> T GetJsonObjectFromFile(String fileName, Class<T> classToConvertTo) throws JsonSyntaxException {
|
||||
Gson gson = new Gson();
|
||||
String ret = "";
|
||||
|
||||
// hot fix: Not sure how to return "false" for invalid conversion when I'm forced to convert or just catch... Look into a better
|
||||
// return value in the future - but for now throw JsonSyntaxException no matter what exception is caught
|
||||
try {
|
||||
File file = new File(fileName);
|
||||
ret = FileUtils.readFileToString(file, "UTF-8");
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println(ChatUtil.ColoredString("nullptr exception", CONSOLE_COLOR.RED));
|
||||
throw new JsonSyntaxException("");
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println(ChatUtil.ColoredString("file not found", CONSOLE_COLOR.RED));
|
||||
throw new JsonSyntaxException("");
|
||||
} catch (java.nio.charset.UnsupportedCharsetException e) {
|
||||
System.out.println(ChatUtil.ColoredString("charset issue", CONSOLE_COLOR.RED));
|
||||
throw new JsonSyntaxException("");
|
||||
} catch (IOException e) {
|
||||
System.out.println(ChatUtil.ColoredString("io exception", CONSOLE_COLOR.RED));
|
||||
throw new JsonSyntaxException("");
|
||||
}
|
||||
|
||||
return gson.fromJson(ret, classToConvertTo);
|
||||
}
|
||||
|
||||
public Boolean DoesFileExist(String fileName) {
|
||||
return new File(fileName).exists(); // untested
|
||||
}
|
||||
|
||||
public Boolean DoesDirectoryExist(String dirName) {
|
||||
return new File(dirName).isDirectory(); // untested
|
||||
}
|
||||
|
||||
public Boolean CreateDirectory(String dirName) throws DIRECTORY_CREATE_EXCEPTION {
|
||||
Boolean ret = false;
|
||||
|
||||
File dir = new File(dirName);
|
||||
|
||||
try {
|
||||
if ( ! dir.exists()) {
|
||||
ret = dir.mkdirs();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(ChatUtil.ColoredString("Failed to make directory with name: ", CONSOLE_COLOR.RED) + ChatUtil.ColoredString(dirName, CONSOLE_COLOR.YELLOW));
|
||||
ret = true; /// TODO: Hack to make Setup fn be fine with prev-created files! Make Setup more robust!
|
||||
throw new DIRECTORY_CREATE_EXCEPTION();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Boolean DeleteDirectory(String dirName) throws DIRECTORY_DELETE_EXCEPTION {
|
||||
Boolean ret = false;
|
||||
|
||||
File dir = new File(dirName);
|
||||
|
||||
try {
|
||||
ret = dir.delete();
|
||||
System.out.println(ChatUtil.ColoredString("Deleted directory ", CONSOLE_COLOR.GREEN) + ChatUtil.ColoredString(dirName, CONSOLE_COLOR.YELLOW));
|
||||
} catch (Exception e) {
|
||||
System.out.println(ChatUtil.ColoredString("Failed to delete directory: ", CONSOLE_COLOR.RED) + ChatUtil.ColoredString(dirName, CONSOLE_COLOR.YELLOW));
|
||||
throw new DIRECTORY_DELETE_EXCEPTION();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// AddToKey
|
||||
//
|
||||
// Adds new text to a key if found inside the config
|
||||
public String AddToKey(String key, String newInfo) {
|
||||
String ret = "";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// GetFile
|
||||
//
|
||||
// Returns a file as an arraylist of all the lines in the file. Generally only used for testing
|
||||
//
|
||||
// NOTE: Returns UTF-8 Encoding of file
|
||||
public List<String> GetFile(String fileName) {
|
||||
List<String> ret = new ArrayList<String>();
|
||||
|
||||
try {
|
||||
return Files.readLines(new File(fileName), Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
ret.clear();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
24
src/main/java/jesse/keeblarcraft/CustomBlocks/BlockList.java
Normal file
@ -0,0 +1,24 @@
|
||||
package jesse.keeblarcraft.CustomBlocks;
|
||||
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.ExperienceDroppingBlock;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.util.math.intprovider.UniformIntProvider;
|
||||
|
||||
// Put all your blocks here
|
||||
public class BlockList {
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterBlocks
|
||||
///
|
||||
/// @brief This function is called by the main thread to register all
|
||||
/// block objects. Please register your blocks here
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public static void RegisterBlocks() {
|
||||
BlockManager.RegisterBlock("example_block_ore", new Block(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).sounds(BlockSoundGroup.AMETHYST_BLOCK).requiresTool().breakInstantly()));
|
||||
BlockManager.RegisterBlock("example_block", new ExperienceDroppingBlock(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).sounds(BlockSoundGroup.ANCIENT_DEBRIS).requiresTool(), UniformIntProvider.create(4, 20)));
|
||||
BlockManager.RegisterBlock("example_statue", new Block(FabricBlockSettings.copyOf(Blocks.BELL)));
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
*
|
||||
* BlockManager
|
||||
*
|
||||
* The mod block manager
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.CustomBlocks;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class BlockManager {
|
||||
|
||||
/// The block list. DO NOT ADD TO THE LIST YOURSELF. USE
|
||||
/// THE RegisterBlock(...) FUNCTION OTHERWISE YOUR BLOCK WILL
|
||||
/// NOT BE REGISTERED PROPERLY AND MAY BREAK THE GAME
|
||||
// public static final List<Block> blockList = new ArrayList<Block>();
|
||||
public static final HashMap<String, Block> blockList = new HashMap<String, Block>();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterBlock
|
||||
///
|
||||
/// @arg[in] name is the block name. IMPORTANT: Name must adhere to rules:
|
||||
/// 1. The name provided here must match these names:
|
||||
/// * This blocks models/block name
|
||||
/// * This blocks textures/block name
|
||||
/// 2 Name must be lowercase & no special characters besides '_'
|
||||
///
|
||||
/// @arg[in] block is the block to be added to the block list
|
||||
///
|
||||
/// @brief This is the call to register your block to the game! Please
|
||||
/// do not forget to update the models/block json file, the
|
||||
/// textures/block png name, and finally the lang/en_us.json file
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public static void RegisterBlock(String name, Block block) {
|
||||
|
||||
// This call registers the block as an item in inventories
|
||||
Registry.register(Registries.ITEM, new Identifier(Keeblarcraft.MOD_ID, name), new BlockItem(block, new FabricItemSettings()));
|
||||
|
||||
// This call registers the block as placed
|
||||
Block newBlock = Registry.register(Registries.BLOCK, new Identifier(Keeblarcraft.MOD_ID, name), block);
|
||||
|
||||
// Add the block to the block list
|
||||
blockList.put(name, newBlock);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GetBlock
|
||||
///
|
||||
/// @brief Gets a block from the block list by name
|
||||
///
|
||||
/// @return Returns a block from the blockList object if name is found,
|
||||
/// will return null if not found
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public static Block GetBlock(String name) {
|
||||
return blockList.get(name);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package jesse.keeblarcraft.CustomItems;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import jesse.keeblarcraft.CustomBlocks.BlockManager;
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class CustomItemGroups {
|
||||
|
||||
// This is the custom mod group for the mod
|
||||
public static final ItemGroup MOD_GROUP = Registry.register(Registries.ITEM_GROUP,
|
||||
new Identifier(Keeblarcraft.MOD_ID, "keeblarcraft"),
|
||||
FabricItemGroup.builder().displayName(Text.translatable("itemgroup.keeblarcraft"))
|
||||
.icon(() -> new ItemStack(Items.ANVIL)).entries((displayContext, entries) -> {
|
||||
// We iterate through all the modded items and add them to the custom item group here
|
||||
for (int i = 0; i < ItemManager.itemList.size(); i++) {
|
||||
entries.add(ItemManager.itemList.get(i));
|
||||
}
|
||||
|
||||
// We iterate through all the modded blocks and add them to the custom block group here
|
||||
for(Entry<String, Block> blocks : BlockManager.blockList.entrySet()) {
|
||||
entries.add(blocks.getValue());
|
||||
}
|
||||
}).build());
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterGroups
|
||||
///
|
||||
/// @brief Glorified print statement that the class has initialized
|
||||
/// basically - meaning that all item groups have registered
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public static void RegisterGroups() {
|
||||
Keeblarcraft.LOGGER.info("Registering item groups for " + Keeblarcraft.MOD_ID);
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
*
|
||||
* ItemManager
|
||||
*
|
||||
* This is the general purpose item manager for the mod. All items will be registered through
|
||||
* this class in order to make custom items a lot cleaner to make!
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.CustomItems;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class ItemManager {
|
||||
|
||||
/// The item list. DO NOT ADD TO THE LIST YOURSELF. USE
|
||||
/// THE RegisterItem(...) FUNCTION OTHERWISE YOUR ITEM WILL
|
||||
/// NOT BE REGISTERED PROPERLY AND MAY BREAK THE GAME
|
||||
public static final List<Item> itemList = new ArrayList<Item>();
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterItem
|
||||
///
|
||||
/// @arg[in] name is the item name. IMPORTANT: Name must adhere to rules:
|
||||
/// 1. The name provided here must match these names:
|
||||
/// * This items models/item name
|
||||
/// * This items textures/item name
|
||||
/// 2 Name must be lowercase & no special characters besides '_'
|
||||
///
|
||||
/// @arg[in] item is the item to be added to the item list
|
||||
///
|
||||
/// @brief This is the call to register your item to the game! Please
|
||||
/// do not forget to update the models/item json file, the
|
||||
/// textures/item png name, and finally the lang/en_us.json file
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public static void RegisterItem(String name, Item item) {
|
||||
Item newItem = Registry.register(Registries.ITEM, new Identifier(Keeblarcraft.MOD_ID, name), item);
|
||||
itemList.add(newItem);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn RegisterAllItems
|
||||
///
|
||||
/// @brief This function is only meant to be called by the main mod
|
||||
/// execution path and should only be called once. This is a
|
||||
/// glorified print statement - but also serves to add the
|
||||
/// example item in the game
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public static void RegisterAllItems() {
|
||||
Keeblarcraft.LOGGER.info("Registering mod items for " + Keeblarcraft.MOD_ID);
|
||||
|
||||
// Call the item group register function first
|
||||
CustomItemGroups.RegisterGroups();
|
||||
|
||||
// The example item provides a demo of how you could make an item in your class
|
||||
// Item exampleItem = new Item(new FabricItemSettings());
|
||||
// RegisterItem("metaljacket_helmet", exampleItem);
|
||||
}
|
||||
|
||||
}
|
16
src/main/java/jesse/keeblarcraft/EventMgr/EventManager.java
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
*
|
||||
* EventManager
|
||||
*
|
||||
* This class is responsible for handling the setup and execution of events within the game for the mod. These events can be configured as plugins in this
|
||||
* directory which are executed in an abstract fashion with handling. If you need a new event (for a story item, or handling a player event, etc) then it
|
||||
* is preferred to add that as an extension class and called within this manager object
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.EventMgr;
|
||||
|
||||
|
||||
public class EventManager {
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package jesse.keeblarcraft.EventMgr;
|
||||
|
||||
import jesse.CommonServerUtils;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
// This interface is responsible for the end tick of a server world event tick
|
||||
public class ServerTickListener implements ServerTickEvents.EndTick {
|
||||
CommonServerUtils config = new CommonServerUtils();
|
||||
@Override
|
||||
public void onEndTick(MinecraftServer server) {
|
||||
if (server != null) {
|
||||
config.SetServerInstance(server);
|
||||
}
|
||||
}
|
||||
|
||||
// Static method to register the server tick listener
|
||||
public static void InitializeServerTicks() {
|
||||
ServerTickEvents.END_SERVER_TICK.register(new ServerTickListener());
|
||||
}
|
||||
}
|
15
src/main/java/jesse/keeblarcraft/FactionMgr/TeamManager.java
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
*
|
||||
* TeamManager
|
||||
*
|
||||
* Class is responsible for keeping track of teams/factions chosen by the players in the game and saves to the configuration
|
||||
* file for persistent data storage. Class handles checks as well for eligibility purposes (making sure players can join, etc)
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.FactionMgr;
|
||||
|
||||
public class TeamManager {
|
||||
// Class controls managing teams and pulling from configuration file and loading to configuration file
|
||||
|
||||
}
|
86
src/main/java/jesse/keeblarcraft/GuiMgr/TreeHandler.java
Normal file
@ -0,0 +1,86 @@
|
||||
package jesse.keeblarcraft.GuiMgr;
|
||||
|
||||
import jesse.keeblarcraft.Keeblarcraft;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.inventory.SimpleInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
|
||||
// Server side screen handler for the attribute tree
|
||||
public class TreeHandler extends ScreenHandler {
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn TreeHandler
|
||||
///
|
||||
/// @arg[in] syncId is SUPPOSED to be some sync identifier between the
|
||||
/// server and client. This isn't being used yet, so there isn't
|
||||
/// enough knowledge to make a good documentation note on it.
|
||||
/// Coming soon!
|
||||
///
|
||||
/// @arg[in] inventory is the players inventory. Required by HandledScreen
|
||||
/// object however is unused currently so we make the size 0. As
|
||||
/// needs and use-cases change; this may be reworked in the future
|
||||
///
|
||||
/// @brief Class constructor
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public TreeHandler(int syncId, PlayerInventory inventory) {
|
||||
// Call the constructor below
|
||||
this(syncId, inventory, new SimpleInventory(0));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn TreeHandler
|
||||
///
|
||||
/// @arg[in] syncId is SUPPOSED to be some sync identifier between the
|
||||
/// server and client. This isn't being used yet, so there isn't
|
||||
/// enough knowledge to make a good documentation note on it.
|
||||
/// Coming soon!
|
||||
///
|
||||
/// @arg[in] inventory is the players inventory. Required by HandledScreen
|
||||
/// object however is unused currently so we make the size 0. As
|
||||
/// needs and use-cases change; this may be reworked in the future
|
||||
///
|
||||
/// @arg[in] inventory is the SERVER's inventory - which is what syncId
|
||||
/// would likely be useful for. Once I (Jesse) get the screen stuff
|
||||
/// more sorted out - a more useful doxygen comment will be applied
|
||||
/// here in this class. Coming soon!
|
||||
///
|
||||
/// @brief Class constructor
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public TreeHandler(int syncId, PlayerInventory playerInventory, Inventory inventory) {
|
||||
super(Keeblarcraft.TREE_HANDLER, syncId);
|
||||
|
||||
System.out.println("Created tree handler");
|
||||
System.out.println("Is static var null? " + Keeblarcraft.TREE_HANDLER == null ? "YES":"NO");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn quickMove
|
||||
///
|
||||
/// @arg[in] player is the player entity moving an item
|
||||
///
|
||||
/// @arg[in] slot is the inventory slot to quick move to (shift+click)
|
||||
///
|
||||
/// @brief Required by parent class; currently do nothing as we aren't
|
||||
/// using inventories in the gui's!
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public ItemStack quickMove(PlayerEntity player, int slot) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn canUse
|
||||
///
|
||||
/// @arg[in] player is the player entity moving an item
|
||||
///
|
||||
/// @brief Returns whether the screen handler can be used. Required by
|
||||
/// parent class as its abstract; but for now players can always
|
||||
/// use GUI's and need no confirmation!
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public boolean canUse(PlayerEntity player) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,239 @@
|
||||
/*
|
||||
*
|
||||
* Note.java
|
||||
*
|
||||
* Class defines what will be in a configuration file for a user note. All metadata is in this class when read from file
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.JsonClassObjects;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||
import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION;
|
||||
|
||||
public class PlayerNote {
|
||||
/// Class variables
|
||||
NoteFile thisNote = new NoteFile();
|
||||
ConfigManager config = new ConfigManager();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @class NoteMetadata
|
||||
///
|
||||
/// @brief The metadata that is attached to each entry in the notebook.
|
||||
/// This includes not just the note itself, but other important
|
||||
/// factors that can be characteristic to each note and useful
|
||||
///
|
||||
/// @note You can picture this as each page in the notebook if it's
|
||||
/// an easier mental image
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private class NoteMetadata {
|
||||
public NoteMetadata(String note, long id, /*long mcday,*/ long sysTime, long chapter, long part) {
|
||||
this.note = note;
|
||||
this.noteId = id;
|
||||
// this.minecraftDay = mcday;
|
||||
this.systemTime = sysTime;
|
||||
this.storyChapter = chapter;
|
||||
this.storyPart = part;
|
||||
}
|
||||
|
||||
String note; // The note itself
|
||||
|
||||
long noteId; // Copied in from the file name, noteId
|
||||
// long minecraftDay; // The minecraft day the note was taken on
|
||||
long systemTime; // The current system time of the server
|
||||
long storyChapter; // The chapter of the story the player is in
|
||||
long storyPart; // Every event in a story is one part
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @class NoteFile
|
||||
///
|
||||
/// @brief This is the notebook
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public class NoteFile {
|
||||
// the uuid is the name of the file written to disk
|
||||
String uuid;
|
||||
public HashMap<Integer, NoteMetadata> noteMap = new HashMap<Integer, NoteMetadata>();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn PlayerNote
|
||||
///
|
||||
/// @brief This class's non-trivial constructor. Grabs a handle on the
|
||||
/// server-side file that is the players notebook at object
|
||||
/// creation. If one does not exist, one is created
|
||||
///
|
||||
/// @arg[in] uuid is the players uuid value
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public PlayerNote(String uuid) {
|
||||
|
||||
// DEVELOPER NOTE:
|
||||
// If you are testing this part of the code, please be reminded that anonymous testing starts a new
|
||||
// player instance everytime you launch. This means the UUID CAN CHANGE when you launch the
|
||||
// game! This is not an issue with proper registered accounts in production
|
||||
Boolean existingFile = false;
|
||||
try {
|
||||
thisNote = config.GetJsonObjectFromFile("notes/" + uuid + ".json", NoteFile.class);
|
||||
existingFile = true;
|
||||
} catch (Exception e) {
|
||||
// Do nothing. This means the file does not exist
|
||||
}
|
||||
|
||||
// In the event the above code failed out, this means a new file has to be created for the player's uuid
|
||||
if (!existingFile)
|
||||
{
|
||||
System.out.println(ChatUtil.ColoredString("Trying to create new file", CONSOLE_COLOR.BLUE));
|
||||
try {
|
||||
thisNote.uuid = uuid;
|
||||
FlashConfig();
|
||||
} catch (Exception e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not write to file", CONSOLE_COLOR.RED));
|
||||
}
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("Moving on", CONSOLE_COLOR.BLUE));
|
||||
}
|
||||
|
||||
// It's possible the above code will return a blank class if a file doesn't exist. This will make
|
||||
// a new file with this players uuid
|
||||
if ("".equals(thisNote.uuid)) {
|
||||
System.out.println(ChatUtil.ColoredString("Assigning new config file for this uuid. No previous existing", CONSOLE_COLOR.BLUE));
|
||||
thisNote.uuid = uuid;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn AddNote
|
||||
///
|
||||
/// @brief Adds a new note to the notebook
|
||||
///
|
||||
/// @arg[in] newNote is the new string value of the note
|
||||
///
|
||||
/// @arg[in] minecraftDay is currently unsupported but will be the day of
|
||||
/// the minecraft world when it is implemented
|
||||
///
|
||||
/// @arg[in] systemTime is the epoch time in milliseconds
|
||||
///
|
||||
/// @arg[in] storyChapter is the chapter in the story this note was taken
|
||||
///
|
||||
/// @arg[in] storyPart is the part in the chapter the note was taken
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void AddNote(String newNote, long minecraftDay, long systemTime, long storyChapter, long storyPart) {
|
||||
Integer noteKey = thisNote.noteMap.size() + 1;
|
||||
thisNote.noteMap.put(noteKey, new NoteMetadata(newNote, noteKey, /*minecraftDay,*/ systemTime, storyChapter, storyPart));
|
||||
|
||||
FlashConfig(); ///TODO: This might be really unnecessary and may only be required on clean up as opposed to everytime the command is run
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn DeleteNote
|
||||
///
|
||||
/// @brief Deletes a note in the notebook
|
||||
///
|
||||
/// @arg[in] noteId is the id to delete
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void DeleteNote(Integer noteId) {
|
||||
thisNote.noteMap.remove(noteId);
|
||||
FlashConfig();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn ModifyNote
|
||||
///
|
||||
/// @brief Modifies a note at noteId entry OR creates new note at that
|
||||
/// entry if the id didn't exist previously
|
||||
///
|
||||
/// @arg[in] noteId is the id we wish to modify the note of
|
||||
///
|
||||
/// @arg[in] newNote is the new string value of the note
|
||||
///
|
||||
/// @arg[in] minecraftDay is currently unsupported but will be the day of
|
||||
/// the minecraft world when it is implemented
|
||||
///
|
||||
/// @arg[in] systemTime is the epoch time in milliseconds
|
||||
///
|
||||
/// @arg[in] storyChapter is the chapter in the story this note was taken
|
||||
///
|
||||
/// @arg[in] storyPart is the part in the chapter the note was taken
|
||||
///
|
||||
/// @return 0 if success, -1 if not
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void ModifyNote(Integer noteId, String newNote, /*long minecraftDay,*/ long systemTime, long storyChapter, long storyPart) {
|
||||
thisNote.noteMap.put(noteId, new NoteMetadata(newNote, noteId, /*minecraftDay,*/ systemTime, storyChapter, storyPart));
|
||||
FlashConfig();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn PurgeAllNotes
|
||||
///
|
||||
/// @brief Wipes the players notebook clean
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void PurgeAllNotes() {
|
||||
thisNote.noteMap.clear();
|
||||
FlashConfig();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GetNoteString
|
||||
///
|
||||
/// @brief Gets the note string in the map by identifier. NOT metadata
|
||||
///
|
||||
/// @arg[in] key is the map key we wish to return
|
||||
///
|
||||
/// @return Empty string if that ID contains no note, or string with note
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public String GetNoteString(Integer key) {
|
||||
if (thisNote.noteMap.containsKey(key)) {
|
||||
return thisNote.noteMap.get(key).note;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GetNotebookSize
|
||||
///
|
||||
/// @brief Returns the size of the notebook object
|
||||
///
|
||||
/// @return Size of notebook
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public Integer GetNotebookSize() {
|
||||
return thisNote.noteMap.size();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn GetNoteKey
|
||||
///
|
||||
/// @brief Returns the key identifier of a note by the value in the map
|
||||
///
|
||||
/// @arg[in] currentNote is the string note that we wish to see if exists
|
||||
///
|
||||
/// @return 0 or positive number if key found, negative number if not
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public Integer GetNoteKey(String currentNote) {
|
||||
Integer ret = -1;
|
||||
for (Entry<Integer, NoteMetadata> entry : thisNote.noteMap.entrySet()) {
|
||||
if (entry.getValue().note.equals(currentNote)) {
|
||||
ret = entry.getKey();
|
||||
}
|
||||
}
|
||||
FlashConfig();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn FlashConfig
|
||||
///
|
||||
/// @brief Writes to the configuration file
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
public void FlashConfig() {
|
||||
try {
|
||||
config.WriteToJsonFile("notes/" + thisNote.uuid + ".json", thisNote);
|
||||
} catch (FILE_WRITE_EXCEPTION e) {
|
||||
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
|
||||
}
|
||||
}
|
||||
}
|
111
src/main/java/jesse/keeblarcraft/Keeblarcraft.java
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
*
|
||||
* Keeblarcraft
|
||||
*
|
||||
* This is the primary server side "main" object that is referenced by Fabric. This is where everything is setup for the mod
|
||||
* and a very important class. Please becareful as you add to it
|
||||
*
|
||||
*/
|
||||
|
||||
// color colour
|
||||
|
||||
package jesse.keeblarcraft;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.resource.featuretoggle.FeatureSet;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
|
||||
import jesse.keeblarcraft.AttributeMgr.AttributeTree;
|
||||
import jesse.keeblarcraft.Commands.CustomCommandManager;
|
||||
import jesse.keeblarcraft.CustomBlocks.BlockList;
|
||||
import jesse.keeblarcraft.CustomItems.ItemManager;
|
||||
import jesse.keeblarcraft.EventMgr.ServerTickListener;
|
||||
import jesse.keeblarcraft.GuiMgr.TreeHandler;
|
||||
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||
import jesse.keeblarcraft.Utils.Setup;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||
|
||||
public class Keeblarcraft implements ModInitializer {
|
||||
public static String MOD_ID = "keeblarcraft";
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger("keeblarcraft");
|
||||
|
||||
// May be moved in future; but is the universal TREE_HANDLER call for at least the tree gui. It's possible it can get a more
|
||||
// generic name in the future after the tree gui is done; however until then it will remain TREE_HANDLER.
|
||||
public static final ScreenHandlerType<TreeHandler> TREE_HANDLER = Registry.register(Registries.SCREEN_HANDLER,
|
||||
Identifier.of(Keeblarcraft.MOD_ID, "tree_gui"),
|
||||
new ScreenHandlerType<>(TreeHandler::new, FeatureSet.empty()));
|
||||
|
||||
CustomCommandManager cmdMgr = new CustomCommandManager();
|
||||
Setup setup = Setup.GetInstance();
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
// This code runs as soon as Minecraft is in a mod-load-ready state.
|
||||
// However, some things (like resources) may still be uninitialized.
|
||||
// Proceed with mild caution.
|
||||
ChatUtil.LoggerColored("Hello Fabric world!", CONSOLE_COLOR.CYAN, LOGGER);
|
||||
|
||||
if (setup != null) {
|
||||
try {
|
||||
// Run setup. If setup fails; it throws SETUP_FAILED_EXCEPTION
|
||||
LOGGER.info("\033[34m Running setup stage \033[0m");
|
||||
setup.RunSetup();
|
||||
|
||||
// This is a very special case where this must be in this classes' initializer
|
||||
// method
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
var player = handler.player;
|
||||
Keeblarcraft.LOGGER.info("Player " + player.getName() + " has logged in. Creating tree...");
|
||||
|
||||
if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == false) {
|
||||
AttributeMgr.activeTrees.put(player.getUuidAsString(), new AttributeTree(player.getUuidAsString()));
|
||||
}
|
||||
});
|
||||
|
||||
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
|
||||
var player = handler.player;
|
||||
Keeblarcraft.LOGGER.info("Player " + player.getName() + " has logged out. Deleting tree...");
|
||||
|
||||
if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == true) {
|
||||
AttributeMgr.activeTrees.remove(player.getUuidAsString());
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize our ticks!!
|
||||
ServerTickListener.InitializeServerTicks();
|
||||
|
||||
// Run command registrations from the command manager
|
||||
LOGGER.info("\033[34m Running command registration \033[0m");
|
||||
cmdMgr.RegisterCustomCommands();
|
||||
|
||||
// Register attributes
|
||||
AttributeMgr.RegisterAttributes();
|
||||
|
||||
|
||||
/// THE BELOW ITEMS MUST BE DONE LAST IN THE STEPS
|
||||
// Register items
|
||||
ItemManager.RegisterAllItems();
|
||||
|
||||
// Register blocks
|
||||
BlockList.RegisterBlocks();
|
||||
|
||||
|
||||
} catch (SETUP_FAILED_EXCEPTION e) {
|
||||
System.out.println(ChatUtil.ColoredString("ERROR. Setup failed to initialize environment. Mod likely does not have read/write permissions inside area. Mod will now close out.", CONSOLE_COLOR.RED));
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
// Program exit. Dual definition of setup somehow happened!
|
||||
System.out.println(ChatUtil.ColoredString("Dual definition of singleton attempted! Out of order initialization? How did this even happen?", CONSOLE_COLOR.RED));
|
||||
}
|
||||
}
|
||||
}
|
17
src/main/java/jesse/keeblarcraft/StoryMgr/StoryMgr.java
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
*
|
||||
* Story Manager
|
||||
*
|
||||
* Class keeps track of the story/note-taking done by players and saves it automagically to the configuration file for note taking / story tracking for
|
||||
* the server.
|
||||
*
|
||||
* In larger detail, this class will set a timeline for each player and where they are on the story. Depending on where they are in the story, certain
|
||||
* milestones will be tagged to their account so they may access certain things that are unlockable achievements within this class
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.StoryMgr;
|
||||
|
||||
public class StoryMgr {
|
||||
|
||||
}
|
157
src/main/java/jesse/keeblarcraft/Utils/ChatUtil.java
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
*
|
||||
* ChatUtil
|
||||
*
|
||||
* Helpful utility for pretty printing in chat in the game with different supported functions and levels
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.Utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class ChatUtil {
|
||||
//This is a private class only used internally to get ANSI colors
|
||||
private static class ConsoleColor {
|
||||
public static String getColor(CONSOLE_COLOR color) {
|
||||
String ret = "";
|
||||
switch(color) {
|
||||
case RED:
|
||||
ret = "31";
|
||||
break;
|
||||
case GREEN:
|
||||
ret = "32";
|
||||
break;
|
||||
case YELLOW:
|
||||
ret = "33";
|
||||
break;
|
||||
case BLUE:
|
||||
ret = "34";
|
||||
break;
|
||||
case MAGENTA:
|
||||
ret = "35";
|
||||
break;
|
||||
case CYAN:
|
||||
ret = "36";
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public static enum CONSOLE_COLOR {
|
||||
RED,
|
||||
GREEN,
|
||||
YELLOW,
|
||||
BLUE,
|
||||
MAGENTA,
|
||||
CYAN;
|
||||
}
|
||||
|
||||
static int CHATBOX_WIDTH_CHARS = 80; // Maximum length of the textbox in individual characters
|
||||
|
||||
// Helpful print wrapper function
|
||||
static public void SendPlayerMsg(ServerPlayerEntity player, String text) {
|
||||
player.sendMessage(Text.literal(text));
|
||||
}
|
||||
|
||||
/// TODO: Add this back in later under a chat ticket
|
||||
// Prints a table of data in chat
|
||||
// static public void ChatBlock(ServerPlayerEntity player, HashMap<Text, List<Text>> table) {
|
||||
|
||||
// ///DEBUG
|
||||
// for (Entry<Text, List<Text>> entry : table.entrySet()) {
|
||||
// for (int debug = 0; debug < entry.getValue().size(); debug++) {
|
||||
// System.out.println("KEY: " + entry.getKey().toString() + " VALUE: " + entry.getValue().get(debug).toString());
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// // The user will likely pass in text strings longer than the character limit for num of columns; therefore
|
||||
// // we are required to split these into this finalPrintList structure
|
||||
// HashMap<Text, ArrayList<Text>> finalPrintList = new HashMap<Text, ArrayList<Text>>();
|
||||
|
||||
// int maxColumnWidth = CHATBOX_WIDTH_CHARS / table.size(); // Represents max char allowance per data column
|
||||
// maxColumnWidth -= table.size(); // Represents a separating '|' between each column
|
||||
|
||||
// // This first behemoth of a loop is to take the given table hashmap and look at
|
||||
// // the Text values & split them
|
||||
// // should their size exceed the maxColumnWidth given for each entry key
|
||||
// System.out.println("Entry data is size " + table.size());
|
||||
// for (Entry<Text, List<Text>> entry : table.entrySet()) {
|
||||
// // Each text line found cannot be longer than "maxColumnWidth" or else it must
|
||||
// // wrap which splits it
|
||||
// // into two texts; thus adding an additional row that is required for iteration.
|
||||
// // Each split text must
|
||||
// // maintain the same formatting as the root text it is split from
|
||||
|
||||
// finalPrintList.put(entry.getKey(), new ArrayList<Text>()); // Instantiate the key & array
|
||||
// System.out.println("Map size is " + finalPrintList.size());
|
||||
// System.out.println("Entry value size is " + entry.getValue().size());
|
||||
// for (Text item : entry.getValue()) {
|
||||
// int numItems = (int) Math.ceil((item.getString().length() / maxColumnWidth));
|
||||
// int strOffset = numItems; // Represents number of items per string
|
||||
// System.out.println("numItems: " + numItems);
|
||||
// System.out.println("strOffset: " + strOffset);
|
||||
|
||||
// for (int offset = 0; offset <= numItems; offset++) { /// TODO: might need to be <=
|
||||
// int start = strOffset * offset; // Multiple from start of string to needed point
|
||||
// int end = start + strOffset; // The original start offset + the width spacer
|
||||
// String substr = item.toString().substring(start, end); // Contains the string to be Textified
|
||||
|
||||
// MutableText newText = Text.literal(substr).setStyle(item.getStyle());
|
||||
// finalPrintList.get(entry.getKey()).add(newText); // Add back into list
|
||||
// System.out.println("SPLIT DEBUG: " + newText.toString());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // This loop does the printing of the table in chat
|
||||
// int tempPreventInfiniteLoops = 10;
|
||||
// while (finalPrintList.size() != 0) {
|
||||
|
||||
// // This is a one time print
|
||||
// MutableText line = Text.literal("");
|
||||
// for (Entry<Text, ArrayList<Text>> entry : finalPrintList.entrySet()) {
|
||||
// if (entry.getValue().size() != 0) {
|
||||
// line.append(entry.getValue().get(0));
|
||||
|
||||
// System.out.println("new line is now " + line.toString());
|
||||
// line.append("|");
|
||||
// } else {
|
||||
// finalPrintList.remove(entry.getKey()); // Clear the key; as we are done with this column for
|
||||
// // printing
|
||||
// }
|
||||
|
||||
// player.sendMessage(line);
|
||||
// String debugPrint = line.toString();
|
||||
// System.out.println("Debug line to be printed: " + debugPrint);
|
||||
// line = Text.literal("");
|
||||
// break;
|
||||
// }
|
||||
|
||||
// tempPreventInfiniteLoops--;
|
||||
// if (tempPreventInfiniteLoops <= 0) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Returns a string with the proper ANSI encoding for the specified CONSOLE_COLOR
|
||||
static public String ColoredString(String msg, CONSOLE_COLOR color) {
|
||||
return "\033[" + ConsoleColor.getColor(color) + "m" + msg + "\033[0m";
|
||||
}
|
||||
|
||||
// Takes in a (already initialized) logger object and prints to console
|
||||
static public void LoggerColored(String msg, CONSOLE_COLOR color, Logger logger) {
|
||||
logger.info(ColoredString(msg, color));
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package jesse.keeblarcraft.Utils.CommonStructures;
|
||||
|
||||
public class Position2d {
|
||||
public Position2d(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package jesse.keeblarcraft.Utils.CommonStructures;
|
||||
|
||||
public class Position3d {
|
||||
public Position3d(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public int z;
|
||||
}
|
18
src/main/java/jesse/keeblarcraft/Utils/CustomExceptions.java
Normal file
@ -0,0 +1,18 @@
|
||||
package jesse.keeblarcraft.Utils;
|
||||
|
||||
public class CustomExceptions {
|
||||
// File exceptions
|
||||
public static class FILE_CREATE_EXCEPTION extends Exception {}
|
||||
public static class FILE_WRITE_EXCEPTION extends Exception {}
|
||||
public static class FILE_DELETE_EXCEPTION extends Exception {}
|
||||
|
||||
// Directory exceptions
|
||||
public static class DIRECTORY_DELETE_EXCEPTION extends Exception {}
|
||||
public static class DIRECTORY_CREATE_EXCEPTION extends Exception {}
|
||||
public static class DIRECTORY_MOVE_EXCEPTION extends Exception {}
|
||||
|
||||
// Setup exceptions
|
||||
public static class SETUP_NO_WRITE_EXCEPTION extends Exception {}
|
||||
public static class SETUP_NO_READ_EXCEPTION extends Exception {}
|
||||
public static class SETUP_FAILED_EXCEPTION extends Exception {}
|
||||
}
|
162
src/main/java/jesse/keeblarcraft/Utils/Setup.java
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
*
|
||||
* Setup.java
|
||||
*
|
||||
* Setup is a singleton object that runs on the initial mod setup to run critical checks to make sure the mod
|
||||
* is allowed to do things on the users filesystem (reading conf files, writing conf files, etc). It's quite
|
||||
* important for the mod to know this!
|
||||
*
|
||||
*/
|
||||
|
||||
package jesse.keeblarcraft.Utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||
import jesse.keeblarcraft.Utils.CustomExceptions.DIRECTORY_CREATE_EXCEPTION;
|
||||
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
|
||||
|
||||
// Singleton class is designed to help the mod set itself up and create all the important things. It does two things:
|
||||
//
|
||||
// Thing 1: If on initial setup of mod for first time; creates all necessary directories and files.
|
||||
// Doing this helps the mod know if it has permissions to do things, or if it shouldn't even bother!
|
||||
// Some functionality is disabled if the mod can't access the hard drive in various ways.
|
||||
//
|
||||
// Thing 2: On any sequential startup; it checks to make sure all the directories exist & replaces missing ones.
|
||||
// It will also do a state-check of the system to make sure we will have permissions to read & write.
|
||||
// If we do not have these, or only partial - then functionality may be disabled for runtime performance
|
||||
public final class Setup {
|
||||
private static Setup static_inst;
|
||||
|
||||
public Setup() {
|
||||
System.out.println(ChatUtil.ColoredString("Running system setup and checks...", CONSOLE_COLOR.BLUE));
|
||||
}
|
||||
|
||||
// Returns the singleton object
|
||||
public static Setup GetInstance() {
|
||||
if (static_inst == null) {
|
||||
static_inst = new Setup();
|
||||
}
|
||||
|
||||
return static_inst;
|
||||
}
|
||||
|
||||
/// Unit testing functions below
|
||||
public static Boolean has_read = false;
|
||||
public static Boolean has_write = false;
|
||||
|
||||
// First time setup variables
|
||||
private static final List<String> DIRECTORY_LIST = new ArrayList<String>() {{
|
||||
add("notes"); // Expect 1 file per player!
|
||||
add("factions"); // Expect 1 file per faction!
|
||||
add("story"); // Expect 1 file per story chapter!
|
||||
add("commands"); // Expect 1 file per command that's configurable!
|
||||
add("events"); // Expect 1 file per event that is configurable!
|
||||
add("bank");
|
||||
add("attributes");
|
||||
}};
|
||||
|
||||
// These will be top-level config files above the directories this mod creates
|
||||
private static final List<String> FILE_LIST = new ArrayList<String>() {{
|
||||
add("story/general_story_config.json"); // Big config file, determines when players can do certain things at different story levels
|
||||
add("factions/general_factions_config.json"); // General configuration file for factions stuff
|
||||
add("events/general_event_config.json"); // General configuration file for story events!
|
||||
add("general.json"); // The super general configuration file! (May be removed)
|
||||
add("attributes/general_attribute_config.json");
|
||||
}};
|
||||
|
||||
// RunChecks()
|
||||
//
|
||||
// Checks if we are able to create necessary directories and run reading over the file system for the current
|
||||
// directory this mod is maintained in. This will return false if any checks fail; but individual checks can
|
||||
// be accessed in class variables (above)
|
||||
public Boolean RunChecks() {
|
||||
ConfigManager conf = new ConfigManager();
|
||||
|
||||
// Create directory check
|
||||
try {
|
||||
has_write = conf.CreateDirectory("test_dir");
|
||||
System.out.println(ChatUtil.ColoredString("test_dir created! has write: ", CONSOLE_COLOR.GREEN) + (has_write ? ChatUtil.ColoredString("YES", CONSOLE_COLOR.YELLOW) : ChatUtil.ColoredString("NO", CONSOLE_COLOR.YELLOW)));
|
||||
} catch (DIRECTORY_CREATE_EXCEPTION e) {
|
||||
System.out.println(ChatUtil.ColoredString("Failed to create test directory or it already exists", CONSOLE_COLOR.MAGENTA));
|
||||
has_write = false;
|
||||
}
|
||||
|
||||
// Write to disk then read that data back
|
||||
if (has_write) {
|
||||
try {
|
||||
has_write = conf.CreateFile("test_dir/test_note.txt");
|
||||
has_write = conf.WriteToFile("test_dir/test_note.txt", "test_write_read", "w");
|
||||
|
||||
List<String> lines = conf.GetFile("test_dir/test_note.txt");
|
||||
if (lines.size() == 0) {
|
||||
has_read = false;
|
||||
} else {
|
||||
has_read = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(ChatUtil.ColoredString("Failed to create or write to test dir file ", CONSOLE_COLOR.RED));
|
||||
has_read = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete directory if created (it's a temporary dir)
|
||||
if (has_write) {
|
||||
try {
|
||||
has_write = conf.DeleteFile("test_dir/test_note.txt");
|
||||
has_write = conf.DeleteDirectory("test_dir");
|
||||
} catch (Exception e) {
|
||||
System.out.println(ChatUtil.ColoredString("Lost access to writing mid-way", CONSOLE_COLOR.RED));
|
||||
has_write = false;
|
||||
}
|
||||
}
|
||||
//need to be able to take in raw booleans for coloredstrings functions
|
||||
System.out.println(ChatUtil.ColoredString("CHECKS DEBUG: Value of has_write: ", CONSOLE_COLOR.BLUE) + ChatUtil.ColoredString(has_write.toString(), CONSOLE_COLOR.YELLOW) + ChatUtil.ColoredString(". Value of has_read: ", CONSOLE_COLOR.BLUE) + ChatUtil.ColoredString(has_read.toString(), CONSOLE_COLOR.YELLOW));
|
||||
return has_write && has_read;
|
||||
}
|
||||
|
||||
// RunSetup
|
||||
//
|
||||
// Primary function call that will execute when mod starts up
|
||||
public Boolean RunSetup() throws SETUP_FAILED_EXCEPTION {
|
||||
Boolean ret = false;
|
||||
|
||||
// Setup can only complete if it has guarenteed we have read & write permissions
|
||||
if (ret = RunChecks()) {
|
||||
try {
|
||||
// Create necessary directories
|
||||
ConfigManager conf = new ConfigManager();
|
||||
for (Integer i = 0; i < DIRECTORY_LIST.size(); i++) {
|
||||
if ( ! conf.DoesDirectoryExist(DIRECTORY_LIST.get(i))) {
|
||||
conf.CreateDirectory(DIRECTORY_LIST.get(i));
|
||||
System.out.println(ChatUtil.ColoredString("Creating directory ", CONSOLE_COLOR.GREEN) + ChatUtil.ColoredString(DIRECTORY_LIST.get(i), CONSOLE_COLOR.YELLOW) + ChatUtil.ColoredString("...", CONSOLE_COLOR.GREEN));
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("Directory ", CONSOLE_COLOR.BLUE) + conf.DoesDirectoryExist(DIRECTORY_LIST.get(i)) + ChatUtil.ColoredString(" already exists. Skipping... ", CONSOLE_COLOR.BLUE));
|
||||
}
|
||||
}
|
||||
|
||||
// Create necessary files
|
||||
for (Integer i = 0; i < FILE_LIST.size(); i++) {
|
||||
if ( ! conf.DoesFileExist(FILE_LIST.get(i))) {
|
||||
conf.CreateFile(FILE_LIST.get(i));
|
||||
System.out.println(ChatUtil.ColoredString("Creating file ", CONSOLE_COLOR.GREEN) + ChatUtil.ColoredString(FILE_LIST.get(i), CONSOLE_COLOR.YELLOW) + ChatUtil.ColoredString("...", CONSOLE_COLOR.GREEN));
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("File ", CONSOLE_COLOR.BLUE) + conf.DoesDirectoryExist(FILE_LIST.get(i)) + ChatUtil.ColoredString(" already exists. Skipping...", CONSOLE_COLOR.BLUE));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new SETUP_FAILED_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
System.out.println(ChatUtil.ColoredString("RunChecks() failed in its process. This mod has deemed it does not have read or write privileges in its hosted area and will now exit.", CONSOLE_COLOR.RED));
|
||||
throw new SETUP_FAILED_EXCEPTION();
|
||||
}
|
||||
|
||||
System.out.println(ChatUtil.ColoredString("DID SETUP COMPLETE SUCCESSFULLY? ", CONSOLE_COLOR.YELLOW) + (ret ? ChatUtil.ColoredString("YES", CONSOLE_COLOR.YELLOW) : ChatUtil.ColoredString("NO", CONSOLE_COLOR.YELLOW)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "keeblarcraft:block/example_block"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "keeblarcraft:block/example_block_ore"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "keeblarcraft:block/example_statue"
|
||||
}
|
||||
}
|
||||
}
|
BIN
src/main/resources/assets/keeblarcraft/icon.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
16
src/main/resources/assets/keeblarcraft/lang/en_us.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"item.keeblarcraft.metaljacket_helmet": "MetalJacket Helmet",
|
||||
"item.keeblarcraft.metaljacket_chestplate": "MetalJacket Chestplate",
|
||||
"item.keeblarcraft.metaljacket_leggings": "MetalJacket Leggings",
|
||||
"item.keeblarcraft.metaljacket_boots": "MetalJacket Booties",
|
||||
|
||||
"itemgroup.keeblarcraft": "Keeblarcraft Modded Items",
|
||||
|
||||
"block.keeblarcraft.example_block": "Keeblarcraft example block",
|
||||
"block.keeblarcraft.example_block_ore": "Keeblarcraft example block ore",
|
||||
"block.keeblarcraft.example_statue": "Keeblarcraft example statue",
|
||||
|
||||
"category.keeblarcraft.test": "Keeblarcraft bindings",
|
||||
"key.keeblarcraft.treemap": "Tree GUI",
|
||||
"key.keeblarcraft.globalconfig": "Config menu"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "block/cube_all",
|
||||
"textures": {
|
||||
"all": "keeblarcraft:block/example_block"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "block/cube_all",
|
||||
"textures": {
|
||||
"all": "keeblarcraft:block/example_block_ore"
|
||||
}
|
||||
}
|
@ -0,0 +1,481 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"0": "keeblarcraft:block/example_statue",
|
||||
"particle": "keeblarcraft:block/example_statue"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "platform",
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 1, 16],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [5, 0, 3]},
|
||||
"faces": {
|
||||
"north": {"uv": [4, 2.5, 8, 2.75], "texture": "#0"},
|
||||
"east": {"uv": [4, 2.75, 8, 3], "texture": "#0"},
|
||||
"south": {"uv": [4, 3, 8, 3.25], "texture": "#0"},
|
||||
"west": {"uv": [4, 3.25, 8, 3.5], "texture": "#0"},
|
||||
"up": {"uv": [4, 4, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [4, 4, 0, 8], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "left_leg",
|
||||
"from": [7, 1, 3],
|
||||
"to": [9, 5, 5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [5.5, 5.5, 6, 6.75], "texture": "#0"},
|
||||
"east": {"uv": [6, 0, 6.5, 1.25], "texture": "#0"},
|
||||
"south": {"uv": [6, 1.25, 6.5, 2.5], "texture": "#0"},
|
||||
"west": {"uv": [6, 3.5, 6.5, 4.75], "texture": "#0"},
|
||||
"up": {"uv": [6.75, 7.75, 6.25, 7.25], "texture": "#0"},
|
||||
"down": {"uv": [7.75, 7, 7.25, 7.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "right_leg",
|
||||
"from": [7, 1, 11],
|
||||
"to": [9, 5, 13],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 11]},
|
||||
"faces": {
|
||||
"north": {"uv": [6, 4.75, 6.5, 6], "texture": "#0"},
|
||||
"east": {"uv": [6, 6, 6.5, 7.25], "texture": "#0"},
|
||||
"south": {"uv": [6.5, 0, 7, 1.25], "texture": "#0"},
|
||||
"west": {"uv": [6.5, 1.25, 7, 2.5], "texture": "#0"},
|
||||
"up": {"uv": [8, 0.5, 7.5, 0], "texture": "#0"},
|
||||
"down": {"uv": [8, 0.5, 7.5, 1], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 5, 5],
|
||||
"to": [9, 10, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 5, 7]},
|
||||
"faces": {
|
||||
"north": {"uv": [6.5, 3.5, 7, 4.75], "texture": "#0"},
|
||||
"east": {"uv": [4, 0, 5.5, 1.25], "texture": "#0"},
|
||||
"south": {"uv": [6.5, 4.75, 7, 6], "texture": "#0"},
|
||||
"west": {"uv": [4, 1.25, 5.5, 2.5], "texture": "#0"},
|
||||
"up": {"uv": [6, 1.5, 5.5, 0], "texture": "#0"},
|
||||
"down": {"uv": [4.5, 5.5, 4, 7], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 8, 10],
|
||||
"to": [9, 10, 12],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 8, 10]},
|
||||
"faces": {
|
||||
"north": {"uv": [7.5, 1, 8, 1.5], "texture": "#0"},
|
||||
"east": {"uv": [7.5, 1.5, 8, 2], "texture": "#0"},
|
||||
"south": {"uv": [7.5, 2, 8, 2.5], "texture": "#0"},
|
||||
"west": {"uv": [7.5, 3.5, 8, 4], "texture": "#0"},
|
||||
"up": {"uv": [8, 4.5, 7.5, 4], "texture": "#0"},
|
||||
"down": {"uv": [8, 5, 7.5, 5.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 10, 11],
|
||||
"to": [9, 11, 13],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 10, 11]},
|
||||
"faces": {
|
||||
"north": {"uv": [8, 2.75, 8.5, 3], "texture": "#0"},
|
||||
"east": {"uv": [8, 3, 8.5, 3.25], "texture": "#0"},
|
||||
"south": {"uv": [8, 3.25, 8.5, 3.5], "texture": "#0"},
|
||||
"west": {"uv": [3.5, 8, 4, 8.25], "texture": "#0"},
|
||||
"up": {"uv": [8, 6, 7.5, 5.5], "texture": "#0"},
|
||||
"down": {"uv": [8, 6, 7.5, 6.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 10, 13],
|
||||
"to": [9, 11, 14],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 10, 12]},
|
||||
"faces": {
|
||||
"north": {"uv": [8, 3.5, 8.5, 3.75], "texture": "#0"},
|
||||
"east": {"uv": [7.5, 8.5, 7.75, 8.75], "texture": "#0"},
|
||||
"south": {"uv": [8, 3.75, 8.5, 4], "texture": "#0"},
|
||||
"west": {"uv": [8.75, 8.75, 9, 9], "texture": "#0"},
|
||||
"up": {"uv": [8.5, 4.25, 8, 4], "texture": "#0"},
|
||||
"down": {"uv": [8.5, 4.25, 8, 4.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 11, 14],
|
||||
"to": [9, 13, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 11, 13]},
|
||||
"faces": {
|
||||
"north": {"uv": [7.5, 6.5, 8, 7], "texture": "#0"},
|
||||
"east": {"uv": [8, 5, 8.25, 5.5], "texture": "#0"},
|
||||
"south": {"uv": [7.25, 7.5, 7.75, 8], "texture": "#0"},
|
||||
"west": {"uv": [5.5, 8, 5.75, 8.5], "texture": "#0"},
|
||||
"up": {"uv": [8.5, 5.75, 8, 5.5], "texture": "#0"},
|
||||
"down": {"uv": [8.5, 5.75, 8, 6], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 14, 12],
|
||||
"to": [9, 15, 14],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 12]},
|
||||
"faces": {
|
||||
"north": {"uv": [8, 6, 8.5, 6.25], "texture": "#0"},
|
||||
"east": {"uv": [8, 6.25, 8.5, 6.5], "texture": "#0"},
|
||||
"south": {"uv": [8, 6.5, 8.5, 6.75], "texture": "#0"},
|
||||
"west": {"uv": [8, 6.75, 8.5, 7], "texture": "#0"},
|
||||
"up": {"uv": [4.5, 8.25, 4, 7.75], "texture": "#0"},
|
||||
"down": {"uv": [5, 7.75, 4.5, 8.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 14, 11],
|
||||
"to": [9, 15, 12],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 10]},
|
||||
"faces": {
|
||||
"north": {"uv": [7.25, 8, 7.75, 8.25], "texture": "#0"},
|
||||
"east": {"uv": [0, 9, 0.25, 9.25], "texture": "#0"},
|
||||
"south": {"uv": [7.75, 8, 8.25, 8.25], "texture": "#0"},
|
||||
"west": {"uv": [9, 0, 9.25, 0.25], "texture": "#0"},
|
||||
"up": {"uv": [8.75, 0.75, 8.25, 0.5], "texture": "#0"},
|
||||
"down": {"uv": [8.75, 0.75, 8.25, 1], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 14, 10],
|
||||
"to": [9, 15, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 9]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.25, 1, 8.75, 1.25], "texture": "#0"},
|
||||
"east": {"uv": [0.25, 9, 0.5, 9.25], "texture": "#0"},
|
||||
"south": {"uv": [8.25, 1.25, 8.75, 1.5], "texture": "#0"},
|
||||
"west": {"uv": [9, 0.25, 9.25, 0.5], "texture": "#0"},
|
||||
"up": {"uv": [8.75, 1.75, 8.25, 1.5], "texture": "#0"},
|
||||
"down": {"uv": [8.75, 1.75, 8.25, 2], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 13, 9],
|
||||
"to": [9, 14, 10],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 9]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.25, 2, 8.75, 2.25], "texture": "#0"},
|
||||
"east": {"uv": [0.5, 9, 0.75, 9.25], "texture": "#0"},
|
||||
"south": {"uv": [8.25, 2.25, 8.75, 2.5], "texture": "#0"},
|
||||
"west": {"uv": [0.75, 9, 1, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [3.25, 8.5, 2.75, 8.25], "texture": "#0"},
|
||||
"down": {"uv": [3.75, 8.25, 3.25, 8.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 11, 8],
|
||||
"to": [9, 13, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 11, 7]},
|
||||
"faces": {
|
||||
"north": {"uv": [5, 7.75, 5.5, 8.25], "texture": "#0"},
|
||||
"east": {"uv": [5.75, 8, 6, 8.5], "texture": "#0"},
|
||||
"south": {"uv": [6.25, 7.75, 6.75, 8.25], "texture": "#0"},
|
||||
"west": {"uv": [3.75, 8.25, 4, 8.75], "texture": "#0"},
|
||||
"up": {"uv": [4.5, 8.5, 4, 8.25], "texture": "#0"},
|
||||
"down": {"uv": [5, 8.25, 4.5, 8.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 10, 9],
|
||||
"to": [9, 11, 11],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 9, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [5, 8.25, 5.5, 8.5], "texture": "#0"},
|
||||
"east": {"uv": [8.25, 5, 8.75, 5.25], "texture": "#0"},
|
||||
"south": {"uv": [8.25, 5.25, 8.75, 5.5], "texture": "#0"},
|
||||
"west": {"uv": [6.25, 8.25, 6.75, 8.5], "texture": "#0"},
|
||||
"up": {"uv": [8.25, 7.5, 7.75, 7], "texture": "#0"},
|
||||
"down": {"uv": [8.25, 7.5, 7.75, 8], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 13, 14],
|
||||
"to": [9, 14, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 14]},
|
||||
"faces": {
|
||||
"north": {"uv": [6.75, 8.25, 7.25, 8.5], "texture": "#0"},
|
||||
"east": {"uv": [1, 9, 1.25, 9.25], "texture": "#0"},
|
||||
"south": {"uv": [8.25, 7, 8.75, 7.25], "texture": "#0"},
|
||||
"west": {"uv": [1.25, 9, 1.5, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [7.75, 8.5, 7.25, 8.25], "texture": "#0"},
|
||||
"down": {"uv": [8.75, 7.25, 8.25, 7.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 7, 4],
|
||||
"to": [9, 9, 5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 7, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 8, 0.5, 8.5], "texture": "#0"},
|
||||
"east": {"uv": [8.25, 7.5, 8.5, 8], "texture": "#0"},
|
||||
"south": {"uv": [8, 0, 8.5, 0.5], "texture": "#0"},
|
||||
"west": {"uv": [7.75, 8.25, 8, 8.75], "texture": "#0"},
|
||||
"up": {"uv": [8.5, 8.5, 8, 8.25], "texture": "#0"},
|
||||
"down": {"uv": [8.75, 8, 8.25, 8.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 8, 3],
|
||||
"to": [9, 9, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 7, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 8.5, 0.5, 8.75], "texture": "#0"},
|
||||
"east": {"uv": [1.5, 9, 1.75, 9.25], "texture": "#0"},
|
||||
"south": {"uv": [8.5, 0, 9, 0.25], "texture": "#0"},
|
||||
"west": {"uv": [1.75, 9, 2, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [9, 0.5, 8.5, 0.25], "texture": "#0"},
|
||||
"down": {"uv": [3.25, 8.5, 2.75, 8.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 9, 2],
|
||||
"to": [9, 12, 3],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 9, 1]},
|
||||
"faces": {
|
||||
"north": {"uv": [4, 7, 4.5, 7.75], "texture": "#0"},
|
||||
"east": {"uv": [2.25, 8, 2.5, 8.75], "texture": "#0"},
|
||||
"south": {"uv": [4.5, 7, 5, 7.75], "texture": "#0"},
|
||||
"west": {"uv": [2.5, 8, 2.75, 8.75], "texture": "#0"},
|
||||
"up": {"uv": [9, 3, 8.5, 2.75], "texture": "#0"},
|
||||
"down": {"uv": [9, 3, 8.5, 3.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 12, 3],
|
||||
"to": [9, 13, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 12, 3]},
|
||||
"faces": {
|
||||
"north": {"uv": [3.25, 8.5, 3.75, 8.75], "texture": "#0"},
|
||||
"east": {"uv": [2, 9, 2.25, 9.25], "texture": "#0"},
|
||||
"south": {"uv": [8.5, 3.25, 9, 3.5], "texture": "#0"},
|
||||
"west": {"uv": [2.25, 9, 2.5, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [9, 3.75, 8.5, 3.5], "texture": "#0"},
|
||||
"down": {"uv": [9, 3.75, 8.5, 4], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 13, 4],
|
||||
"to": [9, 14, 5],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [4, 8.5, 4.5, 8.75], "texture": "#0"},
|
||||
"east": {"uv": [2.5, 9, 2.75, 9.25], "texture": "#0"},
|
||||
"south": {"uv": [8.5, 4, 9, 4.25], "texture": "#0"},
|
||||
"west": {"uv": [2.75, 9, 3, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [9, 4.5, 8.5, 4.25], "texture": "#0"},
|
||||
"down": {"uv": [5, 8.5, 4.5, 8.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 10, 5],
|
||||
"to": [9, 14, 6],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 10, 5]},
|
||||
"faces": {
|
||||
"north": {"uv": [5.5, 1.5, 6, 2.5], "texture": "#0"},
|
||||
"east": {"uv": [6.75, 7.25, 7, 8.25], "texture": "#0"},
|
||||
"south": {"uv": [7, 3.5, 7.5, 4.5], "texture": "#0"},
|
||||
"west": {"uv": [0.5, 8, 0.75, 9], "texture": "#0"},
|
||||
"up": {"uv": [9, 4.75, 8.5, 4.5], "texture": "#0"},
|
||||
"down": {"uv": [9, 4.75, 8.5, 5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 10, 6],
|
||||
"to": [9, 15, 7],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [6.5, 6, 7, 7.25], "texture": "#0"},
|
||||
"east": {"uv": [7, 5.75, 7.25, 7], "texture": "#0"},
|
||||
"south": {"uv": [5.5, 6.75, 6, 8], "texture": "#0"},
|
||||
"west": {"uv": [7, 7, 7.25, 8.25], "texture": "#0"},
|
||||
"up": {"uv": [5.5, 8.75, 5, 8.5], "texture": "#0"},
|
||||
"down": {"uv": [6, 8.5, 5.5, 8.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 10, 7],
|
||||
"to": [9, 15, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 7]},
|
||||
"faces": {
|
||||
"north": {"uv": [7, 0, 7.5, 1.25], "texture": "#0"},
|
||||
"east": {"uv": [7.25, 5.75, 7.5, 7], "texture": "#0"},
|
||||
"south": {"uv": [7, 1.25, 7.5, 2.5], "texture": "#0"},
|
||||
"west": {"uv": [6, 7.25, 6.25, 8.5], "texture": "#0"},
|
||||
"up": {"uv": [9, 8, 8.5, 7.75], "texture": "#0"},
|
||||
"down": {"uv": [8.5, 8.5, 8, 8.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 15, 6],
|
||||
"to": [9, 16, 7],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.5, 5.5, 9, 5.75], "texture": "#0"},
|
||||
"east": {"uv": [9, 2.75, 9.25, 3], "texture": "#0"},
|
||||
"south": {"uv": [8.5, 5.75, 9, 6], "texture": "#0"},
|
||||
"west": {"uv": [3, 9, 3.25, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [6.5, 8.75, 6, 8.5], "texture": "#0"},
|
||||
"down": {"uv": [9, 6, 8.5, 6.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 15, 13],
|
||||
"to": [9, 16, 14],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 13]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.5, 6.5, 9, 6.75], "texture": "#0"},
|
||||
"east": {"uv": [9, 3, 9.25, 3.25], "texture": "#0"},
|
||||
"south": {"uv": [8.5, 6.75, 9, 7], "texture": "#0"},
|
||||
"west": {"uv": [3.25, 9, 3.5, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [7.5, 8.75, 7, 8.5], "texture": "#0"},
|
||||
"down": {"uv": [9, 7.5, 8.5, 7.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 10, 8],
|
||||
"to": [9, 11, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 10, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.5, 8.25, 9, 8.5], "texture": "#0"},
|
||||
"east": {"uv": [9, 3.25, 9.25, 3.5], "texture": "#0"},
|
||||
"south": {"uv": [8.5, 8.5, 9, 8.75], "texture": "#0"},
|
||||
"west": {"uv": [3.5, 9, 3.75, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [0.5, 9, 0, 8.75], "texture": "#0"},
|
||||
"down": {"uv": [9.25, 0.5, 8.75, 0.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 14, 8],
|
||||
"to": [9, 15, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.75, 0.75, 9.25, 1], "texture": "#0"},
|
||||
"east": {"uv": [9, 3.5, 9.25, 3.75], "texture": "#0"},
|
||||
"south": {"uv": [8.75, 1, 9.25, 1.25], "texture": "#0"},
|
||||
"west": {"uv": [3.75, 9, 4, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [9.25, 1.5, 8.75, 1.25], "texture": "#0"},
|
||||
"down": {"uv": [9.25, 1.5, 8.75, 1.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 13, 8],
|
||||
"to": [9, 14, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.75, 1.75, 9.25, 2], "texture": "#0"},
|
||||
"east": {"uv": [9, 3.75, 9.25, 4], "texture": "#0"},
|
||||
"south": {"uv": [8.75, 2, 9.25, 2.25], "texture": "#0"},
|
||||
"west": {"uv": [4, 9, 4.25, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [2.75, 9, 2.25, 8.75], "texture": "#0"},
|
||||
"down": {"uv": [9.25, 2.25, 8.75, 2.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 15, 8],
|
||||
"to": [9, 16, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.75, 2.5, 9.25, 2.75], "texture": "#0"},
|
||||
"east": {"uv": [9, 4, 9.25, 4.25], "texture": "#0"},
|
||||
"south": {"uv": [2.75, 8.75, 3.25, 9], "texture": "#0"},
|
||||
"west": {"uv": [4.25, 9, 4.5, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [3.75, 9, 3.25, 8.75], "texture": "#0"},
|
||||
"down": {"uv": [4.25, 8.75, 3.75, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 15, 7],
|
||||
"to": [9, 16, 8],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 7]},
|
||||
"faces": {
|
||||
"north": {"uv": [4.25, 8.75, 4.75, 9], "texture": "#0"},
|
||||
"east": {"uv": [9, 4.25, 9.25, 4.5], "texture": "#0"},
|
||||
"south": {"uv": [4.75, 8.75, 5.25, 9], "texture": "#0"},
|
||||
"west": {"uv": [4.5, 9, 4.75, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [9.25, 5.25, 8.75, 5], "texture": "#0"},
|
||||
"down": {"uv": [5.75, 8.75, 5.25, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 15, 9],
|
||||
"to": [9, 16, 10],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 9]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.75, 5.25, 9.25, 5.5], "texture": "#0"},
|
||||
"east": {"uv": [9, 4.5, 9.25, 4.75], "texture": "#0"},
|
||||
"south": {"uv": [5.75, 8.75, 6.25, 9], "texture": "#0"},
|
||||
"west": {"uv": [4.75, 9, 5, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [6.75, 9, 6.25, 8.75], "texture": "#0"},
|
||||
"down": {"uv": [7.25, 8.75, 6.75, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 14, 9],
|
||||
"to": [9, 15, 10],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 9]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.75, 7, 9.25, 7.25], "texture": "#0"},
|
||||
"east": {"uv": [9, 4.75, 9.25, 5], "texture": "#0"},
|
||||
"south": {"uv": [7.25, 8.75, 7.75, 9], "texture": "#0"},
|
||||
"west": {"uv": [5, 9, 5.25, 9.25], "texture": "#0"},
|
||||
"up": {"uv": [9.25, 7.5, 8.75, 7.25], "texture": "#0"},
|
||||
"down": {"uv": [8.25, 8.75, 7.75, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 15, 10],
|
||||
"to": [9, 16, 13],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 10]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.75, 8, 9.25, 8.25], "texture": "#0"},
|
||||
"east": {"uv": [8, 2.5, 8.75, 2.75], "texture": "#0"},
|
||||
"south": {"uv": [8.25, 8.75, 8.75, 9], "texture": "#0"},
|
||||
"west": {"uv": [2.75, 8, 3.5, 8.25], "texture": "#0"},
|
||||
"up": {"uv": [5.5, 7.75, 5, 7], "texture": "#0"},
|
||||
"down": {"uv": [7.5, 5, 7, 5.75], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 16, 7],
|
||||
"to": [9, 17, 13],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 16, 7]},
|
||||
"faces": {
|
||||
"north": {"uv": [8.5, 6.25, 9, 6.5], "texture": "#0"},
|
||||
"east": {"uv": [7, 4.5, 8.5, 4.75], "texture": "#0"},
|
||||
"south": {"uv": [6.5, 8.5, 7, 8.75], "texture": "#0"},
|
||||
"west": {"uv": [7, 4.75, 8.5, 5], "texture": "#0"},
|
||||
"up": {"uv": [5, 7, 4.5, 5.5], "texture": "#0"},
|
||||
"down": {"uv": [5.5, 5.5, 5, 7], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 6, 6],
|
||||
"to": [7, 10, 10],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [5, 6, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [8, 0.5, 8.25, 1.5], "texture": "#0"},
|
||||
"east": {"uv": [4, 3.5, 5, 4.5], "texture": "#0"},
|
||||
"south": {"uv": [0.75, 8, 1, 9], "texture": "#0"},
|
||||
"west": {"uv": [4, 4.5, 5, 5.5], "texture": "#0"},
|
||||
"up": {"uv": [1.25, 9, 1, 8], "texture": "#0"},
|
||||
"down": {"uv": [1.5, 8, 1.25, 9], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [9, 6, 6],
|
||||
"to": [10, 10, 10],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [1.5, 8, 1.75, 9], "texture": "#0"},
|
||||
"east": {"uv": [5, 3.5, 6, 4.5], "texture": "#0"},
|
||||
"south": {"uv": [8, 1.5, 8.25, 2.5], "texture": "#0"},
|
||||
"west": {"uv": [5, 4.5, 6, 5.5], "texture": "#0"},
|
||||
"up": {"uv": [2, 9, 1.75, 8], "texture": "#0"},
|
||||
"down": {"uv": [2.25, 8, 2, 9], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "keeblarcraft:block/example_block"
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "keeblarcraft:block/example_block_ore"
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "keeblarcraft:block/example_statue"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "keeblarcraft:item/metaljacket_boots"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "keeblarcraft:item/metaljacket_chestplate"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "keeblarcraft:item/metaljacket_helmet"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "keeblarcraft:item/metaljacket_leggings"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 782 B |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 1012 B |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 791 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 782 B |
After Width: | Height: | Size: 269 B |
After Width: | Height: | Size: 287 B |
After Width: | Height: | Size: 263 B |
After Width: | Height: | Size: 267 B |
@ -0,0 +1,6 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"keeblarcraft:example_block_ore"
|
||||
]
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "keeblarcraft:example_block"
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "keeblarcraft:example_block_ore"
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "misc",
|
||||
"pattern": [
|
||||
" # ",
|
||||
"###",
|
||||
" # "
|
||||
],
|
||||
"key": {
|
||||
"#": {
|
||||
"item": "keeblarcraft:example_block_ore"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "keeblarcraft:example_block",
|
||||
"count": 8
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "misc",
|
||||
"pattern": [
|
||||
"#C#",
|
||||
"###",
|
||||
"#C#"
|
||||
],
|
||||
"key": {
|
||||
"#": {
|
||||
"item": "keeblarcraft:example_block"
|
||||
},
|
||||
"C": {
|
||||
"item": "minecraft:coal"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "keeblarcraft:example_block",
|
||||
"count": 8
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"category": "building",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "keeblarcraft:example_block"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "keeblarcraft:example_block",
|
||||
"count": 1
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"keeblarcraft:example_block",
|
||||
"keeblarcraft:example_block_ore"
|
||||
]
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"keeblarcraft:example_block"
|
||||
]
|
||||
}
|
35
src/main/resources/fabric.mod.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "keeblarcraft",
|
||||
"version": "0.1",
|
||||
"name": "keeblarcraft",
|
||||
"description": "My everything mod",
|
||||
"authors": [
|
||||
"Jkibbels"
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "https://fabricmc.net/",
|
||||
"sources": "https://github.com/FabricMC/fabric-example-mod"
|
||||
},
|
||||
"license": "CC0-1.0",
|
||||
"icon": "assets/keeblarcraft/icon.png",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"jesse.keeblarcraft.Keeblarcraft"
|
||||
],
|
||||
"client": [
|
||||
"jesse.keeblarcraft.KeeblarcraftClient"
|
||||
]
|
||||
},
|
||||
"depends": {
|
||||
"fabricloader": ">=0.15.11",
|
||||
"minecraft": "~1.20",
|
||||
"java": ">=17",
|
||||
"fabric-api": "*",
|
||||
"fabric-key-binding-api-v1": "*"
|
||||
},
|
||||
"suggests": {
|
||||
"another-mod": "*"
|
||||
}
|
||||
}
|