Compare commits
44 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
79600e942f | ||
![]() |
21ba86bbec | ||
![]() |
4e080ad392 | ||
64236d94b6 | |||
![]() |
415983edca | ||
![]() |
e164a489b2 | ||
![]() |
cb91f722e9 | ||
![]() |
2d926310cf | ||
![]() |
4becbd8f45 | ||
![]() |
5911c7c775 | ||
![]() |
bf3b1f6ed2 | ||
![]() |
a36ef1c8f1 | ||
![]() |
0ed8838de0 | ||
![]() |
fa5bc741ec | ||
![]() |
7d5fbca603 | ||
![]() |
c8e379e564 | ||
![]() |
7efeb689cb | ||
![]() |
74722b465a | ||
![]() |
6d14d47e0b | ||
![]() |
d274810ca4 | ||
![]() |
bcbd481fcf | ||
![]() |
f22da92cab | ||
![]() |
f6af706a60 | ||
![]() |
cde06d56c0 | ||
![]() |
ef49519368 | ||
![]() |
82ee25ee97 | ||
![]() |
79a4738bbc | ||
![]() |
4c3e9c65aa | ||
![]() |
20e0325493 | ||
![]() |
a7f8504c2c | ||
![]() |
b6b73d96e8 | ||
![]() |
c9473c59a1 | ||
![]() |
cb9c3c124e | ||
![]() |
f7126a0555 | ||
![]() |
30ec133358 | ||
![]() |
b4234d4b6b | ||
![]() |
b048e34eda | ||
![]() |
afbb2533e7 | ||
![]() |
8ece2f2d45 | ||
![]() |
3abdf9b184 | ||
![]() |
a42d196c3c | ||
![]() |
87afc5c8ab | ||
![]() |
d8a6b7ecd9 | ||
![]() |
5cae7ec313 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,6 +5,8 @@ build/
|
|||||||
out/
|
out/
|
||||||
classes/
|
classes/
|
||||||
|
|
||||||
|
remappedSrc/
|
||||||
|
|
||||||
# eclipse
|
# eclipse
|
||||||
|
|
||||||
*.launch
|
*.launch
|
||||||
|
4
Doxyfile
4
Doxyfile
@ -32,13 +32,13 @@ DOXYFILE_ENCODING = UTF-8
|
|||||||
# title of most generated pages and in a few other places.
|
# title of most generated pages and in a few other places.
|
||||||
# The default value is: My Project.
|
# The default value is: My Project.
|
||||||
|
|
||||||
PROJECT_NAME = "My Project"
|
PROJECT_NAME = "Keeblarcraft"
|
||||||
|
|
||||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER =
|
PROJECT_NUMBER = 1.0
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
|
19
build.gradle
19
build.gradle
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version '1.7-SNAPSHOT'
|
id 'fabric-loom' version '1.9-SNAPSHOT'
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10,6 +10,10 @@ base {
|
|||||||
archivesName = project.archives_base_name
|
archivesName = project.archives_base_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fabricApi {
|
||||||
|
configureDataGeneration()
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// Add repositories to retrieve artifacts from in here.
|
// Add repositories to retrieve artifacts from in here.
|
||||||
// You should only use this when depending on other mods because
|
// You should only use this when depending on other mods because
|
||||||
@ -22,6 +26,8 @@ repositories {
|
|||||||
// includeGroup("cc.tweaked")
|
// includeGroup("cc.tweaked")
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
maven { url = "https://maven.kyrptonaught.dev" }
|
||||||
|
maven { url = 'https://maven.minecraftforge.net/' } // for Terrablender
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
@ -33,7 +39,6 @@ loom {
|
|||||||
sourceSet sourceSets.client
|
sourceSet sourceSets.client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -42,10 +47,16 @@ dependencies {
|
|||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
|
|
||||||
|
// modImplementation "mysql:mysql-connector-java:9.1.0"
|
||||||
|
include(implementation("mysql:mysql-connector-java:8.0.27"))
|
||||||
|
|
||||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||||
//modCompileOnly "cc.tweaked:cc-tweaked-1.20-fabric-api:1.105.0"
|
//modCompileOnly "cc.tweaked:cc-tweaked-1.20-fabric-api:1.105.0"
|
||||||
//modRuntimeOnly "cc.tweaked:cc-tweaked-1.20-fabric-api:1.105.0"
|
//modRuntimeOnly "cc.tweaked:cc-tweaked-1.20-fabric-api:1.105.0"
|
||||||
|
modImplementation 'net.kyrptonaught:customportalapi:0.0.1-beta64.5-1.20.2'
|
||||||
|
include 'net.kyrptonaught:customportalapi:0.0.1-beta64.5-1.20.2'
|
||||||
|
modImplementation 'com.github.glitchfiend:TerraBlender-fabric:1.20.2-3.2.0.14'
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
@ -64,10 +75,10 @@ java {
|
|||||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
||||||
// if it is present.
|
// if it is present.
|
||||||
// If you remove this line, sources will not be generated.
|
// If you remove this line, sources will not be generated.
|
||||||
withSourcesJar()
|
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
|
||||||
|
withSourcesJar()
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
# Done to increase the memory available to gradle.
|
# Done to increase the memory available to gradle.
|
||||||
org.gradle.jvmargs=-Xmx1G
|
org.gradle.jvmargs=-Xmx2G
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://fabricmc.net/develop
|
# check these on https://fabricmc.net/develop
|
||||||
minecraft_version=1.20
|
minecraft_version=1.20.2
|
||||||
yarn_mappings=1.20+build.1
|
yarn_mappings=1.20.2+build.4
|
||||||
loader_version=0.15.11
|
loader_version=0.16.9
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=0.0.1
|
mod_version=1.0.0
|
||||||
maven_group=jesse.keeblarcraft
|
maven_group=jesse.keeblarcraft
|
||||||
archives_base_name=keeblarcraft
|
archives_base_name=keeblarcraft
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
fabric_version=0.83.0+1.20
|
fabric_version=0.91.6+1.20.2
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
5
gradlew
vendored
5
gradlew
vendored
@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@ -84,7 +86,8 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# 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
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||||
|
' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
2
gradlew.bat
vendored
2
gradlew.bat
vendored
@ -13,6 +13,8 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
rm ~/.minecraft/mods/keeblarcraft* # What else could be named this? Really now?
|
rm ~/.minecraft/mods/keeblarcraft* # What else could be named this? Really now?
|
||||||
cp build/devlibs/*sources.jar ~/.minecraft/mods
|
cp build/libs/keeblarcraft-0.0.1.jar ~/.minecraft/mods
|
||||||
|
cp build/libs/keeblarcraft-0.0.1.jar run/mods
|
||||||
echo Moved minecraft to mods dir
|
echo Moved minecraft to mods dir
|
BIN
mysql-connector-java-8.0.27.jar
Normal file
BIN
mysql-connector-java-8.0.27.jar
Normal file
Binary file not shown.
188
run.sh
Executable file
188
run.sh
Executable file
@ -0,0 +1,188 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BASH_PATH=$(which bash)
|
||||||
|
|
||||||
|
#########
|
||||||
|
# GLOBALS
|
||||||
|
#########
|
||||||
|
REPO_TOP=$(dirname $(readlink -f "${BASH_SOURCE[0]}"))
|
||||||
|
SCRIPT_NAME=$(basename $0)
|
||||||
|
SERVER_MODE=0 # 1=true, 0=false
|
||||||
|
CLIENT_MODE=0 # 1=true, 0=false
|
||||||
|
LOG_LEVEL=1
|
||||||
|
BUILD_PATH="build"
|
||||||
|
RUN_PATH="run"
|
||||||
|
RESET_ALL=0
|
||||||
|
RUN_ALL=1
|
||||||
|
GRADLEW_PATH=${REPO_TOP}/gradlew
|
||||||
|
declare SERVER_PID
|
||||||
|
declare CLIENT_PID
|
||||||
|
|
||||||
|
# $1 is text level
|
||||||
|
# LEVELS:
|
||||||
|
# 1: Info
|
||||||
|
# 2: Debug
|
||||||
|
# 3: Warning
|
||||||
|
function TermWrite() {
|
||||||
|
textLevel=$1
|
||||||
|
text="${2}"
|
||||||
|
prefix="[\033[34m"${SCRIPT_NAME}"\033[0m]: "
|
||||||
|
|
||||||
|
if [[ "${textLevel}" == "2" ]]; then
|
||||||
|
prefix="[\033[33m"${SCRIPT_NAME}"\033[0m]:"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${textLevel}" == "3" ]]; then
|
||||||
|
prefix="[\033[31m"${SCRIPT_NAME}"\033[0m]:"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${LOG_LEVEL} -ge ${textLevel} ]]; then
|
||||||
|
printf "${prefix} ${text}\n"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function help() {
|
||||||
|
echo -e "Help for running $0:"
|
||||||
|
echo -e " -s: Build and run the program in server mode"
|
||||||
|
echo -e " -c: Build and run the program in client mode"
|
||||||
|
echo -e " -l [1-3]: Turn up the logging level to see more messages (default: 1)"
|
||||||
|
echo -e " -g <path>: The path to the gradlew executable (default: $(pwd)/gradlew)"
|
||||||
|
echo -e " -r: Reset everything. This will nuke the previous install area and re-build EVERYTHING from scratch"
|
||||||
|
echo -e " -b <path>: Specify the build area (default is cur dir $(pwd)/build)"
|
||||||
|
echo -e " -b2 <path>: Specify the run area (default is cur dir $(pwd)/run)"
|
||||||
|
echo -e " -a: Run everything at once (default option if nothing specified)"
|
||||||
|
echo -e " -h: Bring up this help message"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ExitAll() {
|
||||||
|
TermWrite 1 "Cleaning up..."
|
||||||
|
if [ ! -z $SERVER_PID ]; then
|
||||||
|
TermWrite 1 "Killing PID $SERVER_PID"
|
||||||
|
kill -9 $SERVER_PID
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z $CLIENT_PID ]; then
|
||||||
|
TermWrite 1 "Killing PID $CLIENT_PID"
|
||||||
|
kill -9 $CLIENT_PID
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Close with exit code 1 because a clean close isn't guarenteed with this
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Capture CTRL+C event into ExitAll function
|
||||||
|
trap ExitAll INT
|
||||||
|
|
||||||
|
while getopts ":schl:g:r:b:b2:" opt; do
|
||||||
|
case ${opt} in
|
||||||
|
s)
|
||||||
|
TermWrite 2 "SERVER MODE ENABLED"
|
||||||
|
SERVER_MODE=1
|
||||||
|
RUN_ALL=0
|
||||||
|
;;
|
||||||
|
c)
|
||||||
|
TermWrite 2 "CLIENT MODE ENABLED"
|
||||||
|
CLIENT_MODE=1
|
||||||
|
RUN_ALL=0
|
||||||
|
;;
|
||||||
|
h)
|
||||||
|
help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
l)
|
||||||
|
if [[ $OPTARG =~ [1-3] ]]; then
|
||||||
|
LOG_LEVEL=$OPTARG
|
||||||
|
TermWrite 2 "LOG LEVEL SET TO $LOG_LEVEL"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
g)
|
||||||
|
if [[ -f "${OPTARG}" ]]; then
|
||||||
|
TermWrite 2 "Set gradlew path to $OPTARG"
|
||||||
|
GRADLEW_PATH="$OPTARG"
|
||||||
|
else
|
||||||
|
TermWrite 3 "The path you gave to the gradlew executable (${OPTARG}) does not appear to exist. Please check the path!"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
r)
|
||||||
|
RESET_ALL=1
|
||||||
|
;;
|
||||||
|
b)
|
||||||
|
if [[ -f "${OPTARG}" ]]; then
|
||||||
|
TermWrite 2 "Setting build directory to: ${OPTARG}"
|
||||||
|
BUILD_PATH="${OPTARG}"
|
||||||
|
else
|
||||||
|
TermWrite 3 "The specified path (${OPTARG}) does not appear to exist. Please check the path!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
b1)
|
||||||
|
if [[ "${OPTARG}" ]]; then
|
||||||
|
TermWrite 2 "Setting run directory to: ${OPTARG}"
|
||||||
|
RUN_PATH="${OPTARG}"
|
||||||
|
else
|
||||||
|
TermWrite 3 "The specified path (${OPTARG}) does not appear to exist. Please check the path!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
?)
|
||||||
|
help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
TermWrite 2 "CURRENT DIRECTORY: $(pwd)"
|
||||||
|
TermWrite 2 "SERVER MODE? ${SERVER_MODE}"
|
||||||
|
TermWrite 2 "CLIENT MODE? ${CLIENT_MODE}"
|
||||||
|
|
||||||
|
# If the user specified they wish to wipe everything before we begin; then let us do so.
|
||||||
|
if [[ $RESET_ALL -eq 1 ]]; then
|
||||||
|
TermWrite 1 "Removing $BUILD_PATH"
|
||||||
|
rm -rf $BUILD_PATH
|
||||||
|
TermWrite 1 "Removing $RUN_PATH"
|
||||||
|
rm -rf $RUN_PATH
|
||||||
|
|
||||||
|
TermWrite 1 "Running build..."
|
||||||
|
$BASH_PATH $GRADLEW_PATH build
|
||||||
|
TermWrite 1 "Running datagen..."
|
||||||
|
$BASH_PATH $GRADLEW_PATH runDatagen
|
||||||
|
TermWrite 1 "All completed!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $RUN_ALL -eq 0 ]]; then
|
||||||
|
if [[ $SERVER_MODE -eq 1 ]]; then
|
||||||
|
TermWrite 1 "Running ./gradlew build"
|
||||||
|
$BASH_PATH $GRADLEW_PATH build
|
||||||
|
TermWrite 1 "Running ./gradlew runServer"
|
||||||
|
$BASH_PATH $GRADLEW_PATH runServer &
|
||||||
|
SERVER_PID=$!
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $CLIENT_MODE -eq 1 ]]; then
|
||||||
|
TermWrite 1 "Running ./gradlew build"
|
||||||
|
$BASH_PATH $GRADLEW_PATH build
|
||||||
|
TermWrite 1 "Running ./gradlew runClient"
|
||||||
|
$BASH_PATH $GRADLEW_PATH runClient
|
||||||
|
CLIENT_PID=$!
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Run everything
|
||||||
|
TermWrite 1 "Running both client and server processes..."
|
||||||
|
$BASH_PATH $GRADLEW_PATH clean
|
||||||
|
$BASH_PATH $GRADLEW_PATH build
|
||||||
|
$BASH_PATH $GRADLEW_PATH runClient &
|
||||||
|
CLIENT_PID=$!
|
||||||
|
# We do not run the server in the background so the player may run commands in the server terminal
|
||||||
|
$BASH_PATH $GRADLEW_PATH runServer
|
||||||
|
SERVER_PID=$!
|
||||||
|
|
||||||
|
TermWrite 1 "Server and client processes started"
|
||||||
|
fi
|
||||||
|
|
||||||
|
TermWrite 1 "Finished running gradlew command with exit code $?"
|
||||||
|
|
||||||
|
# We wait and hang here until BOTH background processes finish (or until CTRL+C event)
|
||||||
|
wait
|
||||||
|
|
||||||
|
# Clean up and leave
|
||||||
|
ExitAll
|
@ -0,0 +1,9 @@
|
|||||||
|
package jesse.keeblarcraft.ClientHelpers;
|
||||||
|
|
||||||
|
public class Helper {
|
||||||
|
public static boolean WithinBounds(double x, double y, double w, double h, double clickX, double clickY) {
|
||||||
|
// System.out.println("Mouse click X Y: " + clickX + " " + clickY);
|
||||||
|
// System.out.println("Rectangle X Y W H: " + x + " " + y + " " + w + " " + h);
|
||||||
|
return (clickX >= x) && (clickX <= x + w) && (clickY >= y) && (clickY <= y + h);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package jesse.keeblarcraft.Entities;
|
||||||
|
|
||||||
|
import net.minecraft.client.model.*;
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.render.entity.model.EntityModel;
|
||||||
|
import net.minecraft.client.render.entity.model.EntityModelPartNames;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import org.spongepowered.include.com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
public class ShopKeeperModel extends EntityModel<ShopKeeper> {
|
||||||
|
private final ModelPart base;
|
||||||
|
public ShopKeeperModel(ModelPart modelPart) {
|
||||||
|
this.base = modelPart.getChild(EntityModelPartNames.CUBE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TexturedModelData getTexturedModelData() {
|
||||||
|
ModelData modelData = new ModelData();
|
||||||
|
ModelPartData modelPartData = modelData.getRoot();
|
||||||
|
modelPartData.addChild(EntityModelPartNames.CUBE, ModelPartBuilder.create().uv(0, 0).cuboid(-6F, 12F, -6F, 12F, 12F, 12F),
|
||||||
|
ModelTransform.pivot(0F, 0F, 0F));
|
||||||
|
return TexturedModelData.of(modelData, 64, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAngles(ShopKeeper entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||||
|
ImmutableList.of(this.base).forEach((modelRenderer) -> {
|
||||||
|
modelRenderer.render(matrices, vertices, light, overlay, red, green, blue, alpha);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package jesse.keeblarcraft.Entities;
|
||||||
|
|
||||||
|
import net.minecraft.client.render.entity.EntityRendererFactory;
|
||||||
|
import net.minecraft.client.render.entity.VillagerEntityRenderer;
|
||||||
|
|
||||||
|
public class ShopKeeperRenderer extends VillagerEntityRenderer {
|
||||||
|
public ShopKeeperRenderer(EntityRendererFactory.Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,27 @@
|
|||||||
package jesse.keeblarcraft;
|
package jesse.keeblarcraft;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Entities.EntityRegistration;
|
||||||
|
import jesse.keeblarcraft.Entities.ShopKeeperModel;
|
||||||
import jesse.keeblarcraft.gui.ClientHandlers;
|
import jesse.keeblarcraft.gui.ClientHandlers;
|
||||||
import jesse.keeblarcraft.gui.ScreenManager;
|
|
||||||
import jesse.keeblarcraft.gui.widgets.TreeWidget;
|
|
||||||
import jesse.keeblarcraft.Shortcuts.ShortcutManager;
|
import jesse.keeblarcraft.Shortcuts.ShortcutManager;
|
||||||
|
import jesse.keeblarcraft.Entities.ShopKeeperRenderer;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry;
|
||||||
|
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
|
||||||
|
import net.minecraft.client.render.entity.model.EntityModelLayer;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
|
||||||
public class KeeblarcraftClient implements ClientModInitializer {
|
public class KeeblarcraftClient implements ClientModInitializer {
|
||||||
|
public static final EntityModelLayer SHOP_KEEPER_LAYER = new EntityModelLayer(new Identifier("textures/entity/villager/villager.png"), "VILLAGE_ENTITY_MODEL_LAYER");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
ShortcutManager.RegisterKeybinds();
|
ShortcutManager.RegisterKeybinds();
|
||||||
ClientHandlers.RegisterHandlers();
|
ClientHandlers.RegisterHandlers();
|
||||||
|
|
||||||
ScreenManager.GetInstance();
|
EntityRendererRegistry.register(EntityRegistration.SHOP_KEEPER_ENTITY_TYPE, ShopKeeperRenderer::new);
|
||||||
ScreenManager.AddWidget(TreeWidget.class, 10);
|
EntityModelLayerRegistry.registerModelLayer(SHOP_KEEPER_LAYER, ShopKeeperModel::getTexturedModelData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,6 @@ package jesse.keeblarcraft.Shortcuts;
|
|||||||
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
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.event.lifecycle.v1.ClientTickEvents;
|
||||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
@ -25,7 +23,6 @@ public class ShortcutManager {
|
|||||||
private static KeyBinding skillTreeShortcut;
|
private static KeyBinding skillTreeShortcut;
|
||||||
private static KeyBinding globalConfig;
|
private static KeyBinding globalConfig;
|
||||||
private static Boolean toggleTreeGui = true; // Initialized to true for first time pressing keybind to actually display gui
|
private static Boolean toggleTreeGui = true; // Initialized to true for first time pressing keybind to actually display gui
|
||||||
// private static ScreenManager treeGui = null;
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
/// @fn RegisterKeybinds
|
/// @fn RegisterKeybinds
|
||||||
@ -83,10 +80,10 @@ public class ShortcutManager {
|
|||||||
// treeGui = new ScreenManager(Keeblarcraft.TREE_HANDLER.create(0, client.player.getInventory()), client.player.getInventory(), Text.of("Test"));
|
// 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
|
// 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();
|
// ScreenManager treeGui = ScreenManager.GetInstance();
|
||||||
treeGui.AddParent(currentScreen);
|
// treeGui.AddParent(currentScreen);
|
||||||
|
|
||||||
MinecraftClient.getInstance().setScreen(treeGui);
|
// MinecraftClient.getInstance().setScreen(treeGui);
|
||||||
|
|
||||||
// toggleTreeGui intentionally never bit-flipped to false as a slight implementation bug exists such that pressing the keybind again
|
// 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
|
// does NOT call this callback function until the previous screen is CLOSED (which is why this isn't resource leaking...). This will
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
package jesse.keeblarcraft.gui;
|
package jesse.keeblarcraft.gui;
|
||||||
|
|
||||||
import jesse.keeblarcraft.Keeblarcraft;
|
import jesse.keeblarcraft.GuiMgr.ScreenHandlerRegistration;
|
||||||
|
import jesse.keeblarcraft.gui.FactionBlockGUI.FactionBlockScreen;
|
||||||
|
import jesse.keeblarcraft.gui.ShopKeeperGUI.ShopKeeperMenu;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreens;
|
import net.minecraft.client.gui.screen.ingame.HandledScreens;
|
||||||
|
|
||||||
public class ClientHandlers {
|
public class ClientHandlers {
|
||||||
public static void RegisterHandlers() {
|
public static void RegisterHandlers() {
|
||||||
System.out.println("Registering tree handler screen");
|
System.out.println("Registering tree handler screen");
|
||||||
HandledScreens.register(Keeblarcraft.TREE_HANDLER, ScreenManager::new);
|
// HandledScreens.register(Keeblarcraft.TREE_HANDLER, ScreenManager::new);
|
||||||
|
HandledScreens.register(ScreenHandlerRegistration.FACTION_BLOCK_SCREEN_HANDLER, FactionBlockScreen::new);
|
||||||
|
HandledScreens.register(ScreenHandlerRegistration.SHOP_KEEPER_HANDLER_SCREEN_HANDLER_TYPE, ShopKeeperMenu::new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
package jesse.keeblarcraft.gui.FactionBlockGUI;
|
||||||
|
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.GuiMgr.Factions.FactionBlockScreenHandler;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class FactionBlockScreen extends HandledScreen<FactionBlockScreenHandler> {
|
||||||
|
// This is a placeholder image until an actual one is drawn
|
||||||
|
private static final Identifier TEXTURE = new Identifier(Keeblarcraft.MOD_ID, "textures/gui/faction_block_menu.png");
|
||||||
|
|
||||||
|
public FactionBlockScreen(FactionBlockScreenHandler handler, PlayerInventory inventory, Text title) {
|
||||||
|
super(handler, inventory, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
titleY = 1000; //begone from screen
|
||||||
|
playerInventoryTitleY = 1000; //begone from screen
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionTexProgram);
|
||||||
|
RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
|
||||||
|
RenderSystem.setShaderTexture(0, TEXTURE);
|
||||||
|
|
||||||
|
this.backgroundHeight = 256;
|
||||||
|
this.backgroundWidth = 256;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
|
renderBackground(context, mouseX, mouseY, delta);
|
||||||
|
super.render(context, mouseX, mouseY, delta);
|
||||||
|
drawMouseoverTooltip(context, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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);
|
|
||||||
}
|
|
@ -0,0 +1,72 @@
|
|||||||
|
package jesse.keeblarcraft.gui.Generics;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
||||||
|
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
abstract public class ClickableLayer extends ClickableWidget {
|
||||||
|
private final Identifier texture;
|
||||||
|
private final Text layerName;
|
||||||
|
private final List<ClickableLayer> subLayers = new ArrayList<>();
|
||||||
|
private final Map<String, Boolean> drawSlots = new HashMap<>(); // layerName is used as menu name for the screen handler
|
||||||
|
|
||||||
|
protected abstract void appendClickableNarrations(NarrationMessageBuilder builder);
|
||||||
|
|
||||||
|
public ClickableLayer(Identifier texture, Text layerName, int width, int height, int startX, int startY) {
|
||||||
|
super(startX, startY, width, height, Text.empty());
|
||||||
|
this.texture = texture;
|
||||||
|
this.layerName = layerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AddSubLayer(ClickableLayer newLayer) {
|
||||||
|
subLayers.add(newLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ClearSubLayers() {
|
||||||
|
this.subLayers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ClickableLayer> GetSubLayers() {
|
||||||
|
return this.subLayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Boolean> GetDrawableSlots() {
|
||||||
|
return this.drawSlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddDrawableSlotByName(String slotName, boolean toggled) {
|
||||||
|
this.drawSlots.put(slotName, toggled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearDrawableSlots() {
|
||||||
|
for (Map.Entry<String, Boolean> entry : this.drawSlots.entrySet()) {
|
||||||
|
entry.setValue(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will be called every draw frame
|
||||||
|
public void UpdateSubLayers() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderButton(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
|
context.drawTexture(this.GetTexture(), this.getX(), this.getY(), 0, 0, this.getWidth(), this.getHeight(), this.getWidth(), this.getHeight());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Identifier GetTexture() {
|
||||||
|
return this.texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Text GetLayerName() {
|
||||||
|
return this.layerName;
|
||||||
|
}
|
||||||
|
}
|
@ -1,381 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,40 @@
|
|||||||
|
package jesse.keeblarcraft.gui.ShopKeeperGUI;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.gui.Generics.ClickableLayer;
|
||||||
|
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class NewItemButton extends ClickableLayer {
|
||||||
|
private static final Identifier NEW_ITEM_MENU = new Identifier(Keeblarcraft.MOD_ID, "textures/gui/shopkeeper_item_slot.jpeg");
|
||||||
|
private static NewItemMenu newItemMenu;
|
||||||
|
|
||||||
|
public NewItemButton(Identifier texture, Text layerName, int width, int height, int startX, int startY) {
|
||||||
|
super(texture, layerName, width, height, startX, startY);
|
||||||
|
|
||||||
|
// These values may be temporary
|
||||||
|
newItemMenu = new NewItemMenu(NEW_ITEM_MENU, Text.of("add_item_menu"), 32, 24, this.getX() + 20, this.getY() + 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(double x, double y) {
|
||||||
|
// Toggle the menu sub layer to be on if it was clicked. @See UpdateSubLayers for when it gets closed
|
||||||
|
System.out.println("Status of new item menu: " + newItemMenu.IsOpen());
|
||||||
|
if (!newItemMenu.IsOpen()) {
|
||||||
|
System.out.println("Adding new item menu and telling it to open");
|
||||||
|
this.AddSubLayer(newItemMenu);
|
||||||
|
newItemMenu.OpenMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void UpdateSubLayers() {
|
||||||
|
if (!newItemMenu.IsOpen()) {
|
||||||
|
this.ClearSubLayers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendClickableNarrations(NarrationMessageBuilder builder) {}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package jesse.keeblarcraft.gui.ShopKeeperGUI;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ClientHelpers.Helper;
|
||||||
|
import jesse.keeblarcraft.gui.Generics.ClickableLayer;
|
||||||
|
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class NewItemMenu extends ClickableLayer {
|
||||||
|
private boolean isOpen = false;
|
||||||
|
public NewItemMenu(Identifier texture, Text layerName, int width, int height, int startX, int startY) {
|
||||||
|
super(texture, layerName, width, height, startX, startY);
|
||||||
|
// System.out.println("Item menu created at coordinates X Y: " + this.getX() + " " + this.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseMenu() {
|
||||||
|
this.isOpen = false;
|
||||||
|
this.visible = false;
|
||||||
|
this.ClearDrawableSlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenMenu() {
|
||||||
|
this.visible = true;
|
||||||
|
this.isOpen = true;
|
||||||
|
this.AddDrawableSlotByName("add_item_slot", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean IsOpen() {
|
||||||
|
return this.isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(double x, double y) {
|
||||||
|
// Check to see if user clicked the 'x' area (mark closed in case)
|
||||||
|
// TODO: The coordinates for the 'X' button aren't known at the moment. For now just mark
|
||||||
|
// TODO: top right of the image with a 5 pixel buffer
|
||||||
|
if (this.visible && Helper.WithinBounds((this.getX() + this.getWidth() - 5), this.getY(), 5, 5, x, y)) {
|
||||||
|
System.out.println("User clicked fake 'X' button");
|
||||||
|
// this.isOpen = false;
|
||||||
|
this.CloseMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendClickableNarrations(NarrationMessageBuilder builder) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
package jesse.keeblarcraft.gui.ShopKeeperGUI;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.GuiMgr.ShopKeeper.ShopKeeperHandler;
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.ClientHelpers.Helper;
|
||||||
|
import jesse.keeblarcraft.gui.Generics.ClickableLayer;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ShopKeeperMenu extends HandledScreen<ShopKeeperHandler> {
|
||||||
|
private static final Identifier MENU_TEXTURE = new Identifier(Keeblarcraft.MOD_ID, "textures/gui/shopkeeper_gui.jpeg");
|
||||||
|
private static final Identifier ADD_BUTTON = new Identifier(Keeblarcraft.MOD_ID, "textures/gui/shopkeeper_add_icon.jpeg");
|
||||||
|
private static final Identifier NEW_ITEM_MENU = new Identifier(Keeblarcraft.MOD_ID, "textures/gui/shopkeeper_item_slot.jpeg");
|
||||||
|
private int x = 0;
|
||||||
|
private int y = 0;
|
||||||
|
private final List<ClickableLayer> layers = new ArrayList<>();
|
||||||
|
|
||||||
|
public ShopKeeperMenu(ShopKeeperHandler handler, PlayerInventory inventory, Text title) {
|
||||||
|
super(handler, inventory, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
titleY = 1000; //begone from screen
|
||||||
|
playerInventoryTitleY = 1000; //begone from screen
|
||||||
|
|
||||||
|
// Set the main shop keeping menu variables here
|
||||||
|
this.backgroundWidth = 256;
|
||||||
|
this.backgroundHeight = 256;
|
||||||
|
this.x = (width - backgroundWidth) / 2;
|
||||||
|
this.y = (height - backgroundHeight) / 2;
|
||||||
|
|
||||||
|
// Add all layers below
|
||||||
|
AddNewButton(ADD_BUTTON, Text.of("ADD ITEM BUTTON"), x, y, 64, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {
|
||||||
|
// Draw the menu texture first
|
||||||
|
// context.drawTexture(MENU_TEXTURE, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight);
|
||||||
|
context.drawTexture(MENU_TEXTURE, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight, this.backgroundWidth, this.backgroundHeight);
|
||||||
|
// context.drawTexture(NEW_ITEM_MENU, this.x, this.y, 0, 0, 32, 24);
|
||||||
|
// context.drawTexture(NEW_ITEM_MENU, this.x, this.y, 0, 0, 32, 24, 32, 24);
|
||||||
|
|
||||||
|
// this.getScreenHandler().showSlot("new_item", "add_item_slot");
|
||||||
|
|
||||||
|
for (ClickableLayer layer : layers) {
|
||||||
|
layer.renderButton(context, mouseX, mouseY, delta);
|
||||||
|
ToggleSlots(layer.GetLayerName().getString(), layer.GetDrawableSlots());
|
||||||
|
|
||||||
|
for (ClickableLayer subLayer : layer.GetSubLayers()) {
|
||||||
|
subLayer.renderButton(context, mouseX, mouseY, delta);
|
||||||
|
ToggleSlots(subLayer.GetLayerName().getString(), subLayer.GetDrawableSlots());
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only notify the parent to update sub layers. It must manage its own sub layers
|
||||||
|
layer.UpdateSubLayers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleSlots(String menuName, Map<String, Boolean> slotNames) {
|
||||||
|
for (Map.Entry<String, Boolean> slot : slotNames.entrySet()) {
|
||||||
|
if (slot.getValue()) {
|
||||||
|
System.out.println("Attempting to turn slot " + slot.getKey() + " to value " + slot.getValue());
|
||||||
|
this.getScreenHandler().showSlot(menuName, slot.getKey());
|
||||||
|
} else {
|
||||||
|
System.out.println("Attempting to turn slot " + slot.getKey() + " to value " + slot.getValue());
|
||||||
|
this.getScreenHandler().hideSlot(menuName, slot.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes an image and adds it to the background draw list and saves coordinates to return to a callback if it is clicked
|
||||||
|
private void AddNewButton(Identifier iconId, Text layerName, int drawX, int drawY, int imgWidth, int imgHeight) {
|
||||||
|
layers.add(new NewItemButton(iconId, layerName, imgWidth, imgHeight, drawX, drawY));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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!
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||||
|
for (ClickableLayer layer : layers) {
|
||||||
|
// Check main layer first
|
||||||
|
if (Helper.WithinBounds(layer.getX(), layer.getY(), layer.getWidth(), layer.getHeight(), mouseX, mouseY)) {
|
||||||
|
layer.mouseClicked(mouseX, mouseY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ClickableLayer subLayer : layer.GetSubLayers()) {
|
||||||
|
|
||||||
|
if (subLayer.visible && Helper.WithinBounds(subLayer.getX(), subLayer.getY(), subLayer.getWidth(), subLayer.getHeight(), mouseX, mouseY)) {
|
||||||
|
subLayer.mouseClicked(mouseX, mouseY, button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a click point is within the context of a square (square = x, y, w, h)
|
||||||
|
// public static boolean WithinBounds(double x, double y, double w, double h, double clickX, double clickY) {
|
||||||
|
//// System.out.println("Mouse click X Y: " + clickX + " " + clickY);
|
||||||
|
//// System.out.println("Rectangle X Y W H: " + x + " " + y + " " + w + " " + h);
|
||||||
|
// return (clickX >= x) && (clickX <= x + w) && (clickY >= y) && (clickY <= y + h);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
|
renderBackground(context, mouseX, mouseY, delta);
|
||||||
|
super.render(context, mouseX, mouseY, delta);
|
||||||
|
drawMouseoverTooltip(context, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,25 @@
|
|||||||
|
package jesse.keeblarcraft.mixin;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.sugar.Local;
|
||||||
|
import jesse.keeblarcraft.GuiMgr.ShopKeeper.ShopKeeperHandler;
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
|
import net.minecraft.network.packet.s2c.play.SetTradeOffersS2CPacket;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ClientPlayNetworkHandler.class)
|
||||||
|
public abstract class ClientPlayNetworkHandlerMixin {
|
||||||
|
@Inject(at = @At("TAIL"), method = "onSetTradeOffers")
|
||||||
|
public void onSetTradeOffers(SetTradeOffersS2CPacket packet, CallbackInfo ci, @Local ScreenHandler screenHandler) {
|
||||||
|
if (packet.getSyncId() == screenHandler.syncId && screenHandler instanceof ShopKeeperHandler shopKeeperHandler) {
|
||||||
|
shopKeeperHandler.SetOffers(packet.getOffers());
|
||||||
|
shopKeeperHandler.SetExperienceLevel(packet.getExperience());
|
||||||
|
shopKeeperHandler.SetLevelProgress(packet.getLevelProgress());
|
||||||
|
shopKeeperHandler.SetLeveled(packet.isLeveled());
|
||||||
|
shopKeeperHandler.SetCanRefreshTrades(packet.isRefreshable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
// 1.20.2 2025-01-01T19:10:14.65260685 keeblarcraft/Keeblarcraft World Generation
|
||||||
|
afc3340283d1101601bd4d2ca96341a58eceaf83 data/keeblarcraft/dimension_type/keeblarcraftdim_type.json
|
||||||
|
4398eda2b0c28b2c754c45f5805534bf1921b243 data/keeblarcraft/worldgen/biome/test_biome.json
|
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"ambient_light": 0.5,
|
||||||
|
"bed_works": true,
|
||||||
|
"coordinate_scale": 1.0,
|
||||||
|
"effects": "minecraft:overworld",
|
||||||
|
"fixed_time": 12750,
|
||||||
|
"has_ceiling": false,
|
||||||
|
"has_raids": false,
|
||||||
|
"has_skylight": true,
|
||||||
|
"height": 480,
|
||||||
|
"infiniburn": "#minecraft:infiniburn_overworld",
|
||||||
|
"logical_height": 256,
|
||||||
|
"min_y": 0,
|
||||||
|
"monster_spawn_block_light_limit": 0,
|
||||||
|
"monster_spawn_light_level": {
|
||||||
|
"type": "minecraft:uniform",
|
||||||
|
"value": {
|
||||||
|
"max_inclusive": 0,
|
||||||
|
"min_inclusive": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"natural": false,
|
||||||
|
"piglin_safe": false,
|
||||||
|
"respawn_anchor_works": false,
|
||||||
|
"ultrawarm": false
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
{
|
||||||
|
"carvers": {
|
||||||
|
"air": [
|
||||||
|
"minecraft:cave",
|
||||||
|
"minecraft:cave_extra_underground",
|
||||||
|
"minecraft:canyon"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downfall": 0.6,
|
||||||
|
"effects": {
|
||||||
|
"fog_color": 1800383,
|
||||||
|
"foliage_color": 13763580,
|
||||||
|
"grass_color": 1818548,
|
||||||
|
"sky_color": 11803583,
|
||||||
|
"water_color": 15414436,
|
||||||
|
"water_fog_color": 1800383
|
||||||
|
},
|
||||||
|
"features": [
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
"minecraft:lake_lava_underground",
|
||||||
|
"minecraft:lake_lava_surface"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"minecraft:amethyst_geode",
|
||||||
|
"minecraft:forest_rock"
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
"minecraft:ore_dirt",
|
||||||
|
"minecraft:ore_gravel",
|
||||||
|
"minecraft:ore_granite_upper",
|
||||||
|
"minecraft:ore_granite_lower",
|
||||||
|
"minecraft:ore_diorite_upper",
|
||||||
|
"minecraft:ore_diorite_lower",
|
||||||
|
"minecraft:ore_andesite_upper",
|
||||||
|
"minecraft:ore_andesite_lower",
|
||||||
|
"minecraft:ore_tuff"
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
"minecraft:spring_water",
|
||||||
|
"minecraft:spring_lava"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"minecraft:glow_lichen",
|
||||||
|
"minecraft:trees_plains",
|
||||||
|
"minecraft:forest_flowers",
|
||||||
|
"minecraft:patch_large_fern",
|
||||||
|
"minecraft:brown_mushroom_normal",
|
||||||
|
"minecraft:red_mushroom_normal",
|
||||||
|
"minecraft:patch_sugar_cane",
|
||||||
|
"minecraft:patch_pumpkin"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"minecraft:freeze_top_layer"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"has_precipitation": true,
|
||||||
|
"spawn_costs": {},
|
||||||
|
"spawners": {
|
||||||
|
"ambient": [],
|
||||||
|
"axolotls": [],
|
||||||
|
"creature": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:sheep",
|
||||||
|
"maxCount": 4,
|
||||||
|
"minCount": 4,
|
||||||
|
"weight": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:pig",
|
||||||
|
"maxCount": 4,
|
||||||
|
"minCount": 4,
|
||||||
|
"weight": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:chicken",
|
||||||
|
"maxCount": 4,
|
||||||
|
"minCount": 4,
|
||||||
|
"weight": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:cow",
|
||||||
|
"maxCount": 4,
|
||||||
|
"minCount": 4,
|
||||||
|
"weight": 8
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"misc": [],
|
||||||
|
"monster": [],
|
||||||
|
"underground_water_creature": [],
|
||||||
|
"water_ambient": [],
|
||||||
|
"water_creature": []
|
||||||
|
},
|
||||||
|
"temperature": 0.7
|
||||||
|
}
|
@ -10,13 +10,14 @@
|
|||||||
package jesse.keeblarcraft.AttributeMgr;
|
package jesse.keeblarcraft.AttributeMgr;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import jesse.keeblarcraft.Keeblarcraft;
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
||||||
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeFlight;
|
|
||||||
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeMetalJacket;
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeMetalJacket;
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.FactionNodes.FactionBeacon;
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.FactionNodes.FactionFlight;
|
||||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
|
||||||
|
|
||||||
public class AttributeMgr {
|
public class AttributeMgr {
|
||||||
ConfigManager config;
|
ConfigManager config;
|
||||||
@ -46,13 +47,12 @@ public class AttributeMgr {
|
|||||||
Keeblarcraft.LOGGER.error("Attempted to assign AbstractNode class type when registering object but could not call .newInstance()! Constructs must be empty");
|
Keeblarcraft.LOGGER.error("Attempted to assign AbstractNode class type when registering object but could not call .newInstance()! Constructs must be empty");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
ChatUtil.LoggerColored("Registring attribute called", ChatUtil.CONSOLE_COLOR.CYAN, Keeblarcraft.LOGGER);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (attributes.containsKey(verifyNode.GetNodeTitle())) {
|
if (attributes.containsKey(verifyNode.GetNodeTitle())) {
|
||||||
Keeblarcraft.LOGGER.warn("Could not register attribute with duplicate name '" + verifyNode.GetNodeTitle() + "'");
|
Keeblarcraft.LOGGER.warn("Could not register attribute with duplicate name '" + verifyNode.GetNodeTitle() + "'");
|
||||||
} else {
|
} else {
|
||||||
ChatUtil.LoggerColored("REGISTERING ATTRIBUTE " + verifyNode.GetNodeTitle(), ChatUtil.CONSOLE_COLOR.YELLOW, Keeblarcraft.LOGGER);
|
Keeblarcraft.LOGGER.debug("REGISTERING ATTRIBUTE: " + verifyNode.GetNodeTitle());
|
||||||
attributes.put(verifyNode.GetNodeTitle(), classObj);
|
attributes.put(verifyNode.GetNodeTitle(), classObj);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {} // Left empty since previous try-catch will throw error-message
|
} catch (Exception e) {} // Left empty since previous try-catch will throw error-message
|
||||||
@ -70,6 +70,19 @@ public class AttributeMgr {
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public static String ApplyAttribute(String uuid, String attributeName) {
|
public static String ApplyAttribute(String uuid, String attributeName) {
|
||||||
String msg = "";
|
String msg = "";
|
||||||
|
// System.out.println("ApplyAttribute debug. UUID - NAME: " + uuid + " - " + attributeName);
|
||||||
|
|
||||||
|
// Set<String> keys = attributes.keySet();
|
||||||
|
// for (String key : keys) {
|
||||||
|
// System.out.println("ATTRI: " + key);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// System.out.println("ACTIVE TREES: ");
|
||||||
|
// Set<String> names = activeTrees.keySet();
|
||||||
|
// for (String name : names) {
|
||||||
|
// System.out.println("N: " + name);
|
||||||
|
// }
|
||||||
|
|
||||||
if (attributes.containsKey(attributeName)) {
|
if (attributes.containsKey(attributeName)) {
|
||||||
AttributeTree playerTree = activeTrees.get(uuid);
|
AttributeTree playerTree = activeTrees.get(uuid);
|
||||||
AbstractNode node = null;
|
AbstractNode node = null;
|
||||||
@ -79,7 +92,15 @@ public class AttributeMgr {
|
|||||||
Keeblarcraft.LOGGER.error("Could not successfully apply attribute. String of attribute name could not be successfully cast to actual java object");
|
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) {
|
// System.out.println("Is player tree null: " + (playerTree == null ? "YES" : "NO"));
|
||||||
|
// System.out.println("Is player node null: " + (node == null ? "YES" : "NO"));
|
||||||
|
|
||||||
|
// if (playerTree != null) {
|
||||||
|
// System.out.println("Does player have skill: " + (playerTree.ContainsAttribute(attributeName) ? "YES" : "NO"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Ensure player tree isn't null; node isn't null; and the player doesn't already have this attribute
|
||||||
|
if (playerTree != null && node != null && !playerTree.ContainsAttribute(attributeName)) {
|
||||||
///////////
|
///////////
|
||||||
// debug testing
|
// debug testing
|
||||||
String isNull = (node == null ? "NULL" : "NOT NULL");
|
String isNull = (node == null ? "NULL" : "NOT NULL");
|
||||||
@ -92,13 +113,26 @@ public class AttributeMgr {
|
|||||||
msg = "Applied attribute '" + attributeName + "' successfully";
|
msg = "Applied attribute '" + attributeName + "' successfully";
|
||||||
} else {
|
} else {
|
||||||
msg = "Player tree not found!";
|
msg = "Player tree not found!";
|
||||||
|
// String debug = "PlayerTree is null";
|
||||||
|
// if (playerTree != null) {
|
||||||
|
// debug = playerTree.ContainsAttribute(attributeName) ? "YES":"NO";
|
||||||
|
// }
|
||||||
|
// System.out.println("APPLY ATTRIBUTE FAIL: TREE NULL, NODE NULL, OR PLAYER ALREADY HAS THIS ATTRIBUTE (DO THEY? " + debug + ")");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msg = "Could not apply attribute, attribute name does not exist!";
|
msg = "Could not apply attribute, attribute name does not exist!";
|
||||||
|
System.out.println("Attribute does not exist!");
|
||||||
}
|
}
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deletes an attribute from the node tree
|
||||||
|
public static void DisableAttribute(String uuid, String attributeName) {
|
||||||
|
if (activeTrees.containsKey(uuid) && activeTrees.get(uuid).ContainsAttribute(attributeName)) {
|
||||||
|
activeTrees.get(uuid).DeleteNode(attributeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
/// @fn RegisterAttributes
|
/// @fn RegisterAttributes
|
||||||
///
|
///
|
||||||
@ -112,7 +146,8 @@ public class AttributeMgr {
|
|||||||
/// TODO: Find a better way to do this more dynamically in the future
|
/// TODO: Find a better way to do this more dynamically in the future
|
||||||
/// hint: make it an API for other modders to add to
|
/// hint: make it an API for other modders to add to
|
||||||
|
|
||||||
RegisterAttributeClass(AttributeFlight.class);
|
|
||||||
RegisterAttributeClass(AttributeMetalJacket.class);
|
RegisterAttributeClass(AttributeMetalJacket.class);
|
||||||
|
RegisterAttributeClass(FactionBeacon.class);
|
||||||
|
RegisterAttributeClass(FactionFlight.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,6 +8,8 @@ import jesse.keeblarcraft.Armor.MetalJacketArmor;
|
|||||||
import jesse.keeblarcraft.CustomItems.ItemManager;
|
import jesse.keeblarcraft.CustomItems.ItemManager;
|
||||||
import net.minecraft.item.ArmorItem;
|
import net.minecraft.item.ArmorItem;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
|
||||||
public final class AttributeMetalJacket extends AbstractNode {
|
public final class AttributeMetalJacket extends AbstractNode {
|
||||||
// This is the custom armor set that players will receive if no armor is on & attribute is equipped
|
// This is the custom armor set that players will receive if no armor is on & attribute is equipped
|
||||||
|
@ -0,0 +1,138 @@
|
|||||||
|
package jesse.keeblarcraft.AttributeMgr.AttributeNodes.FactionNodes;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionTier;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerInBaseCallback;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
|
||||||
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
|
||||||
|
public class FactionBeacon extends AbstractNode {
|
||||||
|
private int beaconStrength = 1; // Increases with faction power; 1 is default
|
||||||
|
private int potionEffectLastingTimeTicks = 200; // 20 ticks per second makes this 10 seconds
|
||||||
|
private final Integer timerLengthMillis = 5000; // The default potion length is 10 seconds; so reset every 5 to be sure!
|
||||||
|
private Boolean resetTimer = true;
|
||||||
|
private final Timer timer = new Timer();
|
||||||
|
@Override
|
||||||
|
public String GetNodeTitle() {
|
||||||
|
return "faction_beacon";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String GetNodeDescription() {
|
||||||
|
return "This is a great unlockable for any faction to have and is leveled up with higher faction power. Gives beacon-like abilities + more!";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<String, List<String>> GetDetails() {
|
||||||
|
HashMap<String, List<String>> ret = new HashMap<String, List<String>>();
|
||||||
|
ret.put("Faction Beacon", List.of("Grants a ton of beacon-like effects on faction members inside the radius of the faction block"));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer GetBeaconAmplifier(FactionTierEnum tier) {
|
||||||
|
switch (tier) {
|
||||||
|
case TIER_I:
|
||||||
|
case TIER_II:
|
||||||
|
beaconStrength = 0;
|
||||||
|
break;
|
||||||
|
case TIER_III:
|
||||||
|
beaconStrength = 1;
|
||||||
|
break;
|
||||||
|
case TIER_IV:
|
||||||
|
beaconStrength = 2;
|
||||||
|
break;
|
||||||
|
case TIER_V:
|
||||||
|
beaconStrength = 3;
|
||||||
|
break;
|
||||||
|
case TIER_VI:
|
||||||
|
beaconStrength = 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Invalid case; in which case the beacon probably should do nothing
|
||||||
|
beaconStrength = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return beaconStrength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyEffects(ServerPlayerEntity player, FactionTierEnum tier) {
|
||||||
|
// player.setAbsorptionAmount(absorptionAmnt);
|
||||||
|
// Duration is in ticks
|
||||||
|
beaconStrength = GetBeaconAmplifier(tier);
|
||||||
|
|
||||||
|
// Tier 2 effects
|
||||||
|
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_II)) {
|
||||||
|
StatusEffectInstance regen = new StatusEffectInstance(StatusEffects.REGENERATION, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
StatusEffectInstance fire = new StatusEffectInstance(StatusEffects.FIRE_RESISTANCE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
player.addStatusEffect(regen);
|
||||||
|
player.addStatusEffect(fire);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tier 3 effects
|
||||||
|
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_III)) {
|
||||||
|
StatusEffectInstance hero = new StatusEffectInstance(StatusEffects.HERO_OF_THE_VILLAGE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
StatusEffectInstance haste = new StatusEffectInstance(StatusEffects.HASTE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
|
||||||
|
player.addStatusEffect(hero);
|
||||||
|
player.addStatusEffect(haste);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tier 4 effects
|
||||||
|
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_IV)) {
|
||||||
|
StatusEffectInstance conduit = new StatusEffectInstance(StatusEffects.CONDUIT_POWER, potionEffectLastingTimeTicks, 0, true,true, true);
|
||||||
|
StatusEffectInstance luck = new StatusEffectInstance(StatusEffects.LUCK, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
StatusEffectInstance absorption = new StatusEffectInstance(StatusEffects.ABSORPTION, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
StatusEffectInstance waterBreathing = new StatusEffectInstance(StatusEffects.WATER_BREATHING, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
player.addStatusEffect(conduit);
|
||||||
|
player.addStatusEffect(luck);
|
||||||
|
player.addStatusEffect(absorption);
|
||||||
|
player.addStatusEffect(waterBreathing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tier 5 effects
|
||||||
|
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_V)) {
|
||||||
|
StatusEffectInstance resistance = new StatusEffectInstance(StatusEffects.RESISTANCE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
StatusEffectInstance strength = new StatusEffectInstance(StatusEffects.STRENGTH, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
StatusEffectInstance dolphins = new StatusEffectInstance(StatusEffects.DOLPHINS_GRACE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
|
||||||
|
player.addStatusEffect(resistance);
|
||||||
|
player.addStatusEffect(strength);
|
||||||
|
player.addStatusEffect(dolphins);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tier 6 effects
|
||||||
|
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_VI)) {
|
||||||
|
StatusEffectInstance freeHealth = new StatusEffectInstance(StatusEffects.HEALTH_BOOST, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
|
||||||
|
|
||||||
|
player.addStatusEffect(freeHealth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void RegisterCallbacks() {
|
||||||
|
PlayerInBaseCallback.EVENT.register((player, world, power, factionTier) -> {
|
||||||
|
if (resetTimer) {
|
||||||
|
// The timer is super necessary because some effects (like regen) will not actually regen the player unless they can run for a few seconds
|
||||||
|
timer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
ApplyEffects((ServerPlayerEntity) player, factionTier);
|
||||||
|
resetTimer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}, timerLengthMillis);
|
||||||
|
resetTimer = false;
|
||||||
|
}
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
package jesse.keeblarcraft.AttributeMgr.AttributeNodes.FactionNodes;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerCommandFlightCallback;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerEnteredBaseCallback;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerExitedBaseCallback;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerInBaseCallback;
|
||||||
|
import net.minecraft.entity.player.PlayerAbilities;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
|
||||||
|
public class FactionFlight extends AbstractNode {
|
||||||
|
private final int flightSpeed = 1;
|
||||||
|
private ServerPlayerEntity player;
|
||||||
|
private float SPEED_SCALAR = 40.0f; // The value to scale this correctly to CREATIVE flight is '20.0f' however faction flight is slower than creative intentionally
|
||||||
|
private Boolean canFly = false;
|
||||||
|
private Boolean loginInBaseToggle = false; // Covers the unique case if player logs in inside the faction block border; in which case they need flight enabled!
|
||||||
|
private Integer leaveTimerMs = 5000;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String GetNodeTitle() {
|
||||||
|
return "faction_flight";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String GetNodeDescription() {
|
||||||
|
return "This is a temporary-unlock value when you are around your factions home base block and it has flight unlocked for members!";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<String, List<String>> GetDetails() {
|
||||||
|
HashMap<String, List<String>> ret = new HashMap<String, List<String>>();
|
||||||
|
ret.put("Faction Flight", List.of("Grants flight when near faction base if faction has it unlocked"));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean TurnOnFlight(ServerPlayerEntity player) {
|
||||||
|
Boolean isFlying = false;
|
||||||
|
PlayerAbilities abilities = player.getAbilities();
|
||||||
|
if (canFly && !abilities.allowFlying) {
|
||||||
|
abilities.allowFlying = true;
|
||||||
|
abilities.setFlySpeed((float) (flightSpeed / SPEED_SCALAR));
|
||||||
|
isFlying = true;
|
||||||
|
player.sendAbilitiesUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return isFlying;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean TurnOffFlight(ServerPlayerEntity player) {
|
||||||
|
Boolean isFlying = false;
|
||||||
|
PlayerAbilities abilities = player.getAbilities();
|
||||||
|
if (canFly && abilities.allowFlying) {
|
||||||
|
abilities.allowFlying = false;
|
||||||
|
abilities.flying = false;
|
||||||
|
abilities.setFlySpeed(0);
|
||||||
|
isFlying = false;
|
||||||
|
player.sendAbilitiesUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return isFlying;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetPlayer(ServerPlayerEntity player) {
|
||||||
|
// Disable flight
|
||||||
|
PlayerAbilities abilities = player.getAbilities();
|
||||||
|
abilities.flying = false;
|
||||||
|
abilities.allowFlying = false;
|
||||||
|
abilities.setFlySpeed(0);
|
||||||
|
player.sendAbilitiesUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void RegisterCallbacks() {
|
||||||
|
PlayerEnteredBaseCallback.EVENT.register((player, world, power, factionTier) -> {
|
||||||
|
player.sendMessage(Text.of("Faction flight enabled"));
|
||||||
|
canFly = true;
|
||||||
|
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
|
||||||
|
|
||||||
|
// Toggle flight
|
||||||
|
TurnOnFlight(serverPlayer);
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
|
||||||
|
PlayerInBaseCallback.EVENT.register((player, world, power, factionTier) -> {
|
||||||
|
// Make sure player can fly while inside the border. We don't ever want to run this more than once!
|
||||||
|
if (!canFly && !loginInBaseToggle) {
|
||||||
|
player.sendMessage(Text.of("Faction flight enabled"));
|
||||||
|
loginInBaseToggle = true;
|
||||||
|
canFly = true;
|
||||||
|
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
|
||||||
|
TurnOnFlight(serverPlayer);
|
||||||
|
}
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
|
||||||
|
PlayerCommandFlightCallback.EVENT.register((player, world, power, factionTier) -> {
|
||||||
|
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
|
||||||
|
Boolean isFlying = TurnOnFlight(serverPlayer);
|
||||||
|
// This is a toggle command; so first we get if the player is flying
|
||||||
|
PlayerAbilities abilities = player.getAbilities();
|
||||||
|
if (abilities.flying) {
|
||||||
|
TurnOffFlight((ServerPlayerEntity) player);
|
||||||
|
} else {
|
||||||
|
TurnOnFlight((ServerPlayerEntity) player);
|
||||||
|
}
|
||||||
|
System.out.println("abilities.flying: " + abilities.flying);
|
||||||
|
|
||||||
|
if(canFly && isFlying) {
|
||||||
|
serverPlayer.sendMessage(Text.of("Flight turned on"));
|
||||||
|
} else if (canFly && !isFlying) {
|
||||||
|
// Infers toggled off
|
||||||
|
serverPlayer.sendMessage(Text.of("Flight turned off"));
|
||||||
|
} else {
|
||||||
|
// Means player is not in fly-zone
|
||||||
|
serverPlayer.sendMessage(Text.of("You can only fly within the bounds of your faction base!"));
|
||||||
|
}
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
|
||||||
|
PlayerExitedBaseCallback.EVENT.register((player, world, power, factionTier) -> {
|
||||||
|
Timer timer = new Timer();
|
||||||
|
canFly = false;
|
||||||
|
player.sendMessage(Text.of("You left the faction's perimeter! Flight will disable in 5 seconds..."));
|
||||||
|
timer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Cover the edge condition such that we leave the faction base (canFly = false) then
|
||||||
|
// the timer here starts and we come back into the base (canFly = true) - we want a NO-OP here
|
||||||
|
if (!canFly) {
|
||||||
|
player.sendMessage(Text.of("Faction flight disabled"));
|
||||||
|
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
|
||||||
|
ResetPlayer(serverPlayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, leaveTimerMs);
|
||||||
|
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,15 +17,14 @@ import java.util.HashMap;
|
|||||||
import jesse.keeblarcraft.Keeblarcraft;
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
||||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
|
||||||
import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION;
|
|
||||||
|
|
||||||
public class AttributeTree {
|
public class AttributeTree {
|
||||||
|
|
||||||
PlayerTree playerAttributeTree = new PlayerTree();
|
PlayerTree playerAttributeTree = new PlayerTree();
|
||||||
ConfigManager config = new ConfigManager();
|
ConfigManager config = new ConfigManager();
|
||||||
private AbstractNode root = new RootNode();
|
private AbstractNode root = new RootNode();
|
||||||
|
private ServerPlayerEntity player;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
/// @class TreeNode
|
/// @class TreeNode
|
||||||
@ -33,7 +32,7 @@ public class AttributeTree {
|
|||||||
/// @brief This is an individual node that goes within the larger
|
/// @brief This is an individual node that goes within the larger
|
||||||
/// PlayerTree class object
|
/// PlayerTree class object
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
private class TreeNode {
|
public class TreeNode {
|
||||||
public TreeNode(AbstractNode node, Integer maxLevel, List<String> parents, List<String> children) {
|
public TreeNode(AbstractNode node, Integer maxLevel, List<String> parents, List<String> children) {
|
||||||
thisNode = node;
|
thisNode = node;
|
||||||
parentNodes = parents;
|
parentNodes = parents;
|
||||||
@ -42,15 +41,15 @@ public class AttributeTree {
|
|||||||
currentNodeLevel = 1;
|
currentNodeLevel = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode thisNode;
|
public AbstractNode thisNode;
|
||||||
Integer currentNodeLevel;
|
public Integer currentNodeLevel;
|
||||||
Integer maxNodeLevel;
|
public Integer maxNodeLevel;
|
||||||
|
|
||||||
// Store the names of the parent and children nodes; this lets a node have any number of parents and children
|
// 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
|
// 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!
|
// code before just adding stuff willy-nilly!
|
||||||
List<String> parentNodes;
|
public List<String> parentNodes;
|
||||||
List<String> childrenNodes;
|
public List<String> childrenNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
@ -61,10 +60,10 @@ public class AttributeTree {
|
|||||||
/// stored inside the AttributeMgr class
|
/// stored inside the AttributeMgr class
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
private class PlayerTree {
|
private class PlayerTree {
|
||||||
String uuid;
|
public String uuid;
|
||||||
// Key = name of AbstractNode
|
// Key = name of AbstractNode
|
||||||
// Val = The attribute itself
|
// Val = The attribute itself
|
||||||
HashMap<String, TreeNode> tree = new HashMap<String, TreeNode>();
|
public HashMap<String, TreeNode> tree = new HashMap<String, TreeNode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
@ -172,6 +171,8 @@ public class AttributeTree {
|
|||||||
playerAttributeTree.tree.put(newNode.GetNodeTitle(), new TreeNode(newNode, maxNodeLevel, parents, children));
|
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 the new nodes level is not 0 we need to manually register the callbacks
|
||||||
|
System.out.println("Node title: " + newNode.GetNodeTitle() + " has power level " +
|
||||||
|
playerAttributeTree.tree.get(newNode.GetNodeTitle()).currentNodeLevel);
|
||||||
if (playerAttributeTree.tree.get(newNode.GetNodeTitle()).currentNodeLevel != 0) {
|
if (playerAttributeTree.tree.get(newNode.GetNodeTitle()).currentNodeLevel != 0) {
|
||||||
System.out.println("Registering new callback for new node");
|
System.out.println("Registering new callback for new node");
|
||||||
playerAttributeTree.tree.get(newNode.GetNodeTitle()).thisNode.RegisterCallbacks();
|
playerAttributeTree.tree.get(newNode.GetNodeTitle()).thisNode.RegisterCallbacks();
|
||||||
@ -212,6 +213,18 @@ public class AttributeTree {
|
|||||||
FlashConfig();
|
FlashConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn public Boolean ContainsAttribute(String nodeName) {
|
||||||
|
///
|
||||||
|
/// @arg[in] nodeName is the attribute node title
|
||||||
|
///
|
||||||
|
/// @brief Returns true if this player presently has the 'nodeName'
|
||||||
|
/// attribute unlocked
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean ContainsAttribute(String nodeName) {
|
||||||
|
return playerAttributeTree.tree.containsKey(nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
/// @fn DeleteNode
|
/// @fn DeleteNode
|
||||||
///
|
///
|
||||||
@ -265,37 +278,35 @@ public class AttributeTree {
|
|||||||
///
|
///
|
||||||
/// @brief Constructor for class
|
/// @brief Constructor for class
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
public AttributeTree(String uuid) {
|
public AttributeTree(ServerPlayerEntity p) {
|
||||||
// DEVELOPER NOTE:
|
this.player = p;
|
||||||
// If you are testing this part of the code, please be reminded that anonymous testing starts a new
|
String uuid = player.getUuidAsString();
|
||||||
// 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;
|
Boolean existingFile = false;
|
||||||
try {
|
try {
|
||||||
playerAttributeTree = config.GetJsonObjectFromFile("attributes/" + uuid + ".json", PlayerTree.class);
|
playerAttributeTree = config.GetJsonObjectFromFile("attributes/" + uuid + ".json", PlayerTree.class);
|
||||||
existingFile = true;
|
existingFile = playerAttributeTree != null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
System.out.println("Attribute tree file does not exist for this player");
|
||||||
// Do nothing. This means the file does not exist
|
// 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
|
// In the event the above code failed out, this means a new file has to be created for the player's uuid
|
||||||
if (!existingFile)
|
if (!existingFile)
|
||||||
{
|
{
|
||||||
System.out.println(ChatUtil.ColoredString("Trying to create new file", CONSOLE_COLOR.BLUE));
|
System.out.println("Trying to create new file");
|
||||||
try {
|
try {
|
||||||
|
playerAttributeTree = new PlayerTree();
|
||||||
playerAttributeTree.uuid = uuid;
|
playerAttributeTree.uuid = uuid;
|
||||||
FlashConfig();
|
FlashConfig();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println(ChatUtil.ColoredString("Could not write to file", CONSOLE_COLOR.RED));
|
System.out.println("Could not write to file");
|
||||||
}
|
}
|
||||||
} 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
|
// 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
|
// a new file with this players uuid
|
||||||
if ("".equals(playerAttributeTree.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;
|
playerAttributeTree.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,10 +324,7 @@ public class AttributeTree {
|
|||||||
/// @brief Flashes the config to the disk
|
/// @brief Flashes the config to the disk
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
public void FlashConfig() {
|
public void FlashConfig() {
|
||||||
try {
|
/// TODO: This is broken because of a 'java.util.Option#value it cannot write. Idk, fix soon'
|
||||||
config.WriteToJsonFile("attributes/" + playerAttributeTree.uuid + ".json", playerAttributeTree);
|
// 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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,140 @@
|
|||||||
|
package jesse.keeblarcraft.BankMgr;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
/*
|
||||||
|
Account number composition:
|
||||||
|
|
||||||
|
EXAMPLE:
|
||||||
|
KCSB-9284-0JKI94358732
|
||||||
|
|
||||||
|
EXPLANATION:
|
||||||
|
The composition of the above number is mostly not random. The composition is 'C' = LETTER, and the first 4 represent the 4-letter combination
|
||||||
|
of the financial establishment (think of the stock market NASDAQ). The first 4 '#' (# = Number) digits represent the ROUTING number of the bank.
|
||||||
|
The next '#' (in its own brackets) represents ACCOUNT TYPE. This means the mod supports up to 9 configurations; some examples would be CHECKING
|
||||||
|
or SAVINGS. The next three '#' (in their own brackets too) will be the first three letters of the username of the account holder inside an ASCII
|
||||||
|
table. If the letter is not UTF 8 compatible - then the default will be '0'. The LAST eight '#' (not in brackets) are randomly generated via Java.
|
||||||
|
|
||||||
|
* Please note that the brackets in this example are only for demonstration of separating numbers from each other. They do not show up at all in generation.
|
||||||
|
|
||||||
|
|
||||||
|
CCCC-####-[#][###]########
|
||||||
|
|
||||||
|
* Additional note - enums are not implicitly integers under the hood like C++; so, a financial establishment could pass in ANY 0-9 digit for "account type" and
|
||||||
|
each establishment is allowed to treat that however they want. In one banks case it make checking accounts 3; but in anothers it's 4. This is a general programming
|
||||||
|
note for now. It is probably best to keep this consistent in your server/mod so tellers can understand them universally.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @class AccountNumberGenerator
|
||||||
|
///
|
||||||
|
/// @brief Utility class for the banking system. Can generate new account
|
||||||
|
/// numbers based on parameters and parse the account number
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public class AccountNumberGenerator {
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AccountNumberGenerator
|
||||||
|
///
|
||||||
|
/// @param[in] symbol is the bank/finance institution symbol
|
||||||
|
///
|
||||||
|
/// @param[in] routingNumber is the bank routing number
|
||||||
|
///
|
||||||
|
/// @param[in] accountType is the type of account being generated
|
||||||
|
///
|
||||||
|
/// @param[in] username is the players username who needs the account
|
||||||
|
///
|
||||||
|
/// @brief Creates a new account number for a user
|
||||||
|
///
|
||||||
|
/// @return String representation of account number
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static String GenerateNewAccountNumber(String symbol, Integer routingNumber, Integer accountType, String username) {
|
||||||
|
String generatedAccountNumber = symbol + "-" + routingNumber + "-" + accountType;
|
||||||
|
|
||||||
|
// Block to translate part of username into number format
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (username.length() >= 3 && username.charAt(i) <= 255) { // 255 is largest ASCII value. Might be a sloppy check; can always test later (if I find someone with non ASCII)
|
||||||
|
Integer asciiValueOfLetter = (int) username.charAt(i);
|
||||||
|
String strValueOfAscii = asciiValueOfLetter.toString();
|
||||||
|
strValueOfAscii = strValueOfAscii.substring(0, 1);
|
||||||
|
|
||||||
|
generatedAccountNumber += strValueOfAscii;
|
||||||
|
} else if (username.charAt(i) <= 255) { // Case where length is less than 3 but is still in ASCII table
|
||||||
|
Integer asciiValueOfLetter = (int) username.charAt(i);
|
||||||
|
String strValueOfAscii = asciiValueOfLetter.toString();
|
||||||
|
strValueOfAscii = strValueOfAscii.substring(0, 1);
|
||||||
|
|
||||||
|
generatedAccountNumber += strValueOfAscii;
|
||||||
|
} else { // Case where the length is less than 3 and is not standard ASCII
|
||||||
|
generatedAccountNumber += "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guarentee an 8 digit number. 10000000 is floor and max rng int is at most 89999999. Combined they total 99999999
|
||||||
|
Random rng = new Random();
|
||||||
|
Integer randInteger = 10000000 + rng.nextInt(89999999);
|
||||||
|
generatedAccountNumber += randInteger;
|
||||||
|
|
||||||
|
return generatedAccountNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the below functions must be given a key generated from the above function or they will combust into
|
||||||
|
// not less than one million pieces! :)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetFinancialSymbolFromId
|
||||||
|
///
|
||||||
|
/// @param[in] accountId is the generated account number
|
||||||
|
///
|
||||||
|
/// @brief Gets the financial symbol from the account id
|
||||||
|
///
|
||||||
|
/// @return String representation of financial symbol
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static String GetFinancialSymbolFromId(String accountId) {
|
||||||
|
return accountId.substring(0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetRoutingNumberFromId
|
||||||
|
///
|
||||||
|
/// @param[in] accountId is the generated account number
|
||||||
|
///
|
||||||
|
/// @brief Gets the routing number from the account id
|
||||||
|
///
|
||||||
|
/// @return Returns the integer of the account number
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static Integer GetRoutingNumberFromId(String accountId) {
|
||||||
|
return Integer.parseInt(accountId.substring(5, 9));
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetAccountNumberFromId
|
||||||
|
///
|
||||||
|
/// @param[in] accountId is the generated account number
|
||||||
|
///
|
||||||
|
/// @brief Gets the smaller account identifier from the entire account
|
||||||
|
/// identifier. This would be the ACCOUNT TYPE + GENERATED NUMBER
|
||||||
|
/// on the end of the whole identifier (so no financial symbol and
|
||||||
|
/// no routing number)
|
||||||
|
///
|
||||||
|
/// @return String representation of small account number
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static String GetAccountNumberFromId(String accountId) {
|
||||||
|
return accountId.substring(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetAccountTypeFromId
|
||||||
|
///
|
||||||
|
/// @param[in] accountId is the generated account number
|
||||||
|
///
|
||||||
|
/// @brief Gets the account type from account ID
|
||||||
|
///
|
||||||
|
/// @note The string representation of a valid account ID will have
|
||||||
|
/// '0' - '9' (range) in this position; so, subtracting 48 from
|
||||||
|
/// the ASCII returns the actual account number as an integer.
|
||||||
|
///
|
||||||
|
/// @return Integer representing account type (0-9)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static Integer GetAccountTypeFromId(String accountId) {
|
||||||
|
return ((int) accountId.charAt(10)) - 48; // ASCII 0 starts at 48. One must subtract 48 to be correct.
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package jesse.keeblarcraft.BankMgr;
|
||||||
|
|
||||||
|
public class BankAccountType {
|
||||||
|
public enum ACCOUNT_TYPE {
|
||||||
|
CHECKING,
|
||||||
|
SAVINGS
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,256 +1,339 @@
|
|||||||
package jesse.keeblarcraft.BankMgr;
|
package jesse.keeblarcraft.BankMgr;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import jesse.CommonServerUtils;
|
import jesse.keeblarcraft.BankMgr.BankAccountType.ACCOUNT_TYPE;
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatFormatting;
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatMsg;
|
||||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
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;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
public class BankManager {
|
// The bank manager takes care of routing any and all transactions throughout the server.
|
||||||
BankManagerFile bankInfo = new BankManagerFile(); // not sure why we make another one but i guess so we
|
// It is a singleton object that is active throughout the mods lifetime and will cache players accounts
|
||||||
ConfigManager config = new ConfigManager(); // for read and write privs
|
// when they log in to avoid constant look-ups through JSON.
|
||||||
CommonServerUtils commonServerUtils = new CommonServerUtils();
|
public final class BankManager {
|
||||||
|
private static BankManager static_inst;
|
||||||
|
|
||||||
public BankManager(String uuid) {
|
public static BankManager GetInstance() {
|
||||||
Boolean existingFile = false;
|
if (static_inst == null) {
|
||||||
try {
|
static_inst = new BankManager();
|
||||||
bankInfo = config.GetJsonObjectFromFile("bank/" + uuid + ".json", BankManagerFile.class);
|
|
||||||
existingFile = true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Do nothing. This means the file does not exist
|
|
||||||
}
|
}
|
||||||
|
return static_inst;
|
||||||
|
}
|
||||||
|
|
||||||
// In the event the above code failed out, this means a new file has to be
|
private static class PlayerBankConfig {
|
||||||
// created for the player's uuid
|
List<String> activeBanks = new ArrayList<String>(); // List of all banks a player has accounts in
|
||||||
if (!existingFile) {
|
String defaultSelectedBank = "";
|
||||||
System.out.println(ChatUtil.ColoredString("Trying to create new file", CONSOLE_COLOR.BLUE));
|
String defaultSelectedAccount = "";
|
||||||
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)) {
|
// Key = player uuid
|
||||||
System.out.println(ChatUtil.ColoredString("Assigning new config file for this uuid. No previous existing",
|
// Val = player config
|
||||||
CONSOLE_COLOR.BLUE));
|
private HashMap<String, PlayerBankConfig> playerConfigs = new HashMap<String, PlayerBankConfig>(); // Stores global detail information for bank mgr to use
|
||||||
bankInfo.uuid = uuid;
|
|
||||||
|
private static Integer KEEBLARCRAFT_SERVER_BANK_ID = 1000; // Server global bank (default bank on server)
|
||||||
|
private ConfigManager config = new ConfigManager();
|
||||||
|
|
||||||
|
// KEY = Bank routing number
|
||||||
|
// Val = Bank object
|
||||||
|
private HashMap<Integer, IndividualBank> banks = new HashMap<Integer, IndividualBank>();
|
||||||
|
|
||||||
|
// KEY = Bank name
|
||||||
|
// Val = Bank routing number
|
||||||
|
private HashMap<String, Integer> bankNameFastMap = new HashMap<String, Integer>();
|
||||||
|
|
||||||
|
public BankManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: THIS NEEDS TO READ IN FROM A FILE TO STOP NUKING BANKS ON REBOOT
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn InitializeBanks
|
||||||
|
///
|
||||||
|
/// @brief Initializes all the banks on the server at construction time
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void InitializeBanks() {
|
||||||
|
banks.put(KEEBLARCRAFT_SERVER_BANK_ID, new IndividualBank(Integer.toString(KEEBLARCRAFT_SERVER_BANK_ID), "Keeblarcraft"));
|
||||||
|
|
||||||
|
// Initialize fast map
|
||||||
|
for (Entry<Integer, IndividualBank> bank : banks.entrySet()) {
|
||||||
|
bankNameFastMap.put(bank.getValue().GetBankName().toUpperCase(), bank.getValue().GetRoutingNumber());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//this class is the structure for the hashmap in BankManagerFile
|
// Retrieves balance of the default selected account should that be selected
|
||||||
private class BankManagerMetaData {
|
public void GetBalance(ServerPlayerEntity player) {
|
||||||
public BankManagerMetaData(long money, String reason, long payment, String otherParty, Integer time) {
|
if (playerConfigs.containsKey(player.getUuidAsString()) && !playerConfigs.get(player.getUuidAsString()).defaultSelectedAccount.isEmpty()) {
|
||||||
this.balance = money;
|
String playerSelectedBank = GetPlayerSelectedBank(player.getUuidAsString());
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!playerSelectedBank.isEmpty()) {
|
||||||
|
IndividualBank bank = GetBankByName(playerSelectedBank);
|
||||||
|
Optional<Integer> amount = bank.GetAccountBalance(AccountNumberGenerator.GetAccountNumberFromId(playerConfigs.get(player.getUuidAsString()).defaultSelectedAccount));
|
||||||
|
if (amount.isPresent()) {
|
||||||
|
player.sendMessage(Text.of(ChatMsg.ColorMsg("You have " + amount.get() + " keebucks", ChatFormatting.COLOR_CODE.GREEN)));
|
||||||
} else {
|
} else {
|
||||||
System.out.println(ChatUtil.ColoredString("Player Not Found: " + otherParty, CONSOLE_COLOR.RED));
|
player.sendMessage(Text.of(ChatMsg.ColorMsg("It appears your default account cannot be found at this bank! Re-select your default account maybe?", ChatFormatting.COLOR_CODE.RED)));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of(ChatMsg.ColorMsg("You don't have a bank selected first! To use balance you need a default bank AND account selected!", ChatFormatting.COLOR_CODE.RED)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.out.println(ChatUtil.ColoredString("You need to finance better", CONSOLE_COLOR.RED));
|
player.sendMessage(Text.of(ChatMsg.ColorMsg("You don't have a bank selected first! To use balance you need a default bank AND account selected!", ChatFormatting.COLOR_CODE.RED)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean IsDefaultAccount(String playerUuid, String globalAccountId) {
|
||||||
|
return playerConfigs.containsKey(playerUuid) && playerConfigs.get(playerUuid).defaultSelectedAccount.equals(globalAccountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetAllBankNames
|
||||||
|
///
|
||||||
|
/// @return List of all the banks that exist on a server
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public List<String> GetAllBankNames() {
|
||||||
|
List<String> names = new ArrayList<String>();
|
||||||
|
|
||||||
|
// Iterate through all banks in the list to get their names
|
||||||
|
for (Entry<Integer, IndividualBank> bank : banks.entrySet()) {
|
||||||
|
names.add(bank.getValue().GetBankName());
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetBankByRoutingNumber
|
||||||
|
///
|
||||||
|
/// @return The IndividualBank object by routing number if the bank exists
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public IndividualBank GetBankByRoutingNumber(Integer number) {
|
||||||
|
IndividualBank bank = null;
|
||||||
|
if (banks.containsKey(number)) {
|
||||||
|
bank = banks.get(number);
|
||||||
|
}
|
||||||
|
return bank;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetBankByName
|
||||||
|
///
|
||||||
|
/// @return The Individualbank object by name if the bank exists
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public IndividualBank GetBankByName(String name) {
|
||||||
|
IndividualBank bank = null;
|
||||||
|
if (bankNameFastMap.containsKey(name)) {
|
||||||
|
bank = banks.get(bankNameFastMap.get(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return bank;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ChangeDefaultPlayerAccount
|
||||||
|
///
|
||||||
|
/// @param[in] player Player object to change default accounts of
|
||||||
|
///
|
||||||
|
/// @param[in] The new default account global account identifier
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void ChangeDefaultPlayerAccount(ServerPlayerEntity player, String newDefaultAccount) {
|
||||||
|
Integer routingNumber = AccountNumberGenerator.GetRoutingNumberFromId(newDefaultAccount);
|
||||||
|
if (banks.containsKey(routingNumber)) {
|
||||||
|
IndividualBank bank = banks.get(routingNumber);
|
||||||
|
String accountId = AccountNumberGenerator.GetAccountNumberFromId(newDefaultAccount); // Short ID; not global!
|
||||||
|
if (bank.IsAccountHolder(accountId, player.getUuidAsString())) {
|
||||||
|
playerConfigs.get(player.getUuidAsString()).defaultSelectedAccount = newDefaultAccount;
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("You are not an account holder on this account! Cannot set"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("Could not change default selected account. Bank does not exist!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This guarantees a player config exists; and so can be called from many areas. Does not erase pre-existing config
|
||||||
|
public boolean EnsurePlayerConfigExists(String uuid) {
|
||||||
|
if (!playerConfigs.containsKey(uuid)) {
|
||||||
|
playerConfigs.put(uuid, new PlayerBankConfig());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allows the player to select a bank
|
||||||
|
public void ChangeDefaultSelectedBank(ServerPlayerEntity player, String bankName) {
|
||||||
|
if (bankNameFastMap.containsKey(bankName) && EnsurePlayerConfigExists(player.getUuidAsString())) {
|
||||||
|
playerConfigs.get(player.getUuidAsString()).defaultSelectedBank = bankName;
|
||||||
|
player.sendMessage(Text.of("You have successfully selected the following financial institution: " + bankName));
|
||||||
|
player.sendMessage(Text.of("Please be aware the context of commands following this will likely be done under this financial institution"));
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("That bank does not exist."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AdminChangeFunds
|
||||||
|
///
|
||||||
|
/// @param[in] initiator The player object who is initiating this call
|
||||||
|
///
|
||||||
|
/// @param[in] accountId The account to change funds of
|
||||||
|
///
|
||||||
|
/// @param[in] amount The amount to change funds of in changeType
|
||||||
|
///
|
||||||
|
/// @param[in] changeType The type of funds change being initiated
|
||||||
|
///
|
||||||
|
/// @param[in] optionalReason The optional reason of changing funds
|
||||||
|
///
|
||||||
|
/// @brief Command manager to initiate a funds change from an admins
|
||||||
|
/// perspective (safe guards dropped). Valid changeTypes are
|
||||||
|
/// found inside the switch-case statement in the below function
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void AdminChangeFunds(ServerPlayerEntity initiator, String accountId, Integer amount, String changeType, String optionalReason) {
|
||||||
|
// Check to make sure account id exists
|
||||||
|
Integer routingNum = AccountNumberGenerator.GetRoutingNumberFromId(accountId);
|
||||||
|
IndividualBank bankFromRout = GetBankByRoutingNumber(routingNum);
|
||||||
|
|
||||||
|
System.out.println("Is bank null? " + (bankFromRout == null ? "YES" : "NO"));
|
||||||
|
System.out.println("Bank specified: " + bankFromRout);
|
||||||
|
System.out.println("Routing number: " + routingNum);
|
||||||
|
// Verify bank exists
|
||||||
|
if (bankFromRout != null) {
|
||||||
|
// Verify account exists
|
||||||
|
System.out.println("accountNumber is " + accountId);
|
||||||
|
String accountNumber = AccountNumberGenerator.GetAccountNumberFromId(accountId);
|
||||||
|
System.out.println("changeType is " + changeType);
|
||||||
|
|
||||||
|
switch (changeType) {
|
||||||
|
case "add":
|
||||||
|
bankFromRout.AddMoneyToAccount(accountNumber, amount);
|
||||||
|
break;
|
||||||
|
case "subtract":
|
||||||
|
bankFromRout.SubtractMoneyFromAccount(accountNumber, amount);
|
||||||
|
break;
|
||||||
|
case "set":
|
||||||
|
bankFromRout.SetMoneyOnAccount(accountNumber, amount);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.out.println("The operation that was specified by the developer does not exist. Valid operations are add/subtract/set");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
initiator.sendMessage(Text.of("That bank does not exist!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn InitiateBankFundsTransfer
|
||||||
|
///
|
||||||
|
/// @param[in] fromPlayer is the player funds are coming out of
|
||||||
|
///
|
||||||
|
/// @param[in] toAccount is the account the funds are going to
|
||||||
|
///
|
||||||
|
/// @param[in] amount is the amount of money coming from the player
|
||||||
|
///
|
||||||
|
/// @brief Initiate a funds transfer between accounts or banks
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void InitiateBankFundsTransfer(ServerPlayerEntity fromPlayer, String toAccount, Integer amount, String reason) {
|
||||||
|
// Get player default selection
|
||||||
|
if (!playerConfigs.containsKey(fromPlayer.getUuidAsString()) || playerConfigs.get(fromPlayer.getUuidAsString()).defaultSelectedAccount.isEmpty()) {
|
||||||
|
fromPlayer.sendMessage(Text.of("You need to select a default bank account from the bank you have selected to wire from first! /bank select-default-account"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
String GetUuidByName(MinecraftServer server, String playerName) {
|
String fromAccount = playerConfigs.get(fromPlayer.getUuidAsString()).defaultSelectedAccount;
|
||||||
PlayerManager playerManager = server.getPlayerManager();
|
Integer fromRoutingNumber = AccountNumberGenerator.GetRoutingNumberFromId(fromAccount);
|
||||||
ServerPlayerEntity player = playerManager.getPlayer(playerName);
|
Integer toRoutingNumber = AccountNumberGenerator.GetRoutingNumberFromId(toAccount);
|
||||||
if (player.getUuid() != null) {
|
IndividualBank destBank = banks.get(fromRoutingNumber);
|
||||||
return player.getUuidAsString();
|
IndividualBank fromBank = banks.get(toRoutingNumber);
|
||||||
} else {
|
String fromAccountSymbol = AccountNumberGenerator.GetFinancialSymbolFromId(fromAccount); // For chat
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String PlayerListNameChecker(String otherParty) {
|
// Verify banks exist
|
||||||
MinecraftServer server = CommonServerUtils.GetServerInstance();
|
if (destBank != null && fromBank != null) {
|
||||||
String[] playerList = server.getPlayerNames();
|
if (fromBank.IsValidWithdrawal(amount, fromAccount)) {
|
||||||
|
fromBank.SubtractMoneyFromAccount(fromAccount, amount);
|
||||||
|
destBank.AddMoneyToAccount(toAccount, amount);
|
||||||
|
|
||||||
for (int i = 0; i < playerList.length; i++) {
|
fromPlayer.sendMessage(Text.of("[" + fromAccountSymbol + "]: Your wire has processed."));
|
||||||
System.out.println(ChatUtil.ColoredString("PLAYERS: " + playerList, CONSOLE_COLOR.YELLOW));
|
} else {
|
||||||
if (playerList[i] == otherParty) {
|
fromPlayer.sendMessage(Text.of("[" + fromAccountSymbol + "]: You are not allowed to make this withdrawal."));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fromPlayer.sendMessage(Text.of("Something went wrong! Either your bank or their bank does not exist. You shouldn't get this error!"));
|
||||||
}
|
}
|
||||||
System.out.println(ChatUtil.ColoredString("For Loop condition bypassed Null Playerlist or Null Server instance", CONSOLE_COLOR.RED));
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FlashConfig(String uuid) {
|
public void InitiateBankAccountClosure(ServerPlayerEntity player, String accountId) {
|
||||||
try {
|
Integer routing = AccountNumberGenerator.GetRoutingNumberFromId(accountId);
|
||||||
config.WriteToJsonFile("bank/" + uuid + ".json", bankInfo);
|
|
||||||
} catch (FILE_WRITE_EXCEPTION e) {
|
if (banks.containsKey(routing)) {
|
||||||
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
|
IndividualBank bank = banks.get(routing);
|
||||||
|
boolean success = bank.CloseAccount(AccountNumberGenerator.GetAccountNumberFromId(accountId), player.getUuidAsString());
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
player.sendMessage(Text.of("Successfully closed account."));
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of(ChatMsg.ColorMsg("Failed to close account. Contact bank manager for more information.", ChatFormatting.COLOR_CODE.RED)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of(ChatMsg.ColorMsg("That bank doesn't exist.", ChatFormatting.COLOR_CODE.RED)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetDefaultSelectedAccount
|
||||||
|
///
|
||||||
|
/// @param[in] playerUuid is the player to get their default account
|
||||||
|
///
|
||||||
|
/// @param[in] bankIdentifier is the bank the default account is at
|
||||||
|
///
|
||||||
|
/// @brief Gets a players default account
|
||||||
|
///
|
||||||
|
/// @return The global account identifier of the default selected account
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public String GetDefaultSelectedAccount(String playerUuid, String bankIdentifier) {
|
||||||
|
String account = "";
|
||||||
|
|
||||||
|
if (playerConfigs.containsKey(playerUuid)) {
|
||||||
|
account = playerConfigs.get(playerUuid).defaultSelectedAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String GetPlayerSelectedBank(String playerUuid) {
|
||||||
|
String bank = "";
|
||||||
|
if (playerConfigs.containsKey(playerUuid)) {
|
||||||
|
bank = playerConfigs.get(playerUuid).defaultSelectedBank;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bank;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn InitiateBankAccountCreation
|
||||||
|
///
|
||||||
|
/// @param[in] bankIdentifier is the bank routing number
|
||||||
|
///
|
||||||
|
/// @param[in] player is the player object trying to create account
|
||||||
|
///
|
||||||
|
/// @paran[in] accountType Is the type of account the player wants to make
|
||||||
|
///
|
||||||
|
/// @brief Initiates a bank account creation with a bank
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void InitiateBankAccountCreation(String bankIdentifier, ServerPlayerEntity player, ACCOUNT_TYPE accountType) {
|
||||||
|
Boolean success = false;
|
||||||
|
IndividualBank bank = GetBankByName(bankIdentifier);
|
||||||
|
|
||||||
|
if (bank != null) {
|
||||||
|
success = bank.CreateAccount(player.getUuidAsString(), player.getEntityName(), accountType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
player.sendMessage(Text.of("The banking operation was successful and your banking information has been updated"));
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("The banking operating FAILED. Make sure you selected this bank before creating it!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
236
src/main/java/jesse/keeblarcraft/BankMgr/IndividualAccount.java
Normal file
236
src/main/java/jesse/keeblarcraft/BankMgr/IndividualAccount.java
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
package jesse.keeblarcraft.BankMgr;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.BankMgr.BankAccountType.ACCOUNT_TYPE;
|
||||||
|
|
||||||
|
// Contains the information of an individuals player's bank account.
|
||||||
|
// TODO: Add ability to store NBT data of items in the future so we can store not just money but items too
|
||||||
|
// like a safety deposit box
|
||||||
|
public class IndividualAccount {
|
||||||
|
private String globalAccountNumber;
|
||||||
|
private String bankLetterIdentifier;
|
||||||
|
private String accountNumber;
|
||||||
|
private String accountNumberAlias;
|
||||||
|
private Integer routingNumber; // Will always be the bank it's in
|
||||||
|
private List<String> accountHolders;
|
||||||
|
private List<String> accountHolderUuids;
|
||||||
|
private int accountBalance;
|
||||||
|
private boolean allowNegativeBalance = false;
|
||||||
|
private boolean accountLocked = false;
|
||||||
|
private ACCOUNT_TYPE accountType;
|
||||||
|
|
||||||
|
|
||||||
|
public IndividualAccount() {}
|
||||||
|
|
||||||
|
public IndividualAccount(String accountNumber, Integer routingNumber, List<String> holders,
|
||||||
|
List<String> accountHolderUuids, Boolean allowNegativeBalance, Integer initialBalance,
|
||||||
|
String alias, ACCOUNT_TYPE accountType, String bankLetterIdentifier) {
|
||||||
|
|
||||||
|
System.out.println("Called to create new IndividualAccount with following values: " + accountNumber + " " + routingNumber + " " + holders + " " +
|
||||||
|
accountHolderUuids + " " + allowNegativeBalance + " " + initialBalance + " " + alias + " " + accountType);
|
||||||
|
this.accountNumber = accountNumber;
|
||||||
|
this.routingNumber = routingNumber;
|
||||||
|
this.accountHolders = holders;
|
||||||
|
this.accountHolderUuids = accountHolderUuids;
|
||||||
|
this.allowNegativeBalance = allowNegativeBalance;
|
||||||
|
this.accountBalance = initialBalance;
|
||||||
|
this.accountNumberAlias = alias;
|
||||||
|
this.accountType = accountType;
|
||||||
|
this.bankLetterIdentifier = bankLetterIdentifier;
|
||||||
|
this.globalAccountNumber = bankLetterIdentifier + "-" + routingNumber + "-" + accountNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AddAccountHolder
|
||||||
|
///
|
||||||
|
/// @param[in] newHolder to be added to account
|
||||||
|
///
|
||||||
|
/// @param[in] newHolderUuid to be added to account
|
||||||
|
///
|
||||||
|
/// @brief Adds another UUID who can access the bank account
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void AddAccountHolder(String newHolder, String newHolderUuid) {
|
||||||
|
if (!accountHolders.contains(newHolder)) {
|
||||||
|
accountHolders.add(newHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!accountHolderUuids.contains(newHolderUuid)) {
|
||||||
|
accountHolderUuids.add(newHolderUuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn SetMoney
|
||||||
|
///
|
||||||
|
/// @param[in] amount is the new account balance
|
||||||
|
///
|
||||||
|
/// @brief Set the balance of the bank account. NOT RECOMMENDED OUTSIDE
|
||||||
|
/// OF ADMINISTRATIVE USE!!!
|
||||||
|
///
|
||||||
|
/// @note This will forcefully ignore account settings like not being
|
||||||
|
/// able to go negative. This is not recommended to use
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void SetMoney(Integer amount) {
|
||||||
|
System.out.println("Previous balance on account: " + this.accountBalance + ". New balance: " + amount);
|
||||||
|
this.accountBalance = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AliasAccount
|
||||||
|
///
|
||||||
|
/// @param[in] newAlias to name the account
|
||||||
|
///
|
||||||
|
/// @brief Sets new alias of this account
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void AliasAccount(String newAlias) {
|
||||||
|
this.accountNumberAlias = newAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IsLocked
|
||||||
|
///
|
||||||
|
/// @brief Returns if account is locked
|
||||||
|
///
|
||||||
|
/// @return True if locked, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean IsLocked() {
|
||||||
|
return accountLocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn LockAccount
|
||||||
|
///
|
||||||
|
/// @brief Locks an account
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void LockAccount() {
|
||||||
|
accountLocked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn Deposit
|
||||||
|
///
|
||||||
|
/// @param[in] amount is amount to be added
|
||||||
|
///
|
||||||
|
/// @brief Deposits (adds) amount of money to account
|
||||||
|
///
|
||||||
|
/// @return True if succeeds, false if fails
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean Deposit(Integer amount) {
|
||||||
|
boolean success = false;
|
||||||
|
System.out.println("Depositing " + amount);
|
||||||
|
System.out.println("is account locked: " + accountLocked);
|
||||||
|
if (!accountLocked)
|
||||||
|
{
|
||||||
|
accountBalance += amount;
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn Withdraw
|
||||||
|
///
|
||||||
|
/// @param[in] amount is amount to be subtracted
|
||||||
|
///
|
||||||
|
/// @brief Withdraws (subtracts) amount from account balance
|
||||||
|
///
|
||||||
|
/// @return True if succeeds, false if fails
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean Withdraw(Integer amount) {
|
||||||
|
boolean success = false;
|
||||||
|
|
||||||
|
if (!accountLocked)
|
||||||
|
{
|
||||||
|
// Determine remaining balance
|
||||||
|
int remaining = accountBalance - amount;
|
||||||
|
success = (remaining >= 0 || allowNegativeBalance);
|
||||||
|
|
||||||
|
// Complete the transaction if successful
|
||||||
|
if (success) {
|
||||||
|
accountBalance = remaining;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn CanWithdraw
|
||||||
|
///
|
||||||
|
/// @return True if account can afford withdrawal, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean CanWithdraw(Integer amount) {
|
||||||
|
System.out.println("Account balance: " + accountBalance);
|
||||||
|
System.out.println("Allow negative balance: " + allowNegativeBalance);
|
||||||
|
System.out.println("Account positive after deduction: " + (accountBalance - amount >= 0));
|
||||||
|
return !accountLocked && (accountBalance - amount >= 0 || allowNegativeBalance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IsHolder
|
||||||
|
///
|
||||||
|
/// @return True if name is on name list
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean IsHolder(String uuid) {
|
||||||
|
return accountHolderUuids.contains(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AllowsNegative
|
||||||
|
///
|
||||||
|
/// @return True if account allows negative balances, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean AllowsNegative() {
|
||||||
|
return this.allowNegativeBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetAccountHolders
|
||||||
|
///
|
||||||
|
/// @return List of everyone who has access to this account
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public List<String> GetAccountHolders() {
|
||||||
|
return accountHolders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetAccountBalance
|
||||||
|
///
|
||||||
|
/// @return Account balance
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Integer GetAccountBalance() {
|
||||||
|
return accountBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ACCOUNT_TYPE GetAccountType() {
|
||||||
|
return accountType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetAccountNumber
|
||||||
|
///
|
||||||
|
/// @return String representation of account number (SHORT account number)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public String GetAccountNumber() {
|
||||||
|
return accountNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetRoutingNumber
|
||||||
|
///
|
||||||
|
/// @return Routing number of account
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Integer GetRoutingNumber() {
|
||||||
|
return routingNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetGlobalAccountNumber
|
||||||
|
///
|
||||||
|
/// @return Gets global (ENTIRE) account number
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public String GetGlobalAccountNumber() {
|
||||||
|
return globalAccountNumber;
|
||||||
|
}
|
||||||
|
}
|
594
src/main/java/jesse/keeblarcraft/BankMgr/IndividualBank.java
Normal file
594
src/main/java/jesse/keeblarcraft/BankMgr/IndividualBank.java
Normal file
@ -0,0 +1,594 @@
|
|||||||
|
package jesse.keeblarcraft.BankMgr;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import static java.util.Map.entry;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.BankMgr.BankAccountType.ACCOUNT_TYPE;
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
|
||||||
|
|
||||||
|
// Contains the information of an individual bank
|
||||||
|
//
|
||||||
|
// The bank will keep track of all accounts within its facilities. In addition to accounts, the bank
|
||||||
|
// maintains its own identifier which is unique and other misc things.
|
||||||
|
public class IndividualBank {
|
||||||
|
private Map<ACCOUNT_TYPE, Integer> ACCOUNT_TYPES = Map.ofEntries(
|
||||||
|
entry(ACCOUNT_TYPE.CHECKING, 0),
|
||||||
|
entry(ACCOUNT_TYPE.SAVINGS, 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
private ConfigManager config = new ConfigManager();
|
||||||
|
private Integer routingNumber; // this is the banks unique identifier
|
||||||
|
private Integer numberOfAccounts = 0; // Total number of accounts the bank has. This includes only active accounts inside accountsList.
|
||||||
|
private Integer maxBankAccounts = 100_000_000; // Making this simple for myself any one type of account has 8 random numbers genereated so 10^8 possible accounts
|
||||||
|
private String bankFourLetterIdentifier;
|
||||||
|
private String registeredBankName;
|
||||||
|
|
||||||
|
private static String CONFIG_LOCATION = "config/keeblarcraft/bank/";
|
||||||
|
|
||||||
|
// Think FDIC but from the servers account (keeblarcraft insurance corporation)
|
||||||
|
// KBIC will ensure an amount of money based on its trustworthiness to a bank and the number of holders it has.
|
||||||
|
private Integer kbicInsuredAmount = 75_000;
|
||||||
|
private Boolean kbicInsured = false;
|
||||||
|
|
||||||
|
// bankMoney is the total amount of money the bank possesses itself. The bank itself is personally responsible
|
||||||
|
// for backing the amount of money it claims it has and this is the balance that is withdrawn from for credits.
|
||||||
|
// A bank can have a sum of money that is less than the total amount of money of all its account holders
|
||||||
|
private Integer bankMoney = 0;
|
||||||
|
|
||||||
|
// Key = ACCOUNT NUMBER
|
||||||
|
// Value = ACCOUNT
|
||||||
|
private class Accounts {
|
||||||
|
// Key = account identifier
|
||||||
|
// Val = account object
|
||||||
|
private HashMap<String, IndividualAccount> accountsList = new HashMap<String, IndividualAccount>();
|
||||||
|
|
||||||
|
// Key = user uuid
|
||||||
|
// Val = List of account identifiers
|
||||||
|
private HashMap<String, List<String>> accountsListFromName = new HashMap<String, List<String>>(); // This is a list that just points to a list of account numbers by person. USEFUL
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts accounts;
|
||||||
|
private List<String> lockedUsers; // A list of users who are locked out of the bank and are incapable of performing more actions within it
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IndividualBank
|
||||||
|
///
|
||||||
|
/// @param[in] routingNumber is the routing number this bank is constructed
|
||||||
|
/// with
|
||||||
|
///
|
||||||
|
/// @param[in] nameOfBank Will be the display name of this bank to players
|
||||||
|
///
|
||||||
|
/// @brief Constructor for this bank
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public IndividualBank(String routingNumber, String nameOfBank) {
|
||||||
|
accounts = new Accounts();
|
||||||
|
lockedUsers = new ArrayList<String>();
|
||||||
|
registeredBankName = nameOfBank.toUpperCase();
|
||||||
|
bankFourLetterIdentifier = nameOfBank.substring(0, 4).toLowerCase();
|
||||||
|
this.routingNumber = Integer.parseInt(routingNumber);
|
||||||
|
|
||||||
|
System.out.println("CREATING BANK ACCOUNT WITH ROUTING NUMBER " + routingNumber + " AND NAME " + nameOfBank);
|
||||||
|
|
||||||
|
boolean existingFile = false;
|
||||||
|
try {
|
||||||
|
// Read in the global accounts list
|
||||||
|
String accountsListDir = CONFIG_LOCATION + routingNumber.toString() + "/accounts/";
|
||||||
|
System.out.println("accountsListDir + bankName is " + accountsListDir + nameOfBank);
|
||||||
|
accounts = config.GetJsonObjectFromFile(accountsListDir + nameOfBank, Accounts.class);
|
||||||
|
existingFile = accounts != null;
|
||||||
|
|
||||||
|
// TODO: REPLACE WITH SQL SERVER. DIRTY ITERATE OVER ALL FILES IN DIRECTORY TO LOAD STRUCTURE
|
||||||
|
File dir = new File(accountsListDir);
|
||||||
|
File[] allFiles = dir.listFiles();
|
||||||
|
if (accounts != null && allFiles != null) {
|
||||||
|
for (File file : allFiles ) {
|
||||||
|
// First grab file identifier as KEY
|
||||||
|
String accountIdentifier = file.getName();
|
||||||
|
String accountFromFile = accountsListDir + "/" + accountIdentifier;
|
||||||
|
System.out.println("accountIdentifier found in file is " + accountIdentifier);
|
||||||
|
System.out.println("account identifier with dir path is " + accountFromFile);
|
||||||
|
accounts.accountsList.put(accountIdentifier, config.GetJsonObjectFromFile(accountFromFile, IndividualAccount.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("The try-catch in IndividualBank.java failed to complete. Printing stack trace");
|
||||||
|
// e.printStackTrace();
|
||||||
|
// Falling into this catch just means the file needs to be made
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existingFile)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// We assume the bank dir is created by server. Create this banks dir
|
||||||
|
// config.CreateDirectory("bank/" + routingNumber);
|
||||||
|
// Create this banks initial accounts dir
|
||||||
|
config.CreateDirectory(CONFIG_LOCATION + routingNumber + "/accounts");
|
||||||
|
|
||||||
|
// Flash initial account configuration file for this bank
|
||||||
|
FlashConfig("accounts");
|
||||||
|
} catch (Exception e) {
|
||||||
|
Keeblarcraft.LOGGER.error("Could not write to file in IndividualBank");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A modified config reader is needed here for when each IndividualAccount is read in - the name is taken from that and is attached to the
|
||||||
|
// 'accountsListFromName' structure. This makes it no worse than O(n) to fill these two structures in.
|
||||||
|
// NOTE: This is an *EXPENSIVE* operation! Future us might need to update this. Also note a method is needed for everytime a player opens a new account
|
||||||
|
// or gets put on one to update the map every time
|
||||||
|
if (accounts != null) {
|
||||||
|
for (Entry<String, IndividualAccount> account : accounts.accountsList.entrySet()) {
|
||||||
|
// We must loop over the string of holders for each account as well to make the flattened accountsListFromName map
|
||||||
|
List<String> accountHolders = account.getValue().GetAccountHolders();
|
||||||
|
|
||||||
|
// Match each user to the secondary map & add to list-value if not existing
|
||||||
|
for (String accountHolder : accountHolders) {
|
||||||
|
if (accounts.accountsListFromName.containsKey(accountHolder)) {
|
||||||
|
// Case 1: User exists, update map entry
|
||||||
|
accounts.accountsListFromName.get(accountHolder).add(account.getKey()); // Add a new account id to this person in the new flat map
|
||||||
|
} else {
|
||||||
|
// Case 2: User does not already exist; add a new map entry
|
||||||
|
accounts.accountsListFromName.put(accountHolder, List.of(account.getKey())); // Store name as key, and new List with the value of ACCOUNT #
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
numberOfAccounts = accounts.accountsList.size();
|
||||||
|
} else {
|
||||||
|
accounts = new Accounts();
|
||||||
|
numberOfAccounts = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetBankName
|
||||||
|
///
|
||||||
|
/// @return Returns this banks name
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public String GetBankName() {
|
||||||
|
return registeredBankName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetAccountsOfUser
|
||||||
|
///
|
||||||
|
/// @param[in] uuid is the players UUID to check
|
||||||
|
///
|
||||||
|
/// @brief Gets all the accounts a user has at this bank by UUID
|
||||||
|
///
|
||||||
|
/// @return List of all bank accounts. List will be EMPTY if no accounts
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public List<IndividualAccount> GetAccountsOfUser(String uuid) {
|
||||||
|
List<IndividualAccount> accountsFromUser = new ArrayList<IndividualAccount>();
|
||||||
|
List<String> listOfAccounts = accounts.accountsListFromName.get(uuid);
|
||||||
|
|
||||||
|
if (listOfAccounts != null && !listOfAccounts.isEmpty()) {
|
||||||
|
for (String listOfAccount : listOfAccounts) {
|
||||||
|
accountsFromUser.add(accounts.accountsList.get(listOfAccount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return accountsFromUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetBankBalance
|
||||||
|
///
|
||||||
|
/// @return The banks balance
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Integer GetBankBalance() {
|
||||||
|
return bankMoney;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AddBankBalance
|
||||||
|
///
|
||||||
|
/// @param[in] amount Amount to add to the banks balance
|
||||||
|
///
|
||||||
|
/// @brief Adds to the banks balance
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void AddBankBalance(Integer amount) {
|
||||||
|
bankMoney += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn SubtractBankBalance
|
||||||
|
///
|
||||||
|
/// @param[in] amount Amount to subtract from banks balance
|
||||||
|
///
|
||||||
|
/// @brief Subtracts from the banks balance
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void SubtractBankBalance(Integer amount) {
|
||||||
|
bankMoney -= amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn SetBankBalance
|
||||||
|
///
|
||||||
|
/// @param[in] amount Amount to give the bank
|
||||||
|
///
|
||||||
|
/// @brief Set the banks balance
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void SetBankBalance(Integer amount) {
|
||||||
|
bankMoney = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IsBankInsured
|
||||||
|
///
|
||||||
|
/// @return True if bank is insured, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean IsBankInsured() {
|
||||||
|
return kbicInsured;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn InsuranceAmount
|
||||||
|
///
|
||||||
|
/// @brief Get the insurance amount at this bank
|
||||||
|
///
|
||||||
|
/// @return Insurance amount
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Integer InsuranceAmount() {
|
||||||
|
Integer insuredAmnt = 0;
|
||||||
|
if (kbicInsured) {
|
||||||
|
insuredAmnt = kbicInsuredAmount;
|
||||||
|
} else {
|
||||||
|
insuredAmnt = 0;
|
||||||
|
}
|
||||||
|
return insuredAmnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn UpdateBankAccounts
|
||||||
|
///
|
||||||
|
/// @brief Flashes bank account information to disk; updates volatile
|
||||||
|
/// memory of banking information for this bank
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void UpdateBankAccounts(String newHolderName, String newHolderUuid, String accountIdentifier, IndividualAccount newAccountOnly) {
|
||||||
|
// Update the fast-access map first
|
||||||
|
System.out.println("UpdateBankAccounts called with information " + newHolderName + " " + newHolderUuid + " " + accountIdentifier);
|
||||||
|
if (accounts.accountsListFromName.containsKey(newHolderUuid)) {
|
||||||
|
// Check if user is already in map
|
||||||
|
accounts.accountsListFromName.get(newHolderUuid).add(accountIdentifier);
|
||||||
|
} else {
|
||||||
|
// Add new entry to map
|
||||||
|
List<String> userAccountList = new ArrayList<String>(); // Lists are immutable; must make ArrayList
|
||||||
|
userAccountList.add(accountIdentifier);
|
||||||
|
accounts.accountsListFromName.put(newHolderUuid, userAccountList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update regular account list
|
||||||
|
if (accounts.accountsList.containsKey(accountIdentifier)) {
|
||||||
|
// This path assumes we are adding a holder as opposed to adding an account (else, how else would this work?)
|
||||||
|
System.out.println("Account found in accounts list, adding this person as a holder instead");
|
||||||
|
accounts.accountsList.get(accountIdentifier).AddAccountHolder(newHolderName, newHolderUuid);
|
||||||
|
} else {
|
||||||
|
// Non-existent account means a new one!
|
||||||
|
System.out.println("Brand new account creation, adding!");
|
||||||
|
accounts.accountsList.put(accountIdentifier, newAccountOnly);
|
||||||
|
numberOfAccounts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Flashing configuration file");
|
||||||
|
FlashConfig("bank/" + routingNumber + "/accounts");
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetRoutingNumber
|
||||||
|
///
|
||||||
|
/// @return Routing number
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Integer GetRoutingNumber() {
|
||||||
|
return this.routingNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AddMoneyToAccount
|
||||||
|
///
|
||||||
|
/// @param[in] accountId is the account to add money to at this bank
|
||||||
|
///
|
||||||
|
/// @param[in] amount is the amount of money to add to this account
|
||||||
|
///
|
||||||
|
/// @brief Adds money to an account at this bank if it exists
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void AddMoneyToAccount(String accountId, Integer amount) {
|
||||||
|
IndividualAccount account = accounts.accountsList.get(AccountNumberGenerator.GetAccountNumberFromId(accountId));
|
||||||
|
System.out.println("Received account # " + accountId + " and money amnt " + amount);
|
||||||
|
System.out.println("Is account null? " + (account == null ? "YES":"NO"));
|
||||||
|
|
||||||
|
System.out.println("accounts.accountList.size() : " + accounts.accountsList.size());
|
||||||
|
for (Entry<String, IndividualAccount> accnt : accounts.accountsList.entrySet()) {
|
||||||
|
System.out.println("Account num in entry: " + accnt.getValue().GetAccountNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account != null && account.Deposit(amount)) {
|
||||||
|
GenerateTransactionReport(TransactionMetadata.TRANSACTION_TYPE.DEPOSIT, new Pair<>("ADMIN", "ADMIN"), new Pair<>("ADMIN", "ADMIN"), amount, "ADMIN");
|
||||||
|
FlashConfig("bank/" + routingNumber + "/accounts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn SubtractMoneyFromAccount
|
||||||
|
///
|
||||||
|
/// @param[in] accountId is the account to subtract money to at this bank
|
||||||
|
///
|
||||||
|
/// @param[in] amount is the amount of money to subtract to this account
|
||||||
|
///
|
||||||
|
/// @brief Subtracts money from an account at this bank if it exists
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void SubtractMoneyFromAccount(String accountId, Integer amount) {
|
||||||
|
IndividualAccount account = accounts.accountsList.get(AccountNumberGenerator.GetAccountNumberFromId(accountId));
|
||||||
|
|
||||||
|
if (account != null && account.Withdraw(amount)) {
|
||||||
|
GenerateTransactionReport(TransactionMetadata.TRANSACTION_TYPE.WITHDRAWAL, new Pair<>("ADMIN", "ADMIN"), new Pair<>("ADMIN", "ADMIN"), amount, "ADMIN");
|
||||||
|
FlashConfig("bank/" + routingNumber + "/accounts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn SetMoneyOnAccount
|
||||||
|
///
|
||||||
|
/// @param[in] accountId is the account number
|
||||||
|
///
|
||||||
|
/// @param[in] amount is the new balance to give this account
|
||||||
|
///
|
||||||
|
/// @brief Sets a balance on an account if it exists
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void SetMoneyOnAccount(String accountId, Integer amount) {
|
||||||
|
IndividualAccount account = accounts.accountsList.get(accountId);
|
||||||
|
System.out.println("Is account null? " + (account == null ? "YES" : "NO"));
|
||||||
|
System.out.println("Received account # " + accountId + " and money amnt " + amount);
|
||||||
|
|
||||||
|
for (Entry<String, IndividualAccount> debug : accounts.accountsList.entrySet()) {
|
||||||
|
System.out.println("ACCOUNT ID: " + debug.getKey());
|
||||||
|
System.out.println("ACCOUNT NUM: " + debug.getValue().GetAccountNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account != null) {
|
||||||
|
account.SetMoney(amount);
|
||||||
|
GenerateTransactionReport(TransactionMetadata.TRANSACTION_TYPE.OTHER, new Pair<>("ADMIN", "ADMIN"), new Pair<>("ADMIN", "ADMIN"), amount, "ADMIN");
|
||||||
|
FlashConfig("bank/" + routingNumber + "/accounts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn CreateAccount
|
||||||
|
///
|
||||||
|
/// @param[in] holderUuid is the new holders UUID of this account
|
||||||
|
///
|
||||||
|
/// @param[in] holderName is the display name of the holder
|
||||||
|
///
|
||||||
|
/// @param[in] accountTypeStr is the account type as a string (will be number)
|
||||||
|
///
|
||||||
|
/// @brief Create a new account at this bank
|
||||||
|
///
|
||||||
|
/// @return True if account can be created, false if it fails
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean CreateAccount(String holderUuid, String holderName, ACCOUNT_TYPE accountType) {
|
||||||
|
Boolean success = false;
|
||||||
|
if (accounts.accountsList.size() <= maxBankAccounts) {
|
||||||
|
// Verify this isn't a blacklisted user
|
||||||
|
System.out.println("Is user bank locked? " + lockedUsers.contains(holderName));
|
||||||
|
if (!lockedUsers.contains(holderName)) {
|
||||||
|
Integer maxAttempts = 15; // Reasonably a unique bank account should pop up within 1000 generations. If not, the user may try again.
|
||||||
|
String accountId = AccountNumberGenerator.GenerateNewAccountNumber(bankFourLetterIdentifier, routingNumber, ACCOUNT_TYPES.get(accountType), holderName);
|
||||||
|
|
||||||
|
System.out.println("Account generator came back with bank account id { " + accountId + " }");
|
||||||
|
System.out.println("4 letter bank: " + AccountNumberGenerator.GetFinancialSymbolFromId(accountId));
|
||||||
|
System.out.println("Routing: " + AccountNumberGenerator.GetRoutingNumberFromId(accountId));
|
||||||
|
System.out.println("Account type: " + AccountNumberGenerator.GetAccountTypeFromId(accountId));
|
||||||
|
System.out.println("RNG Account number: " + AccountNumberGenerator.GetAccountNumberFromId(accountId));
|
||||||
|
|
||||||
|
// TODO: Fix in future with a method that will guarentee a one-time necessary number generator. Statistically speaking; this will be okay for the
|
||||||
|
// entire life time of the server. BUT, you never know!
|
||||||
|
while (maxAttempts != 0 && !accounts.accountsList.containsKey(AccountNumberGenerator.GetAccountNumberFromId(accountId))) {
|
||||||
|
accountId = AccountNumberGenerator.GenerateNewAccountNumber(bankFourLetterIdentifier, routingNumber, ACCOUNT_TYPES.get(accountType), holderName);
|
||||||
|
System.out.println("Account generator came back with bank account id { " + accountId + " }");
|
||||||
|
maxAttempts--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final check to add the account
|
||||||
|
String actualAccountNumber = AccountNumberGenerator.GetAccountNumberFromId(accountId);
|
||||||
|
System.out.println("Bank account identifier is { " + actualAccountNumber + " }. Is this already an existing account? " + accounts.accountsList.containsKey(actualAccountNumber));
|
||||||
|
if (!accounts.accountsList.containsKey(actualAccountNumber)) {
|
||||||
|
IndividualAccount newAccount = new IndividualAccount(actualAccountNumber, this.routingNumber, List.of(holderName),
|
||||||
|
List.of(holderUuid), false, 0,
|
||||||
|
"", accountType, bankFourLetterIdentifier);
|
||||||
|
System.out.println("Updating accounts list for this bank");
|
||||||
|
UpdateBankAccounts(holderName, holderUuid, actualAccountNumber, newAccount);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fromParty is expected to be UUID mapped to username
|
||||||
|
// toParty is expected to be UUID mapped to username
|
||||||
|
// NOTHING should be null in this generation!
|
||||||
|
public void GenerateTransactionReport(TransactionMetadata.TRANSACTION_TYPE transactionType, Pair<String, String> fromParty, Pair<String, String> toParty, Integer amount, String reason) {
|
||||||
|
// The transaction ID is to be formatted (for now) as #-FROMUUID-TOUUID-RNG
|
||||||
|
// For this version, we pray there is not a duplicate RNG dupe and no checking is done for now!
|
||||||
|
StringBuilder transactionId = new StringBuilder("#" + fromParty.GetKey() + "-" + toParty.GetKey() + Integer.toString(new Random().nextInt(100_000_000) + 1_000_000));
|
||||||
|
TransactionMetadata trans = new TransactionMetadata(transactionType, fromParty, toParty, amount, transactionId.toString(), reason);
|
||||||
|
|
||||||
|
// This is a hacky solution to make sure the transaction file doesn't exist. It is "technically" possible we fail 10 times in a row
|
||||||
|
// then can't write and thus no papertrail is left - however if the RNG fails to make a unique enough number with these UUID's between
|
||||||
|
// 1 million and 100 million then we have other issues to worry about.
|
||||||
|
int maxTries = 10;
|
||||||
|
// We now want to iterate over the files in the transaction dir and pop a new file in
|
||||||
|
while (config.DoesFileExist("bank/" + routingNumber + "/transactions/" + transactionId) && maxTries-- >= 0) {
|
||||||
|
transactionId.append(Integer.toString(new Random().nextInt(100_000_000) + 1_000_000));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.DoesFileExist("bank/" + routingNumber + "/transactions/" + transactionId)) {
|
||||||
|
config.WriteToJsonFile("bank/" + routingNumber + "/transactions/" + transactionId + ".json", trans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The value 0 should be treated as either non-exist
|
||||||
|
public Optional<Integer> GetAccountBalance(String accountId) {
|
||||||
|
Optional<Integer> amount = Optional.empty();
|
||||||
|
if (accounts.accountsList.containsKey(accountId)) {
|
||||||
|
IndividualAccount account = accounts.accountsList.get(accountId);
|
||||||
|
amount = Optional.of(account.GetAccountBalance());
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn LockAccountHolder
|
||||||
|
///
|
||||||
|
/// @param[in] holderName is player to lock account
|
||||||
|
///
|
||||||
|
/// @brief Locks all accounts under a name for this user
|
||||||
|
///
|
||||||
|
/// @return True if lock succeeds, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean LockAccountHolder(String holderName) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
int accountIter = 0;
|
||||||
|
for (Entry<String, List<String>> holderAccounts : accounts.accountsListFromName.entrySet()) {
|
||||||
|
accounts.accountsList.get(holderAccounts.getValue().get(accountIter++)).LockAccount();
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn CloseAccount
|
||||||
|
///
|
||||||
|
/// @param[in] accountId is id of account to be closed
|
||||||
|
///
|
||||||
|
/// @brief Closes an account
|
||||||
|
///
|
||||||
|
/// @note Balance of account must be 0 to close successfully
|
||||||
|
///
|
||||||
|
/// @return True if can close, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean CloseAccount(String accountId, String playerUuid) {
|
||||||
|
boolean success = false;
|
||||||
|
|
||||||
|
if (accounts.accountsList.containsKey(accountId) && accounts.accountsList.get(accountId).GetAccountBalance() == 0) {
|
||||||
|
System.out.println("Closing user account...");
|
||||||
|
// The below two lists should ALWAYS be in sync. If there is a discrepancy; this may segfault!
|
||||||
|
accounts.accountsList.remove(accountId);
|
||||||
|
accounts.accountsListFromName.get(playerUuid).remove(accountId);
|
||||||
|
FlashConfig("bank/" + routingNumber + "/accounts");
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn HasAccount
|
||||||
|
///
|
||||||
|
/// @param[in] accountIdentifier account number to check to see if it exists
|
||||||
|
/// at this bank
|
||||||
|
///
|
||||||
|
/// @brief See if an account identifier belongs to this bank
|
||||||
|
///
|
||||||
|
/// @return True if this bank has this account identifier, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean HasAccount(String accountIdentifier) {
|
||||||
|
return accounts.accountsList.containsKey(accountIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IsValidWithdrawal
|
||||||
|
///
|
||||||
|
/// @param[in] withdrawalAmount The amount to be withdrawn
|
||||||
|
///
|
||||||
|
/// @param[in] accountIdentifier account to withdraw from
|
||||||
|
///
|
||||||
|
/// @brief Verifies if a withdrawal will succeed on an account prior to
|
||||||
|
/// the actual withdrawal itself
|
||||||
|
///
|
||||||
|
/// @return True if this account can afford this withdrawal. False if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean IsValidWithdrawal(Integer withdrawalAmount, String accountIdentifier) {
|
||||||
|
boolean isValid = false;
|
||||||
|
|
||||||
|
System.out.println("Account id: " + accountIdentifier);
|
||||||
|
System.out.println("Short account id: " + AccountNumberGenerator.GetAccountNumberFromId(accountIdentifier));
|
||||||
|
String localAccountId = AccountNumberGenerator.GetAccountNumberFromId(accountIdentifier);
|
||||||
|
System.out.println("Amount to withdraw: " + withdrawalAmount);
|
||||||
|
System.out.println("accounts list map: " + accounts.accountsList);
|
||||||
|
if (accounts.accountsList.containsKey(localAccountId)) {
|
||||||
|
IndividualAccount account = accounts.accountsList.get(localAccountId);
|
||||||
|
System.out.println("Is account null? " + (account == null));
|
||||||
|
|
||||||
|
if (account.CanWithdraw(withdrawalAmount)) {
|
||||||
|
isValid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IsAccountHolder
|
||||||
|
///
|
||||||
|
/// @param[in] accountIdentifier Account to check
|
||||||
|
///
|
||||||
|
/// @param[in] uuid Is players UUID to see if they are on this account
|
||||||
|
///
|
||||||
|
/// @brief Check if a player is on this account
|
||||||
|
///
|
||||||
|
/// @return True if player is on this account. False if not or account
|
||||||
|
/// does not exist
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean IsAccountHolder(String accountIdentifier, String uuid) {
|
||||||
|
Boolean isHolder = false;
|
||||||
|
|
||||||
|
System.out.println("Looking for accountIdentifier: " + accountIdentifier);
|
||||||
|
for (Entry<String, IndividualAccount> account : accounts.accountsList.entrySet()) {
|
||||||
|
System.out.println("ACCOUNT ID: " + account.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify account exists first
|
||||||
|
if (accounts.accountsList.containsKey(accountIdentifier)) {
|
||||||
|
isHolder = accounts.accountsList.get(accountIdentifier).IsHolder(uuid);
|
||||||
|
} else {
|
||||||
|
System.out.println("Account identifier found to not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
return isHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn FlashConfig
|
||||||
|
///
|
||||||
|
/// @param[in] dirName is config to flash to. Banking is not trivial and will
|
||||||
|
/// require separate files to be updated at different locations!
|
||||||
|
///
|
||||||
|
/// @brief Flashes the config to the disk
|
||||||
|
///
|
||||||
|
/// @note dirName should be the relative full path to dir
|
||||||
|
/// @note Function will be removed in near future for SQL but is
|
||||||
|
/// expensive to run as it flashes everything even if un-updated
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void FlashConfig(String dirName) {
|
||||||
|
for (Entry<String, IndividualAccount> singleAccount : accounts.accountsList.entrySet()) {
|
||||||
|
System.out.println("FlashConfig. dirname: " + dirName);
|
||||||
|
// Iterate over each one & verify if a file exists inside the dir. if it does;
|
||||||
|
// nuke it and
|
||||||
|
// replace it with the new contents in memory
|
||||||
|
String accountNum = singleAccount.getKey().toString();
|
||||||
|
|
||||||
|
// delete file
|
||||||
|
File file = new File(dirName + "/" + accountNum + ".json");
|
||||||
|
System.out.println("Checking path: " + dirName + "/" + accountNum + ".json");
|
||||||
|
if (file.exists()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-flash file
|
||||||
|
config.WriteToJsonFile(dirName + "/" + accountNum + ".json", singleAccount.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package jesse.keeblarcraft.BankMgr;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
|
||||||
|
|
||||||
|
// All details that involve a transaction attempt
|
||||||
|
public class TransactionMetadata {
|
||||||
|
public enum TRANSACTION_TYPE {
|
||||||
|
DEBIT,
|
||||||
|
CREDIT,
|
||||||
|
WITHDRAWAL,
|
||||||
|
DEPOSIT,
|
||||||
|
OTHER
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<String, String> fromParty; // Account ID
|
||||||
|
public Pair<String, String> toParty; // Account ID or party (like ATM/self,etc)
|
||||||
|
public Integer amount;
|
||||||
|
public String transactionId;
|
||||||
|
public TRANSACTION_TYPE transactionType;
|
||||||
|
public String reason;
|
||||||
|
|
||||||
|
public TransactionMetadata(TRANSACTION_TYPE transactionType, Pair<String, String> fromParty, Pair<String, String> toParty, Integer amount, String reason, String transactionId) {
|
||||||
|
this.transactionType = transactionType;
|
||||||
|
this.transactionId = transactionId;
|
||||||
|
this.amount = amount;
|
||||||
|
this.toParty = toParty;
|
||||||
|
this.fromParty = fromParty;
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package jesse.keeblarcraft.Callbacks;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public interface MobSpawnCallback {
|
||||||
|
Event<MobSpawnCallback> EVENT = EventFactory.createArrayBacked(MobSpawnCallback.class,
|
||||||
|
(listeners) -> (world, mob) -> {
|
||||||
|
for (MobSpawnCallback listener : listeners) {
|
||||||
|
ActionResult result = listener.interact(world, mob);
|
||||||
|
|
||||||
|
if (result != ActionResult.PASS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
|
||||||
|
ActionResult interact(World world, MobEntity mob);
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package jesse.keeblarcraft.ChatStuff;
|
||||||
|
|
||||||
|
public class ChatFormatting {
|
||||||
|
// These are for Minecraft chat box
|
||||||
|
public static String COLOR_START = "§";
|
||||||
|
public static String COLOR_END = "§f";
|
||||||
|
public static enum COLOR_CODE {
|
||||||
|
BLUE,
|
||||||
|
GRAY,
|
||||||
|
GOLD,
|
||||||
|
RED,
|
||||||
|
GREEN
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn getColor
|
||||||
|
///
|
||||||
|
/// @param[in] code is the color code that is desired
|
||||||
|
///
|
||||||
|
/// @brief Returns the MINECRAFT color code in string form to help build
|
||||||
|
/// colored messages for players
|
||||||
|
///
|
||||||
|
/// @return String representation of color code
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static String GetColor(COLOR_CODE code) {
|
||||||
|
String colorStr = COLOR_START;
|
||||||
|
return switch (code) {
|
||||||
|
case BLUE -> colorStr + "9";
|
||||||
|
case GRAY -> colorStr + "7";
|
||||||
|
case GOLD -> colorStr + "6";
|
||||||
|
case RED -> colorStr + "4";
|
||||||
|
case GREEN -> colorStr + "2";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
186
src/main/java/jesse/keeblarcraft/ChatStuff/ChatMenu.java
Normal file
186
src/main/java/jesse/keeblarcraft/ChatStuff/ChatMenu.java
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
package jesse.keeblarcraft.ChatStuff;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatFormatting.COLOR_CODE;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.MutableText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
// Create a "chat menu" which is just a menu in chat with pages that a user can click to display
|
||||||
|
// the next page.
|
||||||
|
public class ChatMenu {
|
||||||
|
private ArrayList<Text> msgList = new ArrayList<>();
|
||||||
|
private Text header;
|
||||||
|
private Text headerFooterSpacing = Text.of(" ");
|
||||||
|
private Text leftArrow;
|
||||||
|
private Text rightArrow;
|
||||||
|
private int pageLimit = 25; // Messages per page in this menu (//TODO: This is being increased to show all info at once. Need to add callback to flip a page somehow)
|
||||||
|
private int pageCount = 1; // Calculated at runtime
|
||||||
|
private ChatMsg formatter = new ChatMsg();
|
||||||
|
private int currentPage = 0;
|
||||||
|
ServerPlayerEntity lastTarget;
|
||||||
|
|
||||||
|
private enum TURN_DIRECTION {
|
||||||
|
BACK,
|
||||||
|
FORWARD
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChatMenu() {
|
||||||
|
// Initialize default header and arrows
|
||||||
|
header = Text.of("[----- HELP MENU -----]");
|
||||||
|
header = formatter.ColorMsg(header, COLOR_CODE.GOLD);
|
||||||
|
|
||||||
|
leftArrow = Text.of("<<");
|
||||||
|
leftArrow = formatter.ColorMsg(leftArrow, COLOR_CODE.GOLD);
|
||||||
|
|
||||||
|
rightArrow = Text.of(">>");
|
||||||
|
rightArrow = formatter.ColorMsg(rightArrow, COLOR_CODE.GOLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetHeader(Text header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetHeader(ChatMsg msg) {
|
||||||
|
this.header = msg.mutableText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLeftArrow(Text leftArrow) {
|
||||||
|
this.leftArrow = leftArrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetRightArrow(Text rightArrow) {
|
||||||
|
this.rightArrow = rightArrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Text MakeFooter() {
|
||||||
|
// leftArrow = (Text) formatter.MakeClickCallback((MutableText) leftArrow, new ChatMsgClickEvent(() -> TurnPage(TURN_DIRECTION.BACK)));
|
||||||
|
// leftArrow = Text.literal("TEST").styled(style -> style.withClickEvent(new ChatMsgClickEvent(() -> {
|
||||||
|
// System.out.println("Click event called from server");
|
||||||
|
// })));
|
||||||
|
|
||||||
|
MutableText footer = (MutableText) leftArrow;
|
||||||
|
|
||||||
|
// This spacing is arbitrary and may be changed in future. It just looks OK for now
|
||||||
|
footer.append(Text.of(" "));
|
||||||
|
|
||||||
|
// rightArrow = formatter.MakeClickCallback((MutableText) rightArrow, new ChatMsgClickEvent(() -> TurnPage(TURN_DIRECTION.FORWARD)));
|
||||||
|
footer.append(rightArrow);
|
||||||
|
|
||||||
|
return (Text) footer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TurnPage(TURN_DIRECTION turn) {
|
||||||
|
System.out.println("TurnPage called");
|
||||||
|
// The page we need to turn to will be calculated as so:
|
||||||
|
// msgList[index] where index = (0 + pageLimit) * currentPage(+- 1)
|
||||||
|
pageCount = (int) Math.ceil(msgList.size() / (double) pageLimit);
|
||||||
|
|
||||||
|
// Guard clause: Cannot turn further than end of all pages or before page 1
|
||||||
|
if ((turn == TURN_DIRECTION.BACK && currentPage == 1) || (turn == TURN_DIRECTION.FORWARD && currentPage == pageCount)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust new page number
|
||||||
|
if (turn == TURN_DIRECTION.BACK) {
|
||||||
|
--currentPage;
|
||||||
|
} else {
|
||||||
|
++currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send updated message to player (msg takes care of printing page)
|
||||||
|
if (lastTarget != null) {
|
||||||
|
SendMsg(lastTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Text MakeHeader() {
|
||||||
|
MutableText head = (MutableText) Text.of(" ");
|
||||||
|
head.append(header);
|
||||||
|
head.append(Text.of(" "));
|
||||||
|
|
||||||
|
header = (Text) head;
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMsg(Text newMsg) {
|
||||||
|
msgList.add(newMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMsg(String newMsg) {
|
||||||
|
AddMsg(Text.of(newMsg));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMsg(ChatMsg newMsg) {
|
||||||
|
AddMsg(newMsg.mutableText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMsg(List<ChatMsg> newMsgList) {
|
||||||
|
for (int i = 0; i < newMsgList.size(); i++) {
|
||||||
|
AddMsg(newMsgList.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddNewLine() {
|
||||||
|
AddMsg(Text.of(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearList() {
|
||||||
|
msgList.clear();
|
||||||
|
pageCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPageLimit(int limit) {
|
||||||
|
if (limit >= 1) {
|
||||||
|
pageLimit = limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the current page
|
||||||
|
public void SendMsg(ServerPlayerEntity target) {
|
||||||
|
// Calculate number of pages
|
||||||
|
pageCount = (int) Math.ceil(msgList.size() / (double) pageLimit);
|
||||||
|
int startIdx = currentPage * pageLimit;
|
||||||
|
|
||||||
|
// Send the header
|
||||||
|
target.sendMessage(MakeHeader());
|
||||||
|
int maxCapoutDebug = 20;
|
||||||
|
|
||||||
|
int stopIdx = startIdx + pageLimit;
|
||||||
|
for (int pageItem = startIdx; pageItem < stopIdx && pageItem < msgList.size(); pageItem++) {
|
||||||
|
target.sendMessage(msgList.get(pageItem));
|
||||||
|
|
||||||
|
--maxCapoutDebug;
|
||||||
|
|
||||||
|
if (maxCapoutDebug <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the body
|
||||||
|
// int msgIndex = 0;
|
||||||
|
// for (int page = 0; page < pageCount && msgList.get(msgIndex) != null; page++) {
|
||||||
|
// for (int i = 0; i < pageLimit && msgList.get(msgIndex) != null; i++) {
|
||||||
|
// Text msg = msgList.get(msgIndex);
|
||||||
|
// if (msg == null) {
|
||||||
|
// target.sendMessage(msg);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Send the footer
|
||||||
|
target.sendMessage(MakeFooter());
|
||||||
|
|
||||||
|
// ChatMsg temp = new ChatMsg();
|
||||||
|
// Text test = (Text) temp.MakeCopyableTxt("<<", "Click to copy", "Copied string");
|
||||||
|
// Text test2 = (Text) temp.MakeCopyableTxt(">>", "Click to copy", "Copied");
|
||||||
|
|
||||||
|
// MutableText temp3 = (MutableText) test;
|
||||||
|
// temp3.append(test2);
|
||||||
|
|
||||||
|
// target.sendMessage((Text) temp3);
|
||||||
|
}
|
||||||
|
}
|
218
src/main/java/jesse/keeblarcraft/ChatStuff/ChatMsg.java
Normal file
218
src/main/java/jesse/keeblarcraft/ChatStuff/ChatMsg.java
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* ChatMsg
|
||||||
|
*
|
||||||
|
* Helpful utility for pretty printing in chat in the game with different supported functions and levels
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jesse.keeblarcraft.ChatStuff;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatFormatting.COLOR_CODE;
|
||||||
|
import net.minecraft.text.ClickEvent;
|
||||||
|
import net.minecraft.text.HoverEvent;
|
||||||
|
import net.minecraft.text.MutableText;
|
||||||
|
import net.minecraft.text.Style;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public class ChatMsg {
|
||||||
|
public static Text regularText = Text.of("");
|
||||||
|
public static MutableText mutableText = (MutableText) regularText;
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn MakeCopyableTxt
|
||||||
|
///
|
||||||
|
/// @param[in] terminalTxt is the text to be seen on screen
|
||||||
|
///
|
||||||
|
/// @param[in] hoverTxt is the desired text to be seen in a new hover event
|
||||||
|
///
|
||||||
|
/// @param[in] copyInt is an integer argument that can be copied when the
|
||||||
|
/// player clicks on the chat message
|
||||||
|
///
|
||||||
|
/// @brief Creates a copyable text block for the player
|
||||||
|
///
|
||||||
|
/// @return MutableText of text intended to be used to send to player
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static MutableText MakeCopyableTxt(String terminalTxt, String hoverTxt, Integer copyInt) {
|
||||||
|
return MakeCopyableTxt(terminalTxt, hoverTxt, Integer.toString(copyInt));
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn MakeCopyableTxt
|
||||||
|
///
|
||||||
|
/// @param[in] terminalTxt is the text to be seen on screen
|
||||||
|
///
|
||||||
|
/// @param[in] hoverTxt is the desired text to be seen in a new hover event
|
||||||
|
///
|
||||||
|
/// @param[in] expandedList takes in a list of strings that can be copied
|
||||||
|
/// when the player clicks on a chat message
|
||||||
|
///
|
||||||
|
/// @brief Creates a copyable text block for the player
|
||||||
|
///
|
||||||
|
/// @return MutableText of text intended to be used to send to player
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static MutableText MakeCopyableTxt(String terminalTxt, String hoverTxt, List<String> expandedList) {
|
||||||
|
StringBuilder expanded = new StringBuilder("[");
|
||||||
|
int index = 0;
|
||||||
|
for (String str : expandedList) {
|
||||||
|
expanded.append(str);
|
||||||
|
|
||||||
|
// Add delimiter if next index is not at size
|
||||||
|
if (++index < expandedList.size()) {
|
||||||
|
expanded.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expanded.append("]");
|
||||||
|
|
||||||
|
return MakeCopyableTxt(terminalTxt, hoverTxt, expanded.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This will be added eventually; but requires Mixin black magic
|
||||||
|
// public MutableText MakeClickCallback(MutableText text, ChatMsgClickEvent callback) {
|
||||||
|
// text.styled(style -> style.withClickEvent(callback));
|
||||||
|
// return text;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn MakeCopyableTxt
|
||||||
|
///
|
||||||
|
/// @param[in] terminalTxt is the text to be seen on screen
|
||||||
|
///
|
||||||
|
/// @param[in] hoverTxt is the desired text to be seen in a new hover event
|
||||||
|
///
|
||||||
|
/// @param[in] copyStr is a regular string that can be copied when the player
|
||||||
|
/// clicks on a chat message
|
||||||
|
///
|
||||||
|
/// @brief Creates a copyable text block for the player
|
||||||
|
///
|
||||||
|
/// @return MutableText of text intended to be used to send to player
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static MutableText MakeCopyableTxt(String terminalTxt, String hoverTxt, String copyStr) {
|
||||||
|
Text copyableText = Text.of(terminalTxt);
|
||||||
|
MutableText testTxt = (MutableText) copyableText;
|
||||||
|
testTxt.setStyle(Style.EMPTY.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, copyStr))
|
||||||
|
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of(hoverTxt))));
|
||||||
|
|
||||||
|
mutableText = testTxt;
|
||||||
|
regularText = copyableText;
|
||||||
|
|
||||||
|
return testTxt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ColorMsg
|
||||||
|
///
|
||||||
|
/// @param[in] msg is an integer message that is desired to be colored
|
||||||
|
///
|
||||||
|
/// @param[in] color is the color option
|
||||||
|
///
|
||||||
|
/// @brief Creates a formatted string that will be colored at the
|
||||||
|
/// specification of the developer
|
||||||
|
///
|
||||||
|
/// @return Formatted string of colored text
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static String ColorMsg(Integer msg, COLOR_CODE color) {
|
||||||
|
regularText = Text.of(ChatFormatting.GetColor(color) + msg + ChatFormatting.COLOR_END);
|
||||||
|
mutableText = (MutableText) regularText;
|
||||||
|
return ChatFormatting.GetColor(color) + msg + ChatFormatting.COLOR_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ColorMsg
|
||||||
|
///
|
||||||
|
/// @param[in] msg is an Text object
|
||||||
|
///
|
||||||
|
/// @param[in] color is the color option
|
||||||
|
///
|
||||||
|
/// @brief Creates a formatted string that will be colored at the
|
||||||
|
/// specification of the developer
|
||||||
|
///
|
||||||
|
/// @return Text object but with the minecraft color injected around
|
||||||
|
/// string
|
||||||
|
///
|
||||||
|
/// @note THIS WILL REMOVE FORMATTING ON THE TEXT. If you need to keep
|
||||||
|
/// formatting/other specialties, format a string with the color
|
||||||
|
/// first with functions inside this class.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Text ColorMsg(Text msg, COLOR_CODE color) {
|
||||||
|
regularText = Text.of(ChatFormatting.GetColor(color) + msg.getString() + ChatFormatting.COLOR_END);
|
||||||
|
mutableText = (MutableText) regularText;
|
||||||
|
return regularText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ColorMsg
|
||||||
|
///
|
||||||
|
/// @param[in] msg is a list of strings that is desired to all be colored
|
||||||
|
/// the same
|
||||||
|
///
|
||||||
|
/// @param[in] color is the color option
|
||||||
|
///
|
||||||
|
/// @brief Creates a formatted list of strings that will be colored
|
||||||
|
/// at the specification of the developer and will be returned as
|
||||||
|
/// a list
|
||||||
|
///
|
||||||
|
/// @return Formatted list of strings
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static List<String> ColorMsg(List<String> msg, COLOR_CODE color) {
|
||||||
|
List<String> retList = new ArrayList<String>();
|
||||||
|
|
||||||
|
for (String str : msg) {
|
||||||
|
retList.add(ChatFormatting.GetColor(color) + str + ChatFormatting.COLOR_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ColorMsg
|
||||||
|
///
|
||||||
|
/// @param[in] msg to be formatted
|
||||||
|
///
|
||||||
|
/// @param[in] color is the color option
|
||||||
|
///
|
||||||
|
/// @brief Creates a formatted string that will be colored at the
|
||||||
|
/// specification of the developer
|
||||||
|
///
|
||||||
|
/// @return Formatted string of colored text
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static String ColorMsg(String msg, COLOR_CODE color) {
|
||||||
|
return ChatFormatting.GetColor(color) + msg + ChatFormatting.COLOR_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses a help command and color codes it. assume everything up to first '.' is the
|
||||||
|
// help cmd usage and color it with primaryColor. secondaryColor applied to rest
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn FormatMsg
|
||||||
|
///
|
||||||
|
/// @param[in] helpCmd is outsourced as an intentional help message. The
|
||||||
|
/// string expects the initial format to stop with a '.'
|
||||||
|
/// delimiter.
|
||||||
|
///
|
||||||
|
/// @param[in] primaryColor is the color of the string up to the delimiter
|
||||||
|
///
|
||||||
|
/// @param[in] secondaryColor is the color after the delimiter
|
||||||
|
///
|
||||||
|
/// @brief Creates a formatted string
|
||||||
|
///
|
||||||
|
/// @return Formatted string of colored text
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static String FormatMsg(String helpCmd, COLOR_CODE primaryColor, COLOR_CODE secondaryColor) {
|
||||||
|
StringBuilder coloredStr = new StringBuilder(ChatFormatting.GetColor(primaryColor));
|
||||||
|
List<String> splitStr = List.of(helpCmd.split("\\."));
|
||||||
|
|
||||||
|
boolean isFirst = true;
|
||||||
|
for (String str : splitStr) {
|
||||||
|
coloredStr.append(str);
|
||||||
|
if (isFirst) {
|
||||||
|
isFirst = false;
|
||||||
|
coloredStr.append(ChatFormatting.GetColor(secondaryColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return coloredStr + ChatFormatting.COLOR_END;
|
||||||
|
}
|
||||||
|
}
|
@ -44,18 +44,18 @@ public class AttributeCommands {
|
|||||||
(
|
(
|
||||||
EntityArgumentType.getPlayer(context, "targetPlayer"),
|
EntityArgumentType.getPlayer(context, "targetPlayer"),
|
||||||
StringArgumentType.getString(context, "attributeName"),
|
StringArgumentType.getString(context, "attributeName"),
|
||||||
context)
|
context
|
||||||
)
|
)
|
||||||
.build();
|
).build();
|
||||||
|
|
||||||
var attributeNameDelete = CommandManager.argument("attributeName", StringArgumentType.greedyString())
|
var attributeNameDelete = CommandManager.argument("attributeName", StringArgumentType.greedyString())
|
||||||
.executes(context -> DeleteAttribute
|
.executes(context -> DeleteAttribute
|
||||||
(
|
(
|
||||||
EntityArgumentType.getPlayer(context, "targetPlayer"),
|
EntityArgumentType.getPlayer(context, "targetPlayer"),
|
||||||
StringArgumentType.getString(context, "attributeName"),
|
StringArgumentType.getString(context, "attributeName"),
|
||||||
context)
|
context
|
||||||
)
|
)
|
||||||
.build();
|
).build();
|
||||||
|
|
||||||
// Build out the argument tree here
|
// Build out the argument tree here
|
||||||
dispatcher.getRoot().addChild(attributeNode);
|
dispatcher.getRoot().addChild(attributeNode);
|
||||||
@ -75,10 +75,7 @@ public class AttributeCommands {
|
|||||||
|
|
||||||
public int ApplyAttribute(ServerPlayerEntity targetPlayer, String attributeName, CommandContext<ServerCommandSource> context) {
|
public int ApplyAttribute(ServerPlayerEntity targetPlayer, String attributeName, CommandContext<ServerCommandSource> context) {
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
System.out.println("Applying attribute");
|
|
||||||
if (context.getSource().isExecutedByPlayer()) {
|
if (context.getSource().isExecutedByPlayer()) {
|
||||||
System.out.println("Executed by player");
|
|
||||||
String result = AttributeMgr.ApplyAttribute(targetPlayer.getUuidAsString(), attributeName);
|
String result = AttributeMgr.ApplyAttribute(targetPlayer.getUuidAsString(), attributeName);
|
||||||
Keeblarcraft.LOGGER.info("[ApplyAttribute] -> " + result);
|
Keeblarcraft.LOGGER.info("[ApplyAttribute] -> " + result);
|
||||||
context.getSource().getPlayer().sendMessage(Text.of(result));
|
context.getSource().getPlayer().sendMessage(Text.of(result));
|
||||||
|
@ -1,155 +1,628 @@
|
|||||||
package jesse.keeblarcraft.Commands;
|
package jesse.keeblarcraft.Commands;
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
import com.mojang.brigadier.arguments.LongArgumentType;
|
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import static java.util.Map.entry;
|
||||||
|
|
||||||
import jesse.keeblarcraft.BankMgr.BankManager;
|
import jesse.keeblarcraft.BankMgr.BankManager;
|
||||||
|
import jesse.keeblarcraft.BankMgr.IndividualAccount;
|
||||||
|
import jesse.keeblarcraft.BankMgr.IndividualBank;
|
||||||
|
import jesse.keeblarcraft.BankMgr.BankAccountType.ACCOUNT_TYPE;
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatFormatting;
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatFormatting.COLOR_CODE;
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatMsg;
|
||||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
|
|
||||||
public class BankCommands {
|
public class BankCommands {
|
||||||
|
private static final String HELPCMD_HELP = "help";
|
||||||
|
private static final String HELPCMD_CREATE = "create";
|
||||||
|
private static final String HELPCMD_SELECT = "select";
|
||||||
|
private static final String HELPCMD_CLOSE = "close";
|
||||||
|
private static final String HELPCMD_REPORT = "report";
|
||||||
|
private static final String HELPCMD_BALANCE = "balance";
|
||||||
|
private static final String HELPCMD_EXAMPLES = "examples";
|
||||||
|
private static final String HELPCMD_MOVE = "move";
|
||||||
|
private static final String HELPCMD_SYNTAX = "syntax";
|
||||||
|
private static final String HELPCMD_ALIAS = "alias";
|
||||||
|
private static final String HELPCMD_WIRE = "wire";
|
||||||
|
private static final String HELPCMD_ACCOUNTS = "accounts";
|
||||||
|
private static final String HELPCMD_ADMIN_BALANCE_CHANGE = "admin-set-balance";
|
||||||
|
private static final String HELPCMD_ADMIN_BALANCE_GET = "admin-get-balance";
|
||||||
|
private static final String HELPCMD_ADMIN_CREATE_BANK = "admin-create-bank";
|
||||||
|
private static final String HELPCMD_ADMIN_CLOSE_BANK = "admin-close-bank";
|
||||||
|
private static final String HELPCMD_ADMIN_FORCE_WIRE = "admin-force-wire";
|
||||||
|
private static final String HELPCMD_ADMIN_LOCK_BANK = "admin-lock-bank";
|
||||||
|
private static final String HELPCMD_SET_SERVER_ALLOWANCE = "admin-set-server-allowance";
|
||||||
|
private static final String HELPCMD_GET_SERVER_ALLOWANCE = "admin-get-server-allowance";
|
||||||
|
private static final String HELPCMD_ADMIN_COMMANDS_LIST = "admin-commands-list";
|
||||||
|
private static final String HELPCMD_ADMIN_ACCOUNTS = "admin-accounts";
|
||||||
|
private static final String HELPCMD_ADMIN_ACCOUNTS_LIST = "admin-accounts-list";
|
||||||
|
private static final String HELPCMD_ADMIN_ACCOUNTS_MOVE = "admin-accounts-move";
|
||||||
|
private static final String HELPCMD_ADMIN_ACCOUNTS_FORCE_CLOSE = "admin-accounts-force-close";
|
||||||
|
private static final String HELPCMD_ADMIN_ACCOUNTS_ADD = "admin-accounts-add";
|
||||||
|
private static final String HELPCMD_ADMIN_ACCOUNTS_TRANSACTIONS = "admin-accounts-transactions";
|
||||||
|
private static final String HELPCMD_ADMIN_ACCOUNTS_LOCK = "admin-accounts-lock";
|
||||||
|
|
||||||
|
ChatMsg msgFormatter = new ChatMsg();
|
||||||
|
|
||||||
|
private static final Map<String, String> HELP_COMMANDS = Map.ofEntries(
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_HELP, "Usage: /bank help. This is the general help message for the bank system. For detailed help messages, please run /bank help <command OR subcommand>. List of possible " +
|
||||||
|
"commands are: CREATE, SELECT, CLOSE, REPORT, BALANCE, EXAMPLES, WIRE, MOVE, SYNTAX, ALIAS"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_CREATE, "Usage: /bank create {checking|savings}. This will create a bank account with the default selected bank (/bank select {BANK_ID} to choose other)."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_SELECT, "Usage: /bank select {BANK_ID}. Do `/bank list` for a list of banks on the server."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_CLOSE, "Usage: /bank close {ACCOUNT_ID}. Do `/bank accounts list` to see all the accounts you have! Note: CANNOT close accounts that aren't 0 balance."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_REPORT, "Usage: /bank report [ACCOUNT_ID|none]. Optional args mean you can get a specific report list for one account; but if none specified we default to all accounts."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_BALANCE, "Usage: /bank balance [ACCOUNT_ID]. Optional args get balances for other accounts that aren't the default selected account. You may run `/bank accounts list` to " +
|
||||||
|
"see all possible options to get a balance for."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_EXAMPLES, "Usage: /bank examples. This will print a much larger command with more thorough examples (and even shortcuts!) of all the commands from the bank system."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_MOVE, "Usage: /bank move {ACCOUNT_ID} to {BANK_ID}. The intended use of this command is to move accounts across banks, but you could also plug in another ACCOUNT_ID in " +
|
||||||
|
" the `BANK_ID` part to perform an internal wire instead. NOTE: Moving might not succeed based on bank rules!"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_SYNTAX, "Usage: /bank syntax. This banking system was written to be human readable in command-form and often operates like a database. You can put certain filler-words inside your commands that are " +
|
||||||
|
"parsed out at runtime if it helps with reading. Example command: \"/bank select 942-3449-42\" will work just fine to select a bank account as a primary account. HOWEVER, you can also " +
|
||||||
|
"type \"/bank select for-bills as default\" so long as you aliased the account identifier as 'for-bills'. Much nicer to read and work with. [Related: /bank help aliases]"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ALIAS, "Usage: /bank alias {ACCOUNT_ID} {UNIQUE_NAME}. Alias provides a handy way to refer to bank accounts by their unique names instead of long-form account ids. NOTE: Aliases " +
|
||||||
|
"are ONLY unique within the context of an individual bank and not across all banks, but generally you can replace `ACCOUNT_ID` as seen in other commands with the alias if it exists."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_WIRE, "Usage: /bank wire {AMOUNT} to {ACCOUNT_ID|NAME}. It is recommended to wire a specific account ID over a name since it works if the other player is offline. If name is specified, " +
|
||||||
|
" the wire will go through to that players default account. Use with caution!"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ACCOUNTS, "Usage: /bank accounts {BANK_ID}. Prints out all of your banking information at a bank assuming you have any."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_BALANCE_CHANGE, "Usage: /bank admin {set-bal|add-money|subtract-money} {ACCOUNT_ID|BANK_ID} {AMOUNT}. This command covers set/add/subtract money. Usage varies on context, but general help command is going to be " +
|
||||||
|
"/bank admin {set-bal|add-money|sub-money} {USER_ACCOUNT_ID|BANK_ROUTING_NUM} {amount}. Please note that the \"|\" in this context means OR - you do not put both! " +
|
||||||
|
"So you can set a banks balance or accounts balance with this command."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_BALANCE_GET, "Usage: /bank admin get {USER_ACCOUNT_ID|BANK_ID}. Please note that the \"|\" in this means OR. Do NOT put both!"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_CREATE_BANK, "Usage: /bank admin create {new bank name}. Bank name must be longer than 4 letters!"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_CLOSE_BANK, "Usage: /bank admin close {BANK_ID}. Please be aware if the bank has an active balance or user accounts you will be asked to " +
|
||||||
|
"confirm if this is really what you want to do. Money is not magic, so if you specify to close the bank the bank balance is transferred back " +
|
||||||
|
"to the servers primary bank account & all user accounts money are transferred to the server bank. Accounts will automatically be opened to preserve " +
|
||||||
|
"the money for users to claim because banks are not ordinarily supposed to just close. Only run this command if you absolutely have to!"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_FORCE_WIRE, "Usage: /bank admin wire {AMOUNT} from {ACCOUNT_ID} to {ACCOUNT_ID}. Please be aware this is a heavy handed command and may " +
|
||||||
|
"unintentionally override a bank accounts default setting. A bank account with a rule that can't go negative WILL go negative if this command is " +
|
||||||
|
"run because it's an administrative command! Use with caution"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_LOCK_BANK, "Usage: /bank admin lock-bank {BANK_ID}. Completely freezes all activity in and out of a bank."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_SET_SERVER_ALLOWANCE, "Usage: /bank admin set-server-allowance {amount} {interval}. Example usage: /bank admin set-server-allowance 1,000,000 " +
|
||||||
|
"30d. Supported interval characters: d/m/y (day/month/year). These times are in MINECRAFT in-game time, not real life time! Months are assumed to be equally " +
|
||||||
|
"30 days and years are 365 days. If you need precision, just specify your amount in days!"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_GET_SERVER_ALLOWANCE, "Usage: /bank admin get-server-allowance. Returns the amount of money in the allowance for server and the interval it is in. "
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_COMMANDS_LIST, "Usage: /bank admin {sub-command} [optionals]. POSSIBLE ADMIN COMMANDS LIST: [set-bal, add-money, get-bal, sub-money, accounts, create-bank, close-bank, lock-bank, unlock, " +
|
||||||
|
"force-wire, get-server-allowance, set-server-allowance]. Commands FROM [accounts] cmd => [list, move, force-close, add, transactions, lock]"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_ACCOUNTS, "Usage: /bank admin accounts {sub-command} [optionals]. This command has sub-commands that are expected. Possible => [list, move, force-close, add, transactions, lock]. General syntax is " +
|
||||||
|
"/bank admin accounts [sub-command]"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_ACCOUNTS_ADD, "Usage: /bank admin accounts add {ONLINE_PLAYER} [BANK_ID]. Adds a regular checking account to a bank for a player who is online. " +
|
||||||
|
"If BANK_ID not specified; defaults to the servers default bank"
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_ACCOUNTS_FORCE_CLOSE, "Usage: /bank admin accounts force-close {ACCOUNT_ID}. Command not supported in this version."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_ACCOUNTS_LIST, "Usage: /bank admin accounts list {USERNAME}. Command not supported in this version."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_ACCOUNTS_LOCK, "Usage: /bank admin accounts lock {ACCOUNT_ID}. Command not supported in this version."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_ACCOUNTS_MOVE, "Usage: /bank admin accounts move {ACCOUNT_ID} to {BANK_ID}. Command not supported in this version."
|
||||||
|
),
|
||||||
|
entry
|
||||||
|
(
|
||||||
|
HELPCMD_ADMIN_ACCOUNTS_TRANSACTIONS, "Usage: /bank admin accounts transactions {ACCOUNT_ID}. Command not supported in this version."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
ConfigManager config = new ConfigManager();
|
ConfigManager config = new ConfigManager();
|
||||||
|
|
||||||
public void RegisterCommands(){
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Command: "/getbalance"
|
/// @fn RegisterCommands
|
||||||
|
///
|
||||||
|
/// @brief Registers all bank commands on the server
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void RegisterCommands() {
|
||||||
|
// Bank help
|
||||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
dispatcher.register(CommandManager.literal("getbalance")
|
var bankRoot = CommandManager.literal("bank").build();
|
||||||
.executes(context -> GetBalance(context)));
|
var help = CommandManager.literal("help")
|
||||||
|
.executes(context -> HelpCommand(context.getSource().getPlayer(), ""))
|
||||||
|
.build();
|
||||||
|
var helpTarget = CommandManager.argument("target", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> HelpCommand(context.getSource().getPlayer(), StringArgumentType.getString(context, "target")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var info = CommandManager.literal("info")
|
||||||
|
.executes(context -> ListBankInfo(context.getSource().getPlayer()))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bankRoot.addChild(info);
|
||||||
|
|
||||||
|
var balance = CommandManager.literal("balance")
|
||||||
|
.executes(context -> GetBalance(context.getSource().getPlayer()))
|
||||||
|
.build();
|
||||||
|
bankRoot.addChild(balance);
|
||||||
|
|
||||||
|
var create = CommandManager.literal("create").build();
|
||||||
|
var createAccount = CommandManager.literal("account").build();
|
||||||
|
|
||||||
|
var checking = CommandManager.literal("checking")
|
||||||
|
.executes(context -> CreateAccount(context.getSource().getPlayer(), ACCOUNT_TYPE.CHECKING))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var savings = CommandManager.literal("savings")
|
||||||
|
.executes(context -> CreateAccount(context.getSource().getPlayer(), ACCOUNT_TYPE.SAVINGS))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bankRoot.addChild(create);
|
||||||
|
create.addChild(createAccount);
|
||||||
|
createAccount.addChild(checking);
|
||||||
|
createAccount.addChild(savings);
|
||||||
|
|
||||||
|
var wireCmd = CommandManager.literal("wire").build();
|
||||||
|
var accountNum = CommandManager.argument("account", StringArgumentType.string()).build();
|
||||||
|
var wireAmount = CommandManager.argument("amount", IntegerArgumentType.integer()).build();
|
||||||
|
var wireReason = CommandManager.argument("reason", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> WireCommand(
|
||||||
|
context.getSource().getPlayer(),
|
||||||
|
IntegerArgumentType.getInteger(context, "amount"),
|
||||||
|
StringArgumentType.getString(context, "account"),
|
||||||
|
StringArgumentType.getString(context, "reason")
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bankRoot.addChild(wireCmd);
|
||||||
|
wireCmd.addChild(accountNum);
|
||||||
|
accountNum.addChild(wireAmount);
|
||||||
|
wireAmount.addChild(wireReason);
|
||||||
|
|
||||||
|
var list = CommandManager.literal("list")
|
||||||
|
.executes(context -> ListAllBanks(context.getSource().getPlayer()))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bankRoot.addChild(list);
|
||||||
|
|
||||||
|
var selectBankAccount = CommandManager.literal("select-default-account").build();
|
||||||
|
var selectBankAccountName = CommandManager.argument("global-account-id", StringArgumentType.string())
|
||||||
|
.executes(context -> SelectDefaultAccount(context.getSource().getPlayer(), StringArgumentType.getString(context, "global-account-id")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bankRoot.addChild(selectBankAccount);
|
||||||
|
selectBankAccount.addChild(selectBankAccountName);
|
||||||
|
|
||||||
|
var selectBank = CommandManager.literal("select-bank").build();
|
||||||
|
var selectBankName = CommandManager.argument("global_bank_name", StringArgumentType.string())
|
||||||
|
.executes(context -> SelectBank(context.getSource().getPlayer(), StringArgumentType.getString(context, "global_bank_name")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bankRoot.addChild(selectBank);
|
||||||
|
selectBank.addChild(selectBankName);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var close = CommandManager.literal("close").build();
|
||||||
|
var closeAccountId = CommandManager.argument("account", StringArgumentType.string())
|
||||||
|
.executes(context -> CloseCommand(context.getSource().getPlayer(), StringArgumentType.getString(context, "account")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bankRoot.addChild(close);
|
||||||
|
close.addChild(closeAccountId);
|
||||||
|
|
||||||
|
|
||||||
|
var moveCmd = CommandManager.literal("move").build();
|
||||||
|
var moveAmount = CommandManager.argument("move_amount", IntegerArgumentType.integer()).build();
|
||||||
|
var fromAccount = CommandManager.argument("from_account", StringArgumentType.string()).build();
|
||||||
|
var toAccount = CommandManager.argument("to_account", StringArgumentType.string())
|
||||||
|
.executes(context -> MoveCommand(
|
||||||
|
context.getSource().getPlayer(),
|
||||||
|
IntegerArgumentType.getInteger(context, "move_amount"),
|
||||||
|
StringArgumentType.getString(context, "from_account"),
|
||||||
|
StringArgumentType.getString(context, "to_account")
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
bankRoot.addChild(moveCmd);
|
||||||
|
moveCmd.addChild(moveAmount);
|
||||||
|
moveAmount.addChild(fromAccount);
|
||||||
|
fromAccount.addChild(toAccount);
|
||||||
|
|
||||||
|
|
||||||
|
var admin = CommandManager.literal("admin").build();
|
||||||
|
// var accounts = CommandManager.literal("accounts").build();
|
||||||
|
var subtractMoney = CommandManager.literal("sub-money").build();
|
||||||
|
var subtractAmount = CommandManager.argument("sub_amount", IntegerArgumentType.integer()).build();
|
||||||
|
var subtractAccount = CommandManager.argument("sub_account", StringArgumentType.string()).build();
|
||||||
|
var subtractReason = CommandManager.argument("sub_reason", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> AdminSubtractMoney(
|
||||||
|
context.getSource().getPlayer(),
|
||||||
|
IntegerArgumentType.getInteger(context, "sub_amount"),
|
||||||
|
StringArgumentType.getString(context, "sub_account"),
|
||||||
|
StringArgumentType.getString(context, "sub_reason")
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var addMoney = CommandManager.literal("add-money").build();
|
||||||
|
var addAmount = CommandManager.argument("add_amount", IntegerArgumentType.integer()).build();
|
||||||
|
var addAccount = CommandManager.argument("add_account", StringArgumentType.string()).build();
|
||||||
|
var addReason = CommandManager.argument("add_reason", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> AdminAddMoney(
|
||||||
|
context.getSource().getPlayer(),
|
||||||
|
IntegerArgumentType.getInteger(context, "add_amount"),
|
||||||
|
StringArgumentType.getString(context, "add_account"),
|
||||||
|
StringArgumentType.getString(context, "add_reason")
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var setMoney = CommandManager.literal("set-bal").build();
|
||||||
|
var setAmnt = CommandManager.argument("set_amount", IntegerArgumentType.integer()).build();
|
||||||
|
var setAccount = CommandManager.argument("set_account", StringArgumentType.string()).build();
|
||||||
|
var setReason = CommandManager.argument("set_reason", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> AdminSetMoney(
|
||||||
|
context.getSource().getPlayer(),
|
||||||
|
IntegerArgumentType.getInteger(context, "set_amount"),
|
||||||
|
StringArgumentType.getString(context, "set_account"),
|
||||||
|
StringArgumentType.getString(context, "set_reason")
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var getBal = CommandManager.literal("get-bal").build();
|
||||||
|
var getBalTgt = CommandManager.argument("get_bal_target", StringArgumentType.string()).build();
|
||||||
|
|
||||||
|
var createBank = CommandManager.literal("create-bank").build();
|
||||||
|
var createBankName = CommandManager.argument("create_bank_name", StringArgumentType.string()).build();
|
||||||
|
|
||||||
|
var closeBank = CommandManager.literal("close-bank").build();
|
||||||
|
var closeBankName = CommandManager.argument("close_bank_name", StringArgumentType.string()).build();
|
||||||
|
|
||||||
|
var setServerBal = CommandManager.literal("set-server-bal").build();
|
||||||
|
var setServerBalAmnt = CommandManager.argument("set_server_bal_amount", StringArgumentType.string()).build();
|
||||||
|
|
||||||
|
var setServerAllowance = CommandManager.literal("set-server-allowance").build();
|
||||||
|
var setServerAllowanceAmount = CommandManager.argument("set_server_allowance", IntegerArgumentType.integer()).build();
|
||||||
|
|
||||||
|
|
||||||
|
bankRoot.addChild(admin);
|
||||||
|
|
||||||
|
admin.addChild(subtractMoney);
|
||||||
|
subtractMoney.addChild(subtractAmount);
|
||||||
|
subtractAmount.addChild(subtractAccount);
|
||||||
|
subtractAccount.addChild(subtractReason);
|
||||||
|
|
||||||
|
admin.addChild(addMoney);
|
||||||
|
addMoney.addChild(addAmount);
|
||||||
|
addAmount.addChild(addAccount);
|
||||||
|
addAccount.addChild(addReason);
|
||||||
|
|
||||||
|
admin.addChild(setMoney);
|
||||||
|
setMoney.addChild(setAmnt);
|
||||||
|
setAmnt.addChild(setAccount);
|
||||||
|
setAccount.addChild(setReason);
|
||||||
|
|
||||||
|
admin.addChild(getBal);
|
||||||
|
getBal.addChild(getBalTgt);
|
||||||
|
|
||||||
|
admin.addChild(createBank);
|
||||||
|
createBank.addChild(createBankName);
|
||||||
|
|
||||||
|
admin.addChild(closeBank);
|
||||||
|
admin.addChild(closeBankName);
|
||||||
|
|
||||||
|
admin.addChild(setServerBal);
|
||||||
|
setServerBal.addChild(setServerBalAmnt);
|
||||||
|
|
||||||
|
admin.addChild(setServerAllowance);
|
||||||
|
setServerAllowance.addChild(setServerAllowanceAmount);
|
||||||
|
|
||||||
|
|
||||||
|
// Building the argument tree here
|
||||||
|
dispatcher.getRoot().addChild(bankRoot);
|
||||||
|
bankRoot.addChild(help);
|
||||||
|
help.addChild(helpTarget);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Command: "/setbalance || rootSetBalance"
|
|
||||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
final var rootSetBalance = dispatcher.register(CommandManager.literal("setbalance")
|
var wire = CommandManager.literal("wire").build();
|
||||||
.then(CommandManager.argument("newBalance", IntegerArgumentType.integer())
|
var account = CommandManager.argument("global_account_id", StringArgumentType.string()).build();
|
||||||
.then(CommandManager.argument("reason", StringArgumentType.string())
|
var amount = CommandManager.argument("amount", IntegerArgumentType.integer()).build();
|
||||||
.then(CommandManager.argument("otherParty", StringArgumentType.string())
|
var reason = CommandManager.argument("reason", StringArgumentType.greedyString())
|
||||||
.executes(context -> SetBalance(
|
.executes(context -> WireCommand(
|
||||||
IntegerArgumentType.getInteger(context, "newBalance"),
|
context.getSource().getPlayer(),
|
||||||
StringArgumentType.getString(context, "reason"),
|
IntegerArgumentType.getInteger(context, "amount"),
|
||||||
StringArgumentType.getString(context, "otherParty"),
|
StringArgumentType.getString(context, "global_account_id"),
|
||||||
context))))));
|
StringArgumentType.getString(context, "reason")
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
dispatcher.register(CommandManager.literal("setbalance").redirect(rootSetBalance));
|
dispatcher.getRoot().addChild(wire);
|
||||||
});
|
wire.addChild(account);
|
||||||
|
|
||||||
// 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) {
|
public int SelectBank(ServerPlayerEntity player, String bank) {
|
||||||
Integer ret = -1;
|
System.out.println("Select bank called");
|
||||||
|
BankManager.GetInstance().ChangeDefaultSelectedBank(player, bank.toUpperCase());
|
||||||
if (context.getSource().isExecutedByPlayer()) {
|
return 0;
|
||||||
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 int AdminSubtractMoney(ServerPlayerEntity player, Integer amount, String account, String reason) {
|
||||||
public Integer SetBalance(Integer newBalance, String reason, String otherParty, CommandContext<ServerCommandSource> context) {
|
AdminBalanceChange(player, account, amount, "subtract", reason);
|
||||||
Integer ret = -1;
|
return 0;
|
||||||
|
|
||||||
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 int AdminAddMoney(ServerPlayerEntity player, Integer amount, String account, String reason) {
|
||||||
public Integer AddMoney(String reason, long payment, String otherParty, CommandContext<ServerCommandSource> context) {
|
AdminBalanceChange(player, account, amount, "add", reason);
|
||||||
Integer ret = -1;
|
return 0;
|
||||||
|
|
||||||
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 int AdminSetMoney(ServerPlayerEntity player, Integer amount, String account, String reason) {
|
||||||
public Integer SubtractBalance(String reason, long payment, String otherParty, CommandContext<ServerCommandSource> context) {
|
AdminBalanceChange(player, account, amount, "set", reason);
|
||||||
Integer ret = -1;
|
return 0;
|
||||||
|
|
||||||
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;
|
/// @fn AdminBalanceChange
|
||||||
|
///
|
||||||
|
/// @param[in] player is player who ran command
|
||||||
|
///
|
||||||
|
/// @param[in] accountId is account id to change balance of
|
||||||
|
///
|
||||||
|
/// @param[in] amount is amount to change account balance
|
||||||
|
///
|
||||||
|
/// @param[in] type is type of fund change (parsed on @ref BankManager.java)
|
||||||
|
///
|
||||||
|
/// @param[in] optionalReason is the optional reason of balance change
|
||||||
|
///
|
||||||
|
/// @brief Admin command to change the balance of an account by some
|
||||||
|
/// amount
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void AdminBalanceChange(ServerPlayerEntity player, String accountId, Integer amount, String type, String optionalReason) {
|
||||||
|
BankManager.GetInstance().AdminChangeFunds(player, accountId, amount, type, optionalReason);
|
||||||
|
}
|
||||||
|
|
||||||
if (context.getSource().isExecutedByPlayer()) {
|
public int GetBalance(ServerPlayerEntity player) {
|
||||||
ret = 0;
|
BankManager.GetInstance().GetBalance(player);
|
||||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
return 0;
|
||||||
BankManager playerBank = new BankManager(player.getUuidAsString());
|
}
|
||||||
playerBank.Wire(reason, payment, otherParty);
|
|
||||||
player.sendMessage(Text.literal(String.valueOf(playerBank.GetBalance())));
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ManageAccounts
|
||||||
|
///
|
||||||
|
/// @brief Change the balance of a designated account
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public int ListBankInfo(ServerPlayerEntity sourcePlayer) {
|
||||||
|
String bankName = BankManager.GetInstance().GetPlayerSelectedBank(sourcePlayer.getUuidAsString());
|
||||||
|
IndividualBank bank = BankManager.GetInstance().GetBankByName(bankName);
|
||||||
|
|
||||||
|
if (bank != null) {
|
||||||
|
List<IndividualAccount> userAccounts = bank.GetAccountsOfUser(sourcePlayer.getUuidAsString());
|
||||||
|
sourcePlayer.sendMessage(Text.of("[BANK INFO FOR " + bankName.toUpperCase() + "]"));
|
||||||
|
|
||||||
|
for (IndividualAccount userAccount : userAccounts) {
|
||||||
|
String accountNumber = userAccount.GetAccountNumber();
|
||||||
|
String globalAccountNumber = userAccount.GetGlobalAccountNumber();
|
||||||
|
|
||||||
|
List<String> accountHolders = userAccount.GetAccountHolders();
|
||||||
|
Integer accountBalance = userAccount.GetAccountBalance();
|
||||||
|
ACCOUNT_TYPE accountType = userAccount.GetAccountType();
|
||||||
|
|
||||||
|
String l1 = "ACCOUNT NUMBER: " + ChatMsg.ColorMsg(accountNumber, COLOR_CODE.BLUE);
|
||||||
|
String l2 = "GLOBAL ACCOUNT NUMBER: " + ChatMsg.ColorMsg(globalAccountNumber, COLOR_CODE.BLUE);
|
||||||
|
String l3 = "HOLDERS: " + ChatMsg.ColorMsg(accountHolders, COLOR_CODE.GRAY);
|
||||||
|
String l4 = "ACCOUNT TYPE: " + ChatMsg.ColorMsg(accountType.name(), COLOR_CODE.GRAY);
|
||||||
|
String l5 = "BALANCE: " + ChatMsg.ColorMsg(accountBalance, COLOR_CODE.GREEN);
|
||||||
|
|
||||||
|
// If this is the default account of the player; we will append a "[SELECTED]" tag on it
|
||||||
|
boolean isDefaultAccount = BankManager.GetInstance().IsDefaultAccount(sourcePlayer.getUuidAsString(), globalAccountNumber);
|
||||||
|
if (isDefaultAccount) {
|
||||||
|
l2 = l2 + ChatMsg.ColorMsg(" [SELECTED]", COLOR_CODE.GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l1, "Click to copy", accountNumber));
|
||||||
|
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l2, "Click to copy", globalAccountNumber));
|
||||||
|
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l3, "Click to copy", accountHolders));
|
||||||
|
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l4, "Click to copy", accountType.name()));
|
||||||
|
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l5, "Click to copy", accountBalance));
|
||||||
|
sourcePlayer.sendMessage(Text.of("\n"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sourcePlayer.sendMessage(Text.of(ChatMsg.ColorMsg("That bank does not exist", COLOR_CODE.RED)));
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
// Lists out all the banks on the server in a format that the player can read and click to copy
|
||||||
|
public int ListAllBanks(ServerPlayerEntity player) {
|
||||||
|
for (String bank : BankManager.GetInstance().GetAllBankNames()) {
|
||||||
|
String formattedBankName = ChatMsg.ColorMsg(bank, ChatFormatting.COLOR_CODE.BLUE);
|
||||||
|
player.sendMessage((Text) ChatMsg.MakeCopyableTxt("BANK: " + formattedBankName, "Click to copy bank name", bank));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn MoveCommand
|
||||||
|
///
|
||||||
|
/// @param[in] player is player who ran command
|
||||||
|
///
|
||||||
|
/// @param[in] argList is the argument list to be parsed
|
||||||
|
///
|
||||||
|
/// @brief Not finished in this version of the mod
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public int MoveCommand(ServerPlayerEntity player, Integer amount, String fromAccount, String toAccount) {
|
||||||
|
player.sendMessage(Text.of("This command is not supported in this version. You can accomplish the same thing with /wire though, just make sure you have a default account selected first!"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CloseCommand(ServerPlayerEntity player, String account) {
|
||||||
|
BankManager.GetInstance().InitiateBankAccountClosure(player, account);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Possible code paths:
|
||||||
|
// required = {account id | alias}
|
||||||
|
// optional = [default|secondary|backup]
|
||||||
|
public int SelectDefaultAccount(ServerPlayerEntity sourcePlayer, String account) {
|
||||||
|
BankManager.GetInstance().ChangeDefaultPlayerAccount(sourcePlayer, account);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn WireCommand
|
||||||
|
///
|
||||||
|
/// @param[in] player is player who ran command
|
||||||
|
///
|
||||||
|
/// @param[in] argList is the argument list to be parsed
|
||||||
|
///
|
||||||
|
/// @brief Create wire on bank account
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public int WireCommand(ServerPlayerEntity sourcePlayer, Integer amount, String destAccount, String reason) {
|
||||||
|
BankManager.GetInstance().InitiateBankFundsTransfer(sourcePlayer, destAccount, amount, reason);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn HelpCommand
|
||||||
|
///
|
||||||
|
/// @param[in] player is player who ran command
|
||||||
|
///
|
||||||
|
/// @param[in] helpCommand is the argument list to be parsed
|
||||||
|
///
|
||||||
|
/// @brief Builds a dynamic help list to the player to see all command
|
||||||
|
/// options on the server
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public int HelpCommand(ServerPlayerEntity sourcePlayer, String helpCommandList) {
|
||||||
|
System.out.println("Running help command");
|
||||||
|
List<String> helpCommand = new ArrayList<String>(Arrays.asList(helpCommandList.split(" ")));
|
||||||
|
|
||||||
|
if (helpCommand.isEmpty()) {
|
||||||
|
// General help command
|
||||||
|
for (Entry<String, String> helpCmd : HELP_COMMANDS.entrySet()) {
|
||||||
|
String cmd = ChatMsg.ColorMsg(helpCmd.getKey(), COLOR_CODE.GOLD);
|
||||||
|
String details = ChatMsg.FormatMsg(helpCmd.getValue(), COLOR_CODE.BLUE, COLOR_CODE.GRAY);
|
||||||
|
|
||||||
|
sourcePlayer.sendMessage(Text.of(cmd + " --> " + details));
|
||||||
|
sourcePlayer.sendMessage(Text.of("\n"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Iterate over list; verifying what commands are found
|
||||||
|
List<String> unknownCmds = new ArrayList<String>();
|
||||||
|
for (String newHelpCmd : helpCommand) {
|
||||||
|
if (HELP_COMMANDS.containsKey(newHelpCmd)) {
|
||||||
|
// Print help for this specific command
|
||||||
|
String cmd = ChatMsg.ColorMsg(newHelpCmd, COLOR_CODE.GOLD);
|
||||||
|
String details = ChatMsg.FormatMsg(HELP_COMMANDS.get(newHelpCmd), COLOR_CODE.BLUE, COLOR_CODE.GRAY);
|
||||||
|
|
||||||
|
sourcePlayer.sendMessage(Text.of(cmd + " -> " + details));
|
||||||
|
} else if (!newHelpCmd.isEmpty()){
|
||||||
|
// Add to unknown list at end
|
||||||
|
unknownCmds.add(newHelpCmd);
|
||||||
|
} else {
|
||||||
|
sourcePlayer.sendMessage(Text.of(ChatMsg.ColorMsg("This is the generic help command for the banking system! You should read the dedicated discord channel to figure out how to setup an account. If you want more, you can do '/help {bank command 1} {bank command 2}' if you want a specific help message on that command. Happy taxing!", COLOR_CODE.BLUE)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// After all prints have finished tell the player the commands they plugged in that we did not recognize
|
||||||
|
if (!unknownCmds.isEmpty()) {
|
||||||
|
String msg = ChatMsg.ColorMsg("The following commands do not exist or were mis-pelt: ", COLOR_CODE.RED);
|
||||||
|
sourcePlayer.sendMessage(Text.of(msg + unknownCmds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn CreateAccount
|
||||||
|
///
|
||||||
|
/// @param[in] player is player who ran command
|
||||||
|
///
|
||||||
|
/// @param[in] accountArgs is the argument list to be parsed
|
||||||
|
///
|
||||||
|
/// @brief Creates a bank account
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public int CreateAccount(ServerPlayerEntity player, ACCOUNT_TYPE accountType) {
|
||||||
|
String bank = BankManager.GetInstance().GetPlayerSelectedBank(player.getUuidAsString());
|
||||||
|
System.out.println("Received bank: " + bank);
|
||||||
|
|
||||||
|
if (!bank.isEmpty()) {
|
||||||
|
BankManager.GetInstance().InitiateBankAccountCreation(bank, player, accountType);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
package jesse.keeblarcraft.Commands;
|
package jesse.keeblarcraft.Commands;
|
||||||
|
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
import jesse.keeblarcraft.ChatStuff.ChatMsg;
|
||||||
|
|
||||||
public class CustomCommandManager {
|
public class CustomCommandManager {
|
||||||
// Intentionally empty constructor since at object definition time it may not be possible to register commands
|
// Intentionally empty constructor since at object definition time it may not be possible to register commands
|
||||||
@ -22,13 +22,18 @@ public class CustomCommandManager {
|
|||||||
NoteCommands noteCommands = new NoteCommands();
|
NoteCommands noteCommands = new NoteCommands();
|
||||||
BankCommands bankCommands = new BankCommands();
|
BankCommands bankCommands = new BankCommands();
|
||||||
AttributeCommands attributeCommands = new AttributeCommands();
|
AttributeCommands attributeCommands = new AttributeCommands();
|
||||||
|
FactionCommands factionCommands = new FactionCommands();
|
||||||
|
MiscCommands miscCommands = new MiscCommands();
|
||||||
|
MailCommands mailCommands = new MailCommands();
|
||||||
|
|
||||||
// REGISTER COMMANDS BELOW
|
// REGISTER COMMANDS BELOW
|
||||||
System.out.println(ChatUtil.ColoredString("REGISTERING CUSTOM COMMAND EXTENSIONS BELOW", CONSOLE_COLOR.BLUE));
|
Keeblarcraft.LOGGER.info("Registering mod commands");
|
||||||
shortcuts.RegisterShortcutCommands();
|
shortcuts.RegisterShortcutCommands();
|
||||||
noteCommands.RegisterNoteCommands();
|
noteCommands.RegisterNoteCommands();
|
||||||
bankCommands.RegisterCommands();
|
bankCommands.RegisterCommands();
|
||||||
attributeCommands.RegisterCommands();
|
attributeCommands.RegisterCommands();
|
||||||
|
factionCommands.RegisterFactionCommands();
|
||||||
|
miscCommands.RegisterCommands();
|
||||||
|
mailCommands.RegisterMailCommands();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,47 +1,286 @@
|
|||||||
package jesse.keeblarcraft.Commands;
|
package jesse.keeblarcraft.Commands;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionManager;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerCommandFlightCallback;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
|
||||||
|
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.server.world.ServerWorld;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
|
||||||
public class FactionCommands {
|
public class FactionCommands {
|
||||||
|
|
||||||
// Register function for commands
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterFactionCommands
|
||||||
|
///
|
||||||
|
/// @brief Registers all commands for factions
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
public void RegisterFactionCommands() {
|
public void RegisterFactionCommands() {
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
var factionNode = CommandManager.literal("faction").build();
|
||||||
|
|
||||||
|
var createFaction = CommandManager.literal("create").build();
|
||||||
|
var disbandFaction = CommandManager.literal("disband").build();
|
||||||
|
var promote = CommandManager.literal("promote").build();
|
||||||
|
var demote = CommandManager.literal("demote").build();
|
||||||
|
var kick = CommandManager.literal("kick").build();
|
||||||
|
var set = CommandManager.literal("set").build();
|
||||||
|
var get = CommandManager.literal("get").build();
|
||||||
|
var power = CommandManager.literal("power").build();
|
||||||
|
var join = CommandManager.literal("join").build();
|
||||||
|
var info = CommandManager.literal("info")
|
||||||
|
.executes(context -> GetFactionInformation(context.getSource().getPlayer()))
|
||||||
|
.build();
|
||||||
|
var invite = CommandManager.literal("invite").build();
|
||||||
|
var fly = CommandManager.literal("fly")
|
||||||
|
.executes(context -> ForwardFlightCallback(context)).build();
|
||||||
|
|
||||||
|
// The below nodes are duplicates but are necessary to make the execute path jump correctly
|
||||||
|
var createFactionName = CommandManager.argument("faction_name", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> CreateFaction
|
||||||
|
(
|
||||||
|
context,
|
||||||
|
StringArgumentType.getString(context, "faction_name")
|
||||||
|
)
|
||||||
|
).build();
|
||||||
|
|
||||||
|
var disbandFactionName = CommandManager.argument("faction_name", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> DeleteFaction
|
||||||
|
(
|
||||||
|
context,
|
||||||
|
StringArgumentType.getString(context, "faction_name")
|
||||||
|
)
|
||||||
|
).build();
|
||||||
|
|
||||||
|
var joinName = CommandManager.argument("faction_name", StringArgumentType.string())
|
||||||
|
.executes(context -> JoinFaction(context.getSource().getPlayer(), StringArgumentType.getString(context, "faction_name")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var promoteName = CommandManager.argument("target_name", EntityArgumentType.player())
|
||||||
|
.executes(context -> PromotePlayerInFaction(context, EntityArgumentType.getPlayer(context, "target_name")))
|
||||||
|
.build();
|
||||||
|
var demoteName = CommandManager.argument("target_name", EntityArgumentType.player())
|
||||||
|
.executes(context -> DemotePlayerInFaction(context, EntityArgumentType.getPlayer(context, "target_name")))
|
||||||
|
.build();
|
||||||
|
var kickName = CommandManager.argument("target_name", EntityArgumentType.player())
|
||||||
|
.executes(context -> KickPlayerFromFaction(context, EntityArgumentType.getPlayer(context, "target_name")))
|
||||||
|
.build();
|
||||||
|
var inviteName = CommandManager.argument("target_name", EntityArgumentType.player())
|
||||||
|
.executes(context -> InvitePlayerToFaction(context, EntityArgumentType.getPlayer(context, "target_name")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var setPower = CommandManager.literal("power").build();
|
||||||
|
var setPowerAmnt = CommandManager.argument("power_amount", IntegerArgumentType.integer()).build();
|
||||||
|
var setPowerName = CommandManager.argument("set_power_name", StringArgumentType.string())
|
||||||
|
.executes(context -> SetFactionPower(context.getSource().getPlayer(), StringArgumentType.getString(context, "set_power_name"), IntegerArgumentType.getInteger(context, "power_amount")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var getPowerName = CommandManager.argument("get_power_name", StringArgumentType.string())
|
||||||
|
.executes(context -> GetFactionPower(context.getSource().getPlayer(), StringArgumentType.getString(context, "get_power_name"))).build();
|
||||||
|
|
||||||
|
var leaveFaction = CommandManager.literal("leave").executes(context -> LeaveFaction(context)
|
||||||
|
).build();
|
||||||
|
|
||||||
|
var listAll = CommandManager.literal("list")
|
||||||
|
.executes(context -> ListAllFactions(context.getSource().getPlayer())).build();
|
||||||
|
|
||||||
|
|
||||||
|
// Root node
|
||||||
|
dispatcher.getRoot().addChild(factionNode);
|
||||||
|
|
||||||
|
// List command
|
||||||
|
factionNode.addChild(listAll);
|
||||||
|
factionNode.addChild(createFaction);
|
||||||
|
factionNode.addChild(disbandFaction);
|
||||||
|
factionNode.addChild(leaveFaction);
|
||||||
|
factionNode.addChild(promote);
|
||||||
|
factionNode.addChild(demote);
|
||||||
|
factionNode.addChild(kick);
|
||||||
|
factionNode.addChild(info);
|
||||||
|
factionNode.addChild(invite);
|
||||||
|
factionNode.addChild(fly);
|
||||||
|
factionNode.addChild(set);
|
||||||
|
factionNode.addChild(get);
|
||||||
|
factionNode.addChild(join);
|
||||||
|
|
||||||
|
join.addChild(joinName);
|
||||||
|
|
||||||
|
get.addChild(power);
|
||||||
|
power.addChild(getPowerName);
|
||||||
|
|
||||||
|
set.addChild(setPower);
|
||||||
|
setPower.addChild(setPowerAmnt);
|
||||||
|
setPowerAmnt.addChild(setPowerName);
|
||||||
|
|
||||||
|
promote.addChild(promoteName);
|
||||||
|
demote.addChild(demoteName);
|
||||||
|
kick.addChild(kickName);
|
||||||
|
invite.addChild(inviteName);
|
||||||
|
|
||||||
|
createFaction.addChild(createFactionName);
|
||||||
|
disbandFaction.addChild(disbandFactionName);
|
||||||
|
});
|
||||||
|
|
||||||
|
// I'll refactor the above one later! LOL
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
var factionNode = CommandManager.literal("faction").build();
|
||||||
|
var powerNode = CommandManager.literal("power")
|
||||||
|
.executes(context -> GetFactionPower(context.getSource().getPlayer()))
|
||||||
|
.build();
|
||||||
|
var setNode = CommandManager.literal("set").build();
|
||||||
|
var factionNameNode = CommandManager.argument("faction_name", StringArgumentType.string()).build();
|
||||||
|
|
||||||
|
var powerAmountNode = CommandManager.argument("power_amount", IntegerArgumentType.integer())
|
||||||
|
.executes(context -> SetFactionPower(context.getSource().getPlayer(), StringArgumentType.getString(context, "faction_name"), IntegerArgumentType.getInteger(context, "power_amount")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(factionNode);
|
||||||
|
factionNode.addChild(powerNode);
|
||||||
|
|
||||||
|
powerNode.addChild(setNode);
|
||||||
|
setNode.addChild(factionNameNode);
|
||||||
|
setNode.addChild(powerAmountNode);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PRIVATE HANDLERS BELOW
|
private int ForwardFlightCallback(CommandContext<ServerCommandSource> context) {
|
||||||
private int CreateFaction() {
|
if (context.getSource().isExecutedByPlayer()) {
|
||||||
|
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||||
|
ServerWorld world = context.getSource().getWorld();
|
||||||
|
Integer fPower = FactionManager.GetInstance().GetFactionPower(player);
|
||||||
|
FactionTierEnum fTier = FactionManager.GetInstance().GetFactionTier(FactionManager.GetInstance().GetFactionOfPlayer(player.getUuidAsString()));
|
||||||
|
|
||||||
|
|
||||||
|
ActionResult result = PlayerCommandFlightCallback.EVENT.invoker().interact(player, world, fPower, fTier);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SetFactionPower(ServerPlayerEntity caller, String faction, Integer amount) {
|
||||||
|
Boolean success = FactionManager.GetInstance().SetFactionPower(caller, faction, amount);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
caller.sendMessage(Text.of("Successfully set the faction " + faction + " power to " + amount));
|
||||||
|
} else {
|
||||||
|
caller.sendMessage(Text.of("This is an operator only command!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int JoinFaction(ServerPlayerEntity player, String factionName) {
|
||||||
|
FactionManager.GetInstance().JoinFaction(player, factionName);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetFactionPower(ServerPlayerEntity player) {
|
||||||
|
FactionManager.GetInstance().GetFactionPower(player);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetFactionPower(ServerPlayerEntity player, String factionName) {
|
||||||
|
Integer amnt = FactionManager.GetInstance().GetFactionPower(factionName);
|
||||||
|
player.sendMessage(Text.of("[" + factionName + " - POWER]:" + amnt));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn CreateFaction
|
||||||
|
///
|
||||||
|
/// @param[in] context is the context of where this command runs from
|
||||||
|
///
|
||||||
|
/// @param[in] newFactionName is the faction name to be created
|
||||||
|
///
|
||||||
|
/// @brief Command to create a faction
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private int CreateFaction(CommandContext<ServerCommandSource> context, String newFactionName) {
|
||||||
|
int retValue = 0;
|
||||||
|
|
||||||
|
System.out.println("CreateFaction getting player obj");
|
||||||
|
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||||
|
System.out.println("CreateFaction called");
|
||||||
|
if (newFactionName.length() >= 4) {
|
||||||
|
FactionManager.GetInstance().CreateFaction(newFactionName, player);
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("Your faction must be at least 4 letters long!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return retValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn DeleteFaction
|
||||||
|
///
|
||||||
|
/// @param[in] context is the context of where this command runs from
|
||||||
|
///
|
||||||
|
/// @param[in] newFactionName is the faction name to be deleted
|
||||||
|
///
|
||||||
|
/// @brief Command to create a faction
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private int DeleteFaction(CommandContext<ServerCommandSource> context, String factionName) {
|
||||||
|
int retValue = 0;
|
||||||
|
|
||||||
|
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||||
|
FactionManager.GetInstance().DeleteFaction(factionName, player);
|
||||||
|
|
||||||
|
return retValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int InvitePlayerToFaction(CommandContext<ServerCommandSource> context, ServerPlayerEntity player) {
|
||||||
|
FactionManager.GetInstance().InvitePlayerToFaction(context.getSource().getPlayer(), player.getUuidAsString(), player.getEntityName());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn LeaveFaction
|
||||||
|
///
|
||||||
|
/// @param[in] context is the context of where this command runs from
|
||||||
|
///
|
||||||
|
/// @brief Command to leave a faction
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private int LeaveFaction(CommandContext<ServerCommandSource> context) {
|
||||||
|
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||||
|
|
||||||
|
FactionManager.GetInstance().LeaveFaction(player);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns information on the players current faction
|
||||||
|
private int GetFactionInformation(ServerPlayerEntity player) {
|
||||||
|
System.out.println("GETTING FACTION INFO");
|
||||||
|
FactionManager.GetInstance().GetFactionInformation(player);
|
||||||
|
System.out.println("ENDING FACTION INFO");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int KickPlayerFromFaction(CommandContext<ServerCommandSource> context, ServerPlayerEntity player) {
|
||||||
int retValue = -1;
|
int retValue = -1;
|
||||||
|
|
||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int DeleteFaction() {
|
private int PromotePlayerInFaction(CommandContext<ServerCommandSource> context, ServerPlayerEntity player) {
|
||||||
int retValue = -1;
|
ServerPlayerEntity caller = context.getSource().getPlayer();
|
||||||
|
FactionManager.GetInstance().PromotePlayer(caller, player.getUuidAsString(), player.getEntityName());
|
||||||
return retValue;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int AddPlayerToFaction() {
|
private int DemotePlayerInFaction(CommandContext<ServerCommandSource> context, ServerPlayerEntity player) {
|
||||||
int retValue = -1;
|
ServerPlayerEntity caller = context.getSource().getPlayer();
|
||||||
|
FactionManager.GetInstance().DemotePlayer(caller, player.getUuidAsString(), player.getEntityName());
|
||||||
return retValue;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
private int SetPlayerRoleInFaction() {
|
||||||
@ -56,13 +295,6 @@ public class FactionCommands {
|
|||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// admin only
|
|
||||||
private int SetFactionPower() {
|
|
||||||
int retValue = -1;
|
|
||||||
|
|
||||||
return retValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int DeclareFactionEvent() {
|
private int DeclareFactionEvent() {
|
||||||
int retValue = -1;
|
int retValue = -1;
|
||||||
|
|
||||||
@ -87,9 +319,25 @@ public class FactionCommands {
|
|||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ListAllFactions() {
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ListAllFactions
|
||||||
|
///
|
||||||
|
/// @param[in] player is the command runner
|
||||||
|
///
|
||||||
|
/// @brief Command to see all factions on the server
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private int ListAllFactions(ServerPlayerEntity player) {
|
||||||
int retValue = -1;
|
int retValue = -1;
|
||||||
|
|
||||||
|
System.out.println("Listing factions");
|
||||||
|
List<String> facs = FactionManager.GetInstance().ListOfFactions();
|
||||||
|
|
||||||
|
if (facs != null) {
|
||||||
|
player.sendMessage(Text.of("All factions on server: " + facs));
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("There are no factions on this server yet!"));
|
||||||
|
}
|
||||||
|
|
||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
src/main/java/jesse/keeblarcraft/Commands/MailCommands.java
Normal file
61
src/main/java/jesse/keeblarcraft/Commands/MailCommands.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package jesse.keeblarcraft.Commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
|
import net.minecraft.server.command.CommandManager;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
|
||||||
|
public class MailCommands {
|
||||||
|
public void RegisterMailCommands() {
|
||||||
|
// Mail send <player> msg...
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
var mailRoot = CommandManager.literal("mail").build();
|
||||||
|
var sendNode = CommandManager.literal("send").build();
|
||||||
|
var playerName = CommandManager.argument("target_name", StringArgumentType.string()).build();
|
||||||
|
var message = CommandManager.argument("mail_msg", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> SendMail(context.getSource().getPlayer(), StringArgumentType.getString(context, "target_name"), StringArgumentType.getString(context, "mail_msg")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(mailRoot);
|
||||||
|
|
||||||
|
mailRoot.addChild(sendNode);
|
||||||
|
sendNode.addChild(playerName);
|
||||||
|
playerName.addChild(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mail read
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
var mailRoot = CommandManager.literal("mail").build();
|
||||||
|
var readNode = CommandManager.literal("read")
|
||||||
|
.executes(context -> ReadMail(context.getSource().getPlayer()))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(mailRoot);
|
||||||
|
mailRoot.addChild(readNode);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mail clear
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
var mailRoot = CommandManager.literal("mail").build();
|
||||||
|
var clearNode = CommandManager.literal("clear")
|
||||||
|
.executes(context -> ClearMail(context.getSource().getPlayer()))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(mailRoot);
|
||||||
|
mailRoot.addChild(clearNode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private int SendMail(ServerPlayerEntity source, String targetName, String mail) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ReadMail(ServerPlayerEntity player) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ClearMail(ServerPlayerEntity player) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
176
src/main/java/jesse/keeblarcraft/Commands/MiscCommands.java
Normal file
176
src/main/java/jesse/keeblarcraft/Commands/MiscCommands.java
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
package jesse.keeblarcraft.Commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.GeneralConfig;
|
||||||
|
import jesse.keeblarcraft.Utils.DirectionalVec;
|
||||||
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
|
import net.minecraft.server.command.CommandManager;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
public class MiscCommands {
|
||||||
|
ConfigManager config = new ConfigManager();
|
||||||
|
|
||||||
|
public void RegisterCommands() {
|
||||||
|
// CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
|
||||||
|
// var magicInv = CommandManager.literal("magic-inv").build();
|
||||||
|
// var claim = CommandManager.literal("claim").executes(context -> ClaimInventory(context.getSource().getPlayer())).build();
|
||||||
|
|
||||||
|
// dispatcher.getRoot().addChild(magicInv);
|
||||||
|
// magicInv.addChild(claim);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
|
||||||
|
// var eChest = CommandManager.literal("enderchest").build();
|
||||||
|
// var player = CommandManager.argument("PLAYER", EntityArgumentType.player()).executes(
|
||||||
|
// context -> GetEnderchestOfPlayer(context.getSource().getPlayer(), EntityArgumentType.getPlayer(context, "PLAYER"))
|
||||||
|
// ).build();
|
||||||
|
|
||||||
|
// dispatcher.getRoot().addChild(eChest);
|
||||||
|
// eChest.addChild(player);
|
||||||
|
|
||||||
|
// // Alias
|
||||||
|
// dispatcher.register(CommandManager.literal("echest").redirect(eChest));
|
||||||
|
// });
|
||||||
|
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
|
||||||
|
var forceSpawn = CommandManager.literal("set-global-spawn").executes(context -> ForceGlobalSpawn(context.getSource().getPlayer())).build();
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(forceSpawn);
|
||||||
|
});
|
||||||
|
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
|
||||||
|
var warp = CommandManager.literal("warp").build();
|
||||||
|
|
||||||
|
var warpLoc = CommandManager.argument("LOCATION", StringArgumentType.string())
|
||||||
|
.executes(context -> Warp(context.getSource().getPlayer(), StringArgumentType.getString(context, "LOCATION"))).build();
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(warp);
|
||||||
|
warp.addChild(warpLoc);
|
||||||
|
});
|
||||||
|
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
|
||||||
|
var warp = CommandManager.literal("nick").build();
|
||||||
|
|
||||||
|
var warpLoc = CommandManager.argument("CUSTOM_NICKNAME", StringArgumentType.string())
|
||||||
|
.executes(context -> SetNickname(context.getSource().getPlayer(), StringArgumentType.getString(context, "CUSTOM_NICKNAME"))).build();
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(warp);
|
||||||
|
warp.addChild(warpLoc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Warp(ServerPlayerEntity player, String location) {
|
||||||
|
|
||||||
|
if (player.hasPermissionLevel(4)) {
|
||||||
|
System.out.println("Player is opped");
|
||||||
|
// hard coding spawn as only valid warp location. a more robust warp system can come later
|
||||||
|
DirectionalVec coords = GeneralConfig.GetInstance().GetSpawnCoords();
|
||||||
|
|
||||||
|
// DIRTY HACK: I am unsure how to compare the straight registry key. So for now, we will just iterate over all the worlds in the server. This really should
|
||||||
|
// not be a big deal since I have never seen a server with hundreds of worlds... but you never know I guess.
|
||||||
|
for (ServerWorld world : player.getServer().getWorlds()) {
|
||||||
|
System.out.println("Matched!");
|
||||||
|
if (world.getRegistryKey().toString().equals(coords.world.toString())) {
|
||||||
|
try {
|
||||||
|
player.teleport(world, coords.x, coords.y, coords.z, coords.yaw, coords.pitch);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
System.out.println("KEY {" + world.getRegistryKey() + "} DID NOT MATCH OURS {" + coords.world + "}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("POST TELEPORT");
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("This command is only available to server admins at the moment!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ForceGlobalSpawn(ServerPlayerEntity player) {
|
||||||
|
if (player.hasPermissionLevel(4)) {
|
||||||
|
Vec3d coords = player.getPos();
|
||||||
|
DirectionalVec spawnVec = new DirectionalVec();
|
||||||
|
spawnVec.x = coords.x;
|
||||||
|
spawnVec.y = coords.y;
|
||||||
|
spawnVec.z = coords.z;
|
||||||
|
spawnVec.pitch = player.getPitch();
|
||||||
|
spawnVec.yaw = player.getYaw();
|
||||||
|
spawnVec.world = player.getWorld().getRegistryKey();
|
||||||
|
System.out.println("REG KEY OF SET: " + player.getWorld().getRegistryKey().toString());
|
||||||
|
System.out.println("REG KEY OF SET: " + player.getWorld().getRegistryKey());
|
||||||
|
player.sendMessage(Text.of("Global spawn has been set to [X, Y, Z]--[YAW, PITCH]: [" +
|
||||||
|
spawnVec.x + " " + spawnVec.y + " " + spawnVec.z + "]--" + "[" + spawnVec.yaw + " " + spawnVec.pitch + "]" + " IN WORLD " +
|
||||||
|
player.getWorld().asString()));
|
||||||
|
|
||||||
|
GeneralConfig.GetInstance().SetSpawnCoords(spawnVec);
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("You do not have permission to use this command."));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SetNickname(ServerPlayerEntity player, String name) {
|
||||||
|
player.setCustomName(Text.of(name));
|
||||||
|
player.setCustomNameVisible(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetEnderchestOfPlayer(ServerPlayerEntity cmdInitiator, ServerPlayerEntity targetPlayer) {
|
||||||
|
|
||||||
|
// if (cmdInitiator.hasPermissionLevel(4)) {
|
||||||
|
// EnderChestInventory enderInv = targetPlayer.getEnderChestInventory();
|
||||||
|
// enderInv.
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public int ClaimInventory(ServerPlayerEntity player) {
|
||||||
|
// Vec3d playerPosition = player.getPos();
|
||||||
|
// BlockPos blockPosition = new BlockPos((int) playerPosition.x + 4, (int) playerPosition.y, (int) playerPosition.z).east();
|
||||||
|
// BlockPos blockPosition2 = new BlockPos((int) playerPosition.x + 3, (int) playerPosition.y, (int) playerPosition.z).east();
|
||||||
|
|
||||||
|
|
||||||
|
// // Verify we can place the blocks before loading cached inventory
|
||||||
|
// if (player.getWorld().setBlockState(blockPosition, chestState)
|
||||||
|
// && player.getWorld().setBlockState(blockPosition2, chestState)) {
|
||||||
|
|
||||||
|
// // The below code WILL remove the inventory from the dimension cache. Only get
|
||||||
|
// // it when we succeed in placing chests!
|
||||||
|
// NbtList nbtInventory = DimensionLoadingEvent.GetInstance().GetInventory(player.getUuidAsString());
|
||||||
|
// if (nbtInventory != null) {
|
||||||
|
// BlockEntity block = player.getWorld().getBlockEntity(blockPosition);
|
||||||
|
// BlockEntity block2 = player.getWorld().getBlockEntity(blockPosition2);
|
||||||
|
|
||||||
|
// if (block != null && block2 != null) {
|
||||||
|
// block.markDirty();
|
||||||
|
// block2.markDirty();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// player.sendMessage(Text.of("Look around, your magic inventory chest was placed near you!"));
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// player.sendMessage(Text.of("Well, this is embarassing! Could not place magic inventory chest near you!"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
}
|
@ -6,13 +6,12 @@ import com.mojang.brigadier.context.CommandContext;
|
|||||||
|
|
||||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
import jesse.keeblarcraft.JsonClassObjects.PlayerNote;
|
import jesse.keeblarcraft.JsonClassObjects.PlayerNote;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
import jesse.keeblarcraft.ChatStuff.ChatMsg;
|
||||||
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.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
public class NoteCommands {
|
public class NoteCommands {
|
||||||
/// Class Variables
|
/// Class Variables
|
||||||
@ -21,28 +20,10 @@ public class NoteCommands {
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
/// @fn NoteCommands
|
/// @fn NoteCommands
|
||||||
///
|
|
||||||
/// @brief This classes non-trivial constructor. Ensures creation
|
|
||||||
// of notes directory exists before commands can be ran
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
public NoteCommands() {
|
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!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//TODO: Rework note commands upon story mode release
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
/// @fn RegisterNoteCommands
|
/// @fn RegisterNoteCommands
|
||||||
///
|
///
|
||||||
@ -136,11 +117,11 @@ public class NoteCommands {
|
|||||||
// Note mgmt
|
// Note mgmt
|
||||||
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
||||||
note.AddNote(value, 1, 1, 1, 1);
|
note.AddNote(value, 1, 1, 1, 1);
|
||||||
ChatUtil.SendPlayerMsg(player, "New note logged to entry! View notes any time with /notegui");
|
player.sendMessage(Text.of("New note logged to entry! View notes any time with /notegui"));
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
System.out.println(ChatUtil.ColoredString("Only a player can execute this command!", CONSOLE_COLOR.RED));
|
System.out.println("Only a player can execute this command!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -165,7 +146,7 @@ public class NoteCommands {
|
|||||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||||
|
|
||||||
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
||||||
ChatUtil.SendPlayerMsg(player, "Deleted note entry. View notes any time with /notegui");
|
player.sendMessage(Text.of("Deleted note entry. View notes any time with /notegui"));
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
note.DeleteNote(value);
|
note.DeleteNote(value);
|
||||||
@ -205,7 +186,8 @@ public class NoteCommands {
|
|||||||
|
|
||||||
note.ModifyNote(value, newNote, epochTime, storyChapter, storyPart);
|
note.ModifyNote(value, newNote, epochTime, storyChapter, storyPart);
|
||||||
|
|
||||||
ChatUtil.SendPlayerMsg(player, "Modified note entry. View notes any time with /notegui");
|
player.sendMessage(Text.of("Modified note entry. View notes any time with /notegui"));
|
||||||
|
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
@ -231,7 +213,7 @@ public class NoteCommands {
|
|||||||
|
|
||||||
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
PlayerNote note = new PlayerNote(player.getUuidAsString());
|
||||||
note.PurgeAllNotes();
|
note.PurgeAllNotes();
|
||||||
ChatUtil.SendPlayerMsg(player, "Purged all notes. View notes any time with /notegui");
|
player.sendMessage(Text.of("Purged all notes. View notes any time with /notegui"));
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -258,11 +240,10 @@ public class NoteCommands {
|
|||||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||||
|
|
||||||
PlayerNote notes = new PlayerNote(player.getUuidAsString());
|
PlayerNote notes = new PlayerNote(player.getUuidAsString());
|
||||||
ChatUtil.SendPlayerMsg(player, "Listing all notes...");
|
|
||||||
for (int i = 0; i <= notes.GetNotebookSize(); i++) {
|
for (int i = 0; i <= notes.GetNotebookSize(); i++) {
|
||||||
String individualNote = notes.GetNoteString(i);
|
String individualNote = notes.GetNoteString(i);
|
||||||
if (individualNote != "") {
|
if (individualNote != "") {
|
||||||
ChatUtil.SendPlayerMsg(player, "Note " + i + ": " + individualNote);
|
player.sendMessage(Text.of("Note " + i + ": " + individualNote));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
src/main/java/jesse/keeblarcraft/Commands/ShopCommands.java
Normal file
18
src/main/java/jesse/keeblarcraft/Commands/ShopCommands.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package jesse.keeblarcraft.Commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
|
import net.minecraft.server.command.CommandManager;
|
||||||
|
|
||||||
|
public class ShopCommands {
|
||||||
|
public void RegisterShopCommands() {
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
var shopCmd = CommandManager.literal("shop").build();
|
||||||
|
|
||||||
|
var shopCreate = CommandManager.literal("create").build();
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(shopCmd);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -13,9 +13,10 @@ package jesse.keeblarcraft.Commands;
|
|||||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
import jesse.keeblarcraft.Utils.PlayerChecks;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
|
import net.minecraft.command.argument.EntityArgumentType;
|
||||||
import net.minecraft.entity.player.PlayerAbilities;
|
import net.minecraft.entity.player.PlayerAbilities;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
@ -24,8 +25,6 @@ import net.minecraft.server.network.ServerPlayerEntity;
|
|||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
public class ShortcutCommands {
|
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)
|
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()
|
public void RegisterShortcutCommands()
|
||||||
@ -39,31 +38,31 @@ public class ShortcutCommands {
|
|||||||
|
|
||||||
// Fly command
|
// Fly command
|
||||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
dispatcher.register(CommandManager.literal("fly")
|
var flightNode = CommandManager.literal("fly").executes(context -> FlightSpeedShortcut(null, context)).build();
|
||||||
.executes(context -> { FlightShortcut(context);
|
|
||||||
return 0;
|
var flightSpeed = CommandManager.argument("value", IntegerArgumentType.integer())
|
||||||
}));
|
.executes(context -> FlightSpeedShortcut(IntegerArgumentType.getInteger(context, "value"), context)).build();
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(flightNode);
|
||||||
|
flightNode.addChild(flightSpeed);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fly command with speed
|
|
||||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
dispatcher.register(CommandManager.literal("fly")
|
var healNode = CommandManager.literal("heal").executes(context -> HealShortcut(context, null)).build();
|
||||||
.then(CommandManager.argument("value", IntegerArgumentType.integer())
|
var targetPlayer = CommandManager.argument("targetPlayer", EntityArgumentType.player())
|
||||||
.executes(context -> FlightSpeedShortcut(IntegerArgumentType.getInteger(context, "value"), context))));
|
.executes(context -> HealShortcut(context, EntityArgumentType.getPlayer(context, "targetPlayer"))).build();
|
||||||
|
|
||||||
|
dispatcher.getRoot().addChild(healNode);
|
||||||
|
healNode.addChild(targetPlayer);
|
||||||
});
|
});
|
||||||
|
|
||||||
///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) -> {
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
dispatcher.register(CommandManager.literal("heal")
|
var feedNode = CommandManager.literal("feed").executes(context -> FeedShortcut(context, null)).build();
|
||||||
.executes(context -> { HealShortcut(context);
|
var targetPlayer = CommandManager.argument("targetPlayer", EntityArgumentType.player())
|
||||||
return 0;
|
.executes(context -> FeedShortcut(context, EntityArgumentType.getPlayer(context, "targetPlayer"))).build();
|
||||||
}));
|
|
||||||
|
dispatcher.getRoot().addChild(feedNode);
|
||||||
|
feedNode.addChild(targetPlayer);
|
||||||
});
|
});
|
||||||
|
|
||||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
@ -111,118 +110,79 @@ public class ShortcutCommands {
|
|||||||
retValue = -1;
|
retValue = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
player.sendMessage(Text.literal("\033[31m You do not have permissions to run this command! \033[0m"));
|
player.sendMessage(Text.literal("\033[31m You do not have permissions to run this command! \033[0m"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
System.out.println(ChatUtil.ColoredString("This command cannot be executed by a non-player entity!", CONSOLE_COLOR.RED));
|
Keeblarcraft.LOGGER.info("This command cannot be executed by a non-player entity!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int FlightShortcut(CommandContext<ServerCommandSource> context) {
|
private int FlightSpeedShortcut(Integer value, CommandContext<ServerCommandSource> context) {
|
||||||
int retValue = -1;
|
if (PlayerChecks.HasPermission(context)) {
|
||||||
if (context.getSource().isExecutedByPlayer()) {
|
|
||||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||||
|
PlayerAbilities abilities = player.getAbilities();
|
||||||
|
|
||||||
if (player.hasPermissionLevel(4)) {
|
// Disable flight
|
||||||
PlayerAbilities abilities = player.getAbilities();
|
if (abilities.flying && value == null) {
|
||||||
abilities.flying = !abilities.flying; // Toggle flying
|
abilities.flying = false;
|
||||||
abilities.setFlySpeed(DEFAULT_FLIGHT_SPEED); // It seems flight speed is on a 0-1 scale
|
abilities.allowFlying = false;
|
||||||
|
abilities.setFlySpeed(0);
|
||||||
|
player.sendMessage(Text.of("Disabled flight"));
|
||||||
player.sendAbilitiesUpdate();
|
player.sendAbilitiesUpdate();
|
||||||
ChatUtil.SendPlayerMsg(player, "You can now fly! Flight speed is " + abilities.getFlySpeed());
|
} else if (!abilities.flying && value == null) {
|
||||||
} else {
|
value = 1;
|
||||||
player.sendMessage(Text.literal("You do not have permission for this command"));
|
}
|
||||||
|
|
||||||
|
// Enable flight
|
||||||
|
if (value != null && 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();
|
||||||
|
player.sendMessage(Text.of("Flight speed set to " + value));
|
||||||
|
} else if (value != null) {
|
||||||
|
player.sendMessage(Text.literal("Only values from 1-10 are accepted"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return retValue;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int FlightSpeedShortcut(int value, CommandContext<ServerCommandSource> context) {
|
private int FeedShortcut(CommandContext<ServerCommandSource> context, ServerPlayerEntity target) {
|
||||||
int retValue = -1;
|
if (PlayerChecks.HasPermission(context)) {
|
||||||
|
// if target is null, feed ourselves
|
||||||
if (context.getSource().isExecutedByPlayer()) {
|
if (target == null) {
|
||||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||||
|
player.getHungerManager().setExhaustion(0.0f);
|
||||||
if (player.hasPermissionLevel(4)) {
|
player.getHungerManager().setFoodLevel(20); // 20 is hardcoded inside class
|
||||||
PlayerAbilities abilities = player.getAbilities();
|
player.getHungerManager().setSaturationLevel(10.0f); // 5 is set in constructor, but let's try 10!
|
||||||
|
player.sendMessage(Text.of("You were just super fed!"));
|
||||||
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 {
|
} else {
|
||||||
player.sendMessage(Text.literal("You do not have permission for this command"));
|
target.getHungerManager().setExhaustion(0.0f);
|
||||||
|
target.getHungerManager().setFoodLevel(20); // 20 is hardcoded inside class
|
||||||
|
target.getHungerManager().setSaturationLevel(10.0f); // 5 is set in constructor, but let's try 10!
|
||||||
|
target.sendMessage(Text.of("You were just super fed!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
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
|
private int HealShortcut(CommandContext<ServerCommandSource> context, ServerPlayerEntity target) {
|
||||||
///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;
|
int retValue = -1;
|
||||||
if (context.getSource().isExecutedByPlayer()) {
|
if (PlayerChecks.HasPermission(context)) {
|
||||||
ServerPlayerEntity player = context.getSource().getPlayer();
|
// If no player specified; then heal ourself full HP
|
||||||
|
if (target == null) {
|
||||||
if (player.hasPermissionLevel(4)) {
|
context.getSource().getPlayer().setHealth(context.getSource().getPlayer().getMaxHealth());
|
||||||
player.setHealth(player.getMaxHealth());
|
context.getSource().getPlayer().sendMessage(Text.of("Healed!"));
|
||||||
ChatUtil.SendPlayerMsg(player, "Healed!");
|
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage(Text.literal("You do not have permission for this command"));
|
target.setHealth(target.getMaxHealth());
|
||||||
|
target.sendMessage(Text.of("You were just healed!"));
|
||||||
|
context.getSource().getPlayer().sendMessage(Text.of("You healed " + target.getEntityName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import java.io.FileWriter;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
@ -28,63 +29,201 @@ import java.util.List;
|
|||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import jesse.keeblarcraft.Utils.CustomExceptions.*;
|
import net.minecraft.nbt.NbtIo;
|
||||||
|
import net.minecraft.nbt.NbtList;
|
||||||
|
|
||||||
public class ConfigManager {
|
public class ConfigManager {
|
||||||
|
|
||||||
// Pedantic empty constructor
|
// Pedantic empty constructor
|
||||||
|
private static final String GLOBAL_CONFIG = "config/keeblarcraft/";
|
||||||
|
|
||||||
public ConfigManager() {}
|
public ConfigManager() {}
|
||||||
|
|
||||||
// CreateFile
|
// Get a File reference to a file that is created on disk
|
||||||
//
|
private File GetFile(String confFile) {
|
||||||
// Returns true if file is created, will return false if file cannot be created (returns true if already exists)
|
File file = null;
|
||||||
public Boolean CreateFile(String fileName) throws FILE_CREATE_EXCEPTION {
|
try {
|
||||||
Boolean ret = false;
|
file = new File(GLOBAL_CONFIG + confFile);
|
||||||
File file = new File(fileName);
|
} catch (Exception e) {}
|
||||||
|
return file;
|
||||||
// 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 the parent path to a given input.
|
||||||
//
|
// Ex: /home/Downloads/file.txt will return /home/Downloads/
|
||||||
// Returns true if file is deleted, false if could not be deleted or does not exist
|
// Ex: /home/Downloads will return /home/
|
||||||
public Boolean DeleteFile(String fileName) throws FILE_DELETE_EXCEPTION {
|
// Ex: / will return /
|
||||||
Boolean ret = false;
|
private String GetPathOfFile(String file) {
|
||||||
File file = new File(fileName);
|
String pathToFile = "";
|
||||||
|
if (file != null) {
|
||||||
|
for (int i = file.length() - 1; i >= 0; i--) {
|
||||||
|
if (file.charAt(i) != File.separatorChar) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Trim and break
|
||||||
|
pathToFile = file.substring(0, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Step 1: Does file exist?
|
System.out.println("PathOfFile: " + pathToFile);
|
||||||
ret = file.exists();
|
return pathToFile;
|
||||||
|
}
|
||||||
|
|
||||||
// Step 2: If file exists, attempt to delete
|
// Creates a directory and all necessary parent directories listed in dirname (under global config area)
|
||||||
if (ret == true) {
|
public Boolean CreateDirectory(String dirName) {
|
||||||
|
Boolean success = false;
|
||||||
|
File directory = GetFile(dirName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (directory != null) {
|
||||||
|
if (!directory.exists())
|
||||||
|
{
|
||||||
|
success = directory.mkdirs();
|
||||||
|
} else if (directory.isDirectory()) {
|
||||||
|
success = true;
|
||||||
|
} else {
|
||||||
|
System.out.println("Directory " + dirName + " is an already existing file!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Failed to create directory with name " + dirName);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a file on the disk
|
||||||
|
public Boolean CreateFile(String fileName) {
|
||||||
|
Boolean success = false;
|
||||||
|
File file = GetFile(fileName);
|
||||||
|
String parentDir = GetPathOfFile(fileName);
|
||||||
|
|
||||||
|
// CreateDirectory will verify that the parent directories exist & at least the parent directory is in fact a directory
|
||||||
|
if (file != null && !file.exists() && CreateDirectory(parentDir)) {
|
||||||
try {
|
try {
|
||||||
ret = file.delete();
|
success = file.createNewFile();
|
||||||
} catch (SecurityException e) {
|
} catch (Exception e) {
|
||||||
throw new FILE_DELETE_EXCEPTION();
|
System.out.println("Failed to create file " + fileName);
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
} 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));
|
System.out.println("CreateFile failed to finish. File may have been null (empty string input, unlikely), or parent directories could not be created/have overlapped name");
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
return ret;
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean DeleteFile(String fileName) {
|
||||||
|
Boolean success = false;
|
||||||
|
File file = GetFile(fileName);
|
||||||
|
|
||||||
|
success = !file.exists();
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
try {
|
||||||
|
success = file.delete();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Failed to delete file " + fileName);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn WriteNbtListToFile
|
||||||
|
///
|
||||||
|
/// @param[in] fileName is the file location to write to
|
||||||
|
///
|
||||||
|
/// @param[in] key is the compound key type to store
|
||||||
|
///
|
||||||
|
/// @param[in] data is the NbtList to write
|
||||||
|
///
|
||||||
|
/// @brief Writes NbtList data to disk
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void WriteNbtListToFile(String fileName, String key, NbtList data) {
|
||||||
|
// fileName = "config/keeblarcraft/" + fileName;
|
||||||
|
|
||||||
|
File file = GetFile(fileName);
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
NbtCompound compound = new NbtCompound();
|
||||||
|
compound.put(key, data);
|
||||||
|
NbtIo.writeCompressed(compound, file);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ReadAllNbtListFromDirectory
|
||||||
|
///
|
||||||
|
/// @param[in] dir is the directory path to read from
|
||||||
|
///
|
||||||
|
/// @param[in] listType is the NBT Compound list type
|
||||||
|
///
|
||||||
|
/// @brief Reads in NBTList data from a directory; using file names as key.
|
||||||
|
/// If a file is read in correctly, the file is deleted
|
||||||
|
///
|
||||||
|
/// @return A map of NbtList data with the key being the file name (minus ext)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public HashMap<String, NbtList> ReadAllNbtListFromDirectory(String dir, int listType) {
|
||||||
|
HashMap<String, NbtList> list = new HashMap<String, NbtList>();
|
||||||
|
// dir = "config/keeblarcraft/" + dir;
|
||||||
|
|
||||||
|
File directory = GetFile(dir);
|
||||||
|
|
||||||
|
File[] files = directory.listFiles();
|
||||||
|
|
||||||
|
if (files != null) {
|
||||||
|
for (File file : files) {
|
||||||
|
String key = file.getName().substring(0, file.getName().length() - 4);
|
||||||
|
NbtList nbtList = ReadNbtListFromFile(file, key, listType);
|
||||||
|
|
||||||
|
if (nbtList != null) {
|
||||||
|
// Subtract out '.nbt' from name
|
||||||
|
list.put(key, nbtList);
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ReadNbtListFromFile
|
||||||
|
///
|
||||||
|
/// @param[in] file handler object to read nbt list data from
|
||||||
|
///
|
||||||
|
/// @param[in] key for the nbt compound object
|
||||||
|
///
|
||||||
|
/// @param[in] listType is the NBT Compound list type
|
||||||
|
///
|
||||||
|
/// @brief Reads in NBTList data from a single file
|
||||||
|
///
|
||||||
|
/// @return NbtList data
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public NbtList ReadNbtListFromFile(File file, String key, int listType) {
|
||||||
|
NbtList list = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
NbtCompound c = NbtIo.readCompressed(file);
|
||||||
|
list = c.getList(key, listType);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteToFile
|
// WriteToFile
|
||||||
@ -95,7 +234,7 @@ public class ConfigManager {
|
|||||||
|
|
||||||
FileWriter file;
|
FileWriter file;
|
||||||
try {
|
try {
|
||||||
file = new FileWriter(fileName);
|
file = new FileWriter(GetFile(fileName));
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case "w":
|
case "w":
|
||||||
file.write(data);
|
file.write(data);
|
||||||
@ -106,13 +245,14 @@ public class ConfigManager {
|
|||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
System.out.println(ChatUtil.ColoredString("Invalid mode to WriteToFile!", CONSOLE_COLOR.RED));
|
Keeblarcraft.LOGGER.debug("Invalid mode to WriteToFile!!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
} catch (IOException e) {
|
} 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));
|
e.printStackTrace();
|
||||||
|
Keeblarcraft.LOGGER.error("Could not open file " + fileName + " to write to it! Possible permissions issue??");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -128,16 +268,23 @@ public class ConfigManager {
|
|||||||
// top-level key.
|
// top-level key.
|
||||||
//
|
//
|
||||||
// NOTE: THIS DOES NOT SAFE UPDATE THE KEY OBJECT. PRE-EXISTING DATA WILL BE DELETED FOREVER
|
// 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 {
|
public void WriteToJsonFile(String fileName, Object data) {
|
||||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
try {
|
try {
|
||||||
FileWriter writer = new FileWriter(fileName);
|
// The FileWriter cannot create objects; so we create parent directories before writing. This may be
|
||||||
|
// changed in the future
|
||||||
|
File parent = GetFile(fileName).getParentFile();
|
||||||
|
if (!parent.exists()) {
|
||||||
|
parent.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
FileWriter writer = new FileWriter(GetFile(fileName));
|
||||||
gson.toJson(data, writer);
|
gson.toJson(data, writer);
|
||||||
writer.flush();
|
writer.flush();
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (JsonIOException | IOException e) {
|
} catch (JsonIOException | IOException e) {
|
||||||
System.out.println(ChatUtil.ColoredString("Could not successfully write to json file", CONSOLE_COLOR.RED));
|
Keeblarcraft.LOGGER.error("Could not successfully write to json file ["+fileName+"]");
|
||||||
throw new FILE_WRITE_EXCEPTION();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,73 +298,28 @@ public class ConfigManager {
|
|||||||
// hot fix: Not sure how to return "false" for invalid conversion when I'm forced to convert or just catch... Look into a better
|
// 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
|
// return value in the future - but for now throw JsonSyntaxException no matter what exception is caught
|
||||||
try {
|
try {
|
||||||
File file = new File(fileName);
|
File file = GetFile(fileName);
|
||||||
ret = FileUtils.readFileToString(file, "UTF-8");
|
ret = FileUtils.readFileToString(file, "UTF-8");
|
||||||
} catch (NullPointerException e) {
|
} catch (Exception e) {
|
||||||
System.out.println(ChatUtil.ColoredString("nullptr exception", CONSOLE_COLOR.RED));
|
e.printStackTrace();
|
||||||
throw new JsonSyntaxException("");
|
System.out.println("Caught an exception in retrieving JSON Object from file " + fileName);
|
||||||
} catch (FileNotFoundException e) {
|
// throw new JsonSyntaxException("");
|
||||||
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);
|
return gson.fromJson(ret, classToConvertTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean DoesFileExist(String fileName) {
|
public Boolean DoesFileExist(String fileName) {
|
||||||
return new File(fileName).exists(); // untested
|
return GetFile(fileName).exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean DoesDirectoryExist(String dirName) {
|
public Boolean DoesDirectoryExist(String dirName) {
|
||||||
return new File(dirName).isDirectory(); // untested
|
File file = GetFile(dirName);
|
||||||
|
return file != null && file.isDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean CreateDirectory(String dirName) throws DIRECTORY_CREATE_EXCEPTION {
|
public Boolean DeleteDirectory(String dirName) {
|
||||||
Boolean ret = false;
|
return DeleteFile(dirName);
|
||||||
|
|
||||||
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
|
// GetFile
|
||||||
@ -225,11 +327,11 @@ public class ConfigManager {
|
|||||||
// Returns a file as an arraylist of all the lines in the file. Generally only used for testing
|
// 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
|
// NOTE: Returns UTF-8 Encoding of file
|
||||||
public List<String> GetFile(String fileName) {
|
public List<String> GetFileLines(String fileName) {
|
||||||
List<String> ret = new ArrayList<String>();
|
List<String> ret = new ArrayList<String>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return Files.readLines(new File(fileName), Charsets.UTF_8);
|
return Files.readLines(GetFile(fileName), Charsets.UTF_8);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
ret.clear();
|
ret.clear();
|
||||||
}
|
}
|
||||||
|
166
src/main/java/jesse/keeblarcraft/ConfigMgr/GeneralConfig.java
Normal file
166
src/main/java/jesse/keeblarcraft/ConfigMgr/GeneralConfig.java
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package jesse.keeblarcraft.ConfigMgr;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Utils.DirectionalVec;
|
||||||
|
|
||||||
|
public class GeneralConfig {
|
||||||
|
private static GeneralConfig static_inst;
|
||||||
|
ConfigManager cfgMgr = new ConfigManager();
|
||||||
|
private ImplementedConfig config;
|
||||||
|
|
||||||
|
public static GeneralConfig GetInstance() {
|
||||||
|
if (static_inst == null) {
|
||||||
|
static_inst = new GeneralConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetConfig
|
||||||
|
///
|
||||||
|
/// @brief Returns the mods general configuration file object
|
||||||
|
///
|
||||||
|
/// @return The configuration object
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public ImplementedConfig GetConfig() {
|
||||||
|
if (config == null) {
|
||||||
|
config = new ImplementedConfig();
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GeneralConfig
|
||||||
|
///
|
||||||
|
/// @brief Constructs the general configuration file for the project
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public GeneralConfig() {
|
||||||
|
Boolean existingFile = false;
|
||||||
|
try {
|
||||||
|
config = cfgMgr.GetJsonObjectFromFile("general.json", ImplementedConfig.class);
|
||||||
|
|
||||||
|
existingFile = true;
|
||||||
|
} catch(Exception e) {
|
||||||
|
System.out.println("FAILED TO READ IN GENERALCONFIG");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existingFile) {
|
||||||
|
config = new ImplementedConfig();
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config == null) {
|
||||||
|
config = new ImplementedConfig();
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetSpawnCoords
|
||||||
|
///
|
||||||
|
/// @brief Gets the coordinates for the global spawn
|
||||||
|
///
|
||||||
|
/// @return A vector containing how a player should spawn in or null if not
|
||||||
|
/// set yet.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public DirectionalVec GetSpawnCoords() {
|
||||||
|
return config.global_spawn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn SetSpawnCoords
|
||||||
|
///
|
||||||
|
/// @brief Sets the coordinates for the global spawn
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void SetSpawnCoords(DirectionalVec vec) {
|
||||||
|
config.global_spawn = vec;
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetSQLPassword
|
||||||
|
///
|
||||||
|
/// @brief Returns the SQL password set in the text config
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public String GetSQLPassword() {
|
||||||
|
return config.sqlPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String GetSQLUsername() {
|
||||||
|
return config.sqlUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String GetSQLAddress() {
|
||||||
|
return config.sqlAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String GetSQLDatabase() {
|
||||||
|
return config.sqlDatabaseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IsNewPlayer
|
||||||
|
///
|
||||||
|
/// @param[in] uuid is the player uuid
|
||||||
|
///
|
||||||
|
/// @brief Checks to see if player uuid has ever joined. If not, then add
|
||||||
|
/// to global list of uuids who have joined.
|
||||||
|
///
|
||||||
|
/// @return True if player is new, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean IsNewPlayer(String uuid) {
|
||||||
|
System.out.println("Is config null? " + (config == null ? "YES" : "NO"));
|
||||||
|
System.out.println("IsNewPlayer called. List has: " + config.playerList);
|
||||||
|
Boolean isNew = !config.playerList.contains(uuid);
|
||||||
|
|
||||||
|
System.out.println("Value of isNew is " + isNew);
|
||||||
|
|
||||||
|
if (isNew) {
|
||||||
|
config.playerList.add(uuid);
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
return isNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetMOTD
|
||||||
|
///
|
||||||
|
/// @brief String object with the MOTD of the server
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public String GetMOTD() {
|
||||||
|
return config.MOTD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @class ImplementedConfig is the configuration class holder
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private class ImplementedConfig {
|
||||||
|
public String MOTD = "Welcome to the server! Have fun!";
|
||||||
|
public String sqlAddress = "localhost";
|
||||||
|
public String sqlDatabaseName = "keeblarcraft";
|
||||||
|
public String sqlUsername = "SQL_USERNAME";
|
||||||
|
public String sqlPassword = "SQL_PASSWORD";
|
||||||
|
|
||||||
|
// This is lazy, but this will fill with every unique UUID that has joined the server. This is how I am checking
|
||||||
|
// to see if a player has just joined the server for a first time or not
|
||||||
|
public List<String> playerList = new ArrayList<>();
|
||||||
|
DirectionalVec global_spawn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn FlashConfig
|
||||||
|
///
|
||||||
|
/// @brief String object with the MOTD of the server
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private void FlashConfig() {
|
||||||
|
System.out.println("Attempting to write generalconfig to file. Is null? " + (config == null ? "YES" : "NO"));
|
||||||
|
cfgMgr.WriteToJsonFile("general.json", config);
|
||||||
|
}
|
||||||
|
}
|
184
src/main/java/jesse/keeblarcraft/ConfigMgr/SQLConfig.java
Normal file
184
src/main/java/jesse/keeblarcraft/ConfigMgr/SQLConfig.java
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package jesse.keeblarcraft.ConfigMgr;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.SQLTypeSupport.VALID_SQL_TYPE;
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
|
||||||
|
|
||||||
|
public class SQLConfig {
|
||||||
|
private static SQLConfig static_inst;
|
||||||
|
private String dbName;
|
||||||
|
private String dbUser;
|
||||||
|
private String dbPass;
|
||||||
|
private String dbAddr;
|
||||||
|
private Boolean connected = false;
|
||||||
|
private Connection conn = null; // Actual connection object
|
||||||
|
|
||||||
|
private enum SQL_RUN_TYPE {
|
||||||
|
GENERAL,
|
||||||
|
QUERY,
|
||||||
|
UPDATE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Direct return object in relation to the SQL_RUN_TYPE of the SQL command that was used. Only one will
|
||||||
|
// be filled out properly for what you run - the other values will be null and not cleared!
|
||||||
|
private class SQLRunReturn {
|
||||||
|
Boolean generalRet;
|
||||||
|
ResultSet queryReturn;
|
||||||
|
Integer updateReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SQLConfig GetInstance() {
|
||||||
|
if (static_inst == null) {
|
||||||
|
static_inst = new SQLConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SQLConfig() {
|
||||||
|
connected = false;
|
||||||
|
try {
|
||||||
|
// According to some random online tutorial; this loads the driver!
|
||||||
|
Class.forName("com.mysql.cj.jdbc.Driver");
|
||||||
|
connected = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Could not find the proper SQL JDBC Drivers. Cannot connect to SQL Config");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
try {
|
||||||
|
dbName = GeneralConfig.GetInstance().GetSQLDatabase();
|
||||||
|
dbUser = GeneralConfig.GetInstance().GetSQLUsername();
|
||||||
|
dbPass = GeneralConfig.GetInstance().GetSQLPassword();
|
||||||
|
dbAddr = "jdbc:mysql://" + GeneralConfig.GetInstance().GetSQLAddress() + "/" + dbName;
|
||||||
|
conn = DriverManager.getConnection(dbAddr, dbUser, dbPass);
|
||||||
|
} catch (SQLException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLRunReturn RunCommand(String sqlCommand, SQL_RUN_TYPE type) {
|
||||||
|
SQLRunReturn sqlData = new SQLRunReturn();
|
||||||
|
// If conn is null; we may need to reconnect before running the command
|
||||||
|
if (conn == null) {
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn != null) {
|
||||||
|
try {
|
||||||
|
Statement statement = conn.createStatement();
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case GENERAL:
|
||||||
|
sqlData.generalRet = statement.execute(sqlCommand);
|
||||||
|
break;
|
||||||
|
case QUERY:
|
||||||
|
sqlData.queryReturn = statement.executeQuery(sqlCommand);
|
||||||
|
break;
|
||||||
|
case UPDATE:
|
||||||
|
sqlData.updateReturn = statement.executeUpdate(sqlCommand);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
System.out.println(e.getSQLState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sqlData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-attempt the connection
|
||||||
|
public Boolean Connect() {
|
||||||
|
if (conn != null) {
|
||||||
|
try {
|
||||||
|
conn.close();
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean success = false;
|
||||||
|
try {
|
||||||
|
conn = DriverManager.getConnection(dbAddr, dbUser, dbPass);
|
||||||
|
success = true;
|
||||||
|
} catch (Exception e) {}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean IsConnected() {
|
||||||
|
return conn != null && this.connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The case is converted to upper case automatically to be case insensitive
|
||||||
|
public Boolean DoesTableExist(String name) {
|
||||||
|
boolean tableExists = false;
|
||||||
|
if (conn != null) {
|
||||||
|
try (ResultSet rs = conn.getMetaData().getTables(null, null, name, null)) {
|
||||||
|
while (rs.next()) {
|
||||||
|
String tName = rs.getString("TABLE_NAME");
|
||||||
|
if (tName != null && tName.equals(name)) {
|
||||||
|
tableExists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {}
|
||||||
|
}
|
||||||
|
return tableExists;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean MakeNonNullable(String table, String columnName) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer AddPrimaryKey(String tableName, String primaryKeyColumn) {
|
||||||
|
SQLRunReturn success = new SQLRunReturn();
|
||||||
|
|
||||||
|
if (DoesTableExist(tableName)) {
|
||||||
|
String sqlCmd = "ALTER TABLE " + tableName + " ADD PRIMARY KEY (" + primaryKeyColumn + ");";
|
||||||
|
|
||||||
|
success = RunCommand(sqlCmd, SQL_RUN_TYPE.UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success.updateReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer AddForeignKey(String primaryTableName, String primaryColumnName, String foreignTableName, String foreignKeyColumn) {
|
||||||
|
SQLRunReturn success = new SQLRunReturn();
|
||||||
|
Boolean primaryTableExists = DoesTableExist(primaryTableName);
|
||||||
|
Boolean foreignTableExists = DoesTableExist(foreignTableName);
|
||||||
|
|
||||||
|
if (primaryTableExists && foreignTableExists) {
|
||||||
|
String sqlCmd = "ALTER TABLE " + primaryTableName + " ADD FOREIGN KEY (" + primaryColumnName + ") REFERENCES " + foreignTableName + " (" + foreignKeyColumn + ")";
|
||||||
|
success = RunCommand(sqlCmd, SQL_RUN_TYPE.UPDATE);
|
||||||
|
}
|
||||||
|
return success.updateReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Might fix heap pollution decay in future with enum types or something. For now we assume the user isn't horrifically stupid and will give a SQL-able type
|
||||||
|
public Boolean CreateTable(String tableName, Pair<String, VALID_SQL_TYPE>... columnPairs) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (conn != null && !DoesTableExist(tableName.toUpperCase())) {
|
||||||
|
String sqlCommand = "CREATE TABLE " + tableName.toUpperCase() + "(";
|
||||||
|
for (Pair<String, VALID_SQL_TYPE> colPair : columnPairs) {
|
||||||
|
sqlCommand = sqlCommand + " " + colPair.GetKey() + " " + SQLTypeSupport.GetSqlStrForType(colPair.GetValue()) + ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip the leading comma and append the ending ');' on the SQL statement
|
||||||
|
sqlCommand = sqlCommand.substring(0, sqlCommand.length() - 1) + ");";
|
||||||
|
|
||||||
|
SQLRunReturn rs = RunCommand(sqlCommand, SQL_RUN_TYPE.GENERAL);
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (rs.queryReturn.next()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package jesse.keeblarcraft.ConfigMgr;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.SQLTypeSupport.VALID_SQL_TYPE;
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
|
||||||
|
|
||||||
|
public class SQLInitServer {
|
||||||
|
// Initial run-time checks to make sure tables are all setup in advanced
|
||||||
|
public void Initialize() {
|
||||||
|
SetupTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void SetupTables() {
|
||||||
|
// TABLE NAMES
|
||||||
|
String accountsTable = "ACCOUNTS";
|
||||||
|
String banksTable = "BANKS";
|
||||||
|
String customerTable = "CUSTOMER";
|
||||||
|
String transactionTable = "TRANSACTION";
|
||||||
|
|
||||||
|
// Create the ACCOUNTS table
|
||||||
|
Pair<String, VALID_SQL_TYPE> accountsGlobalId = new Pair<>("global_account_id", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> userUuid = new Pair<>("address", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> accountType = new Pair<>("account_type", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> balance = new Pair<>("balance", VALID_SQL_TYPE.BIGINT);
|
||||||
|
Pair<String, VALID_SQL_TYPE> openDate = new Pair<>("open_date", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
SQLConfig.GetInstance().CreateTable(accountsTable, accountsGlobalId, userUuid, accountType, balance, openDate);
|
||||||
|
|
||||||
|
// Create the CUSTOMER table
|
||||||
|
Pair<String, VALID_SQL_TYPE> playerUuid = new Pair<>("player_uuid", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> playerName = new Pair<>("player_entity_name", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
SQLConfig.GetInstance().CreateTable(customerTable, playerUuid, playerName);
|
||||||
|
|
||||||
|
// Create the BANKS table
|
||||||
|
Pair<String, VALID_SQL_TYPE> bankRouting = new Pair<>("routing", VALID_SQL_TYPE.BIGINT);
|
||||||
|
Pair<String, VALID_SQL_TYPE> bankName = new Pair<>("bank_name", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> bankSymbol = new Pair<>("bank_symbol", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> bankDateOpened = new Pair<>("date_opened", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
SQLConfig.GetInstance().CreateTable(banksTable, bankRouting, bankName, bankSymbol, bankDateOpened);
|
||||||
|
|
||||||
|
// Create the TRANSACTION table
|
||||||
|
Pair<String, VALID_SQL_TYPE> transactionId = new Pair<>("transaction_id", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> transactionDate = new Pair<>("transaction_date", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> transactionType = new Pair<>("transaction_type", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> transactionAmount = new Pair<>("amount", VALID_SQL_TYPE.BIGINT);
|
||||||
|
Pair<String, VALID_SQL_TYPE> transactionFromAccount = new Pair<>("account_id", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> transactionDescription = new Pair<>("description", VALID_SQL_TYPE.TEXT);
|
||||||
|
Pair<String, VALID_SQL_TYPE> transactionDestination = new Pair<>("destination", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
SQLConfig.GetInstance().CreateTable(transactionTable, transactionId, transactionDate, transactionType, transactionAmount,
|
||||||
|
transactionFromAccount, transactionDescription, transactionDestination);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package jesse.keeblarcraft.ConfigMgr;
|
||||||
|
|
||||||
|
public class SQLTypeSupport {
|
||||||
|
public enum VALID_SQL_TYPE {
|
||||||
|
VARCHAR,
|
||||||
|
BIGINT,
|
||||||
|
INT,
|
||||||
|
TEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produces the word that SQL would expect for the given datatype. In general it's usually just the word itself but in cases
|
||||||
|
// like 'varchar' you usually specify a size too. For now it defaults 255 but this can be expanded in the future
|
||||||
|
public static String GetSqlStrForType(VALID_SQL_TYPE type) {
|
||||||
|
switch(type) {
|
||||||
|
case VARCHAR:
|
||||||
|
return "VARCHAR(255)";
|
||||||
|
case BIGINT:
|
||||||
|
return "BIGINT";
|
||||||
|
case INT:
|
||||||
|
return "INT";
|
||||||
|
case TEXT:
|
||||||
|
return "TEXT";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null; // This should never get hit
|
||||||
|
}
|
||||||
|
}
|
38
src/main/java/jesse/keeblarcraft/ConfigMgr/SQLUnitTest.java
Normal file
38
src/main/java/jesse/keeblarcraft/ConfigMgr/SQLUnitTest.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package jesse.keeblarcraft.ConfigMgr;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.SQLTypeSupport.VALID_SQL_TYPE;
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
|
||||||
|
|
||||||
|
// Random commands to run to test the SQL class
|
||||||
|
public class SQLUnitTest {
|
||||||
|
public void RunTests() {
|
||||||
|
CreateTableTest();
|
||||||
|
ForeignKeyTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateTableTest() {
|
||||||
|
String tableName = "test_table";
|
||||||
|
Pair<String, VALID_SQL_TYPE> pairOne = new Pair<>("name", VALID_SQL_TYPE.VARCHAR);
|
||||||
|
Pair<String, VALID_SQL_TYPE> pairTwo = new Pair<>("address", VALID_SQL_TYPE.BIGINT);
|
||||||
|
Pair<String, VALID_SQL_TYPE> pairThree = new Pair<>("email", VALID_SQL_TYPE.TEXT);
|
||||||
|
|
||||||
|
SQLConfig.GetInstance().CreateTable(tableName, pairOne, pairTwo, pairThree);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DoesTableExistTest() {
|
||||||
|
String tableName = "test_table";
|
||||||
|
Boolean temp = SQLConfig.GetInstance().DoesTableExist(tableName.toUpperCase());
|
||||||
|
|
||||||
|
System.out.println("[SQL-UnitTest]: Does the table " + tableName + " exist? " + (temp ? "YES":"NO"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ForeignKeyTest() {
|
||||||
|
String primTableName = "test_table";
|
||||||
|
String primColName = "name";
|
||||||
|
String foreTableName = "accounts";
|
||||||
|
String foreColName = "global_account_id";
|
||||||
|
|
||||||
|
Integer ret = SQLConfig.GetInstance().AddForeignKey(primTableName, primColName, foreTableName, foreColName);
|
||||||
|
System.out.println("[SQL-UnitTest]: Update foreign key test. Got return result number: " + ret);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package jesse.keeblarcraft.CustomBlocks.BlockEntities;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.CustomBlocks.BlockManager;
|
||||||
|
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||||
|
import net.minecraft.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.registry.Registry;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
// EVENTUALLY THIS CLASS WILL GET COLLAPSED UNDER @ref BlockManager.java
|
||||||
|
// However; I don't have the time to figure out how to do this dynamically this second (I'm lazy and doing this
|
||||||
|
// all in one sitting)
|
||||||
|
public class BlockEntityRegistration {
|
||||||
|
// PLEASE STICK A COMMENT ABOVE EACH REGISTRATION FOR LATER REFERENCE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// FactionBlockEntity
|
||||||
|
public static final BlockEntityType<FactionBlockEntity> FACTION_BLOCK_ENTITY =
|
||||||
|
Registry.register(Registries.BLOCK_ENTITY_TYPE, new Identifier(Keeblarcraft.MOD_ID, "faction_block_entity"),
|
||||||
|
FabricBlockEntityTypeBuilder.create(FactionBlockEntity::new, BlockManager.GetBlock("faction_base_block")).build());
|
||||||
|
|
||||||
|
public static void RegisterBlockEntities() {
|
||||||
|
Keeblarcraft.LOGGER.info("Registering block entities for " + Keeblarcraft.MOD_ID);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,231 @@
|
|||||||
|
package jesse.keeblarcraft.CustomBlocks.BlockEntities;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
|
||||||
|
import jesse.keeblarcraft.Callbacks.MobSpawnCallback;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionConfig;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionManager;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerEnteredBaseCallback;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerExitedBaseCallback;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerInBaseCallback;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
|
||||||
|
import jesse.keeblarcraft.GuiMgr.Factions.FactionBlockScreenHandler;
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Position3d;
|
||||||
|
import jesse.keeblarcraft.world.ImplementedInventory;
|
||||||
|
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.inventory.Inventories;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.screen.PropertyDelegate;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.util.collection.DefaultedList;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class FactionBlockEntity extends BlockEntity implements ExtendedScreenHandlerFactory, ImplementedInventory {
|
||||||
|
private final DefaultedList<ItemStack> inventory = DefaultedList.ofSize(7, ItemStack.EMPTY);
|
||||||
|
|
||||||
|
private String faction = null; // Faction this block belongs to
|
||||||
|
private static int factionPower = 0;
|
||||||
|
private FactionTierEnum factionTier = FactionTierEnum.TIER_INVALID;
|
||||||
|
private Boolean hasStopMobSpawn = true;
|
||||||
|
private Boolean registeredMobSpawnCallback = false;
|
||||||
|
private Boolean hasBuildFlight = true;
|
||||||
|
private Boolean hasSuperBeacon = true;
|
||||||
|
private Position3d storedBlockPos;
|
||||||
|
private final double factionDefaultRadiusBlocks = 50; // 50 blocks
|
||||||
|
private ArrayList<String> playersInRadius = new ArrayList<>();
|
||||||
|
private HashMap<String, FactionConfig.VALID_FACTION_ROLES> factionPlayers;
|
||||||
|
|
||||||
|
protected final PropertyDelegate propertyDelegate;
|
||||||
|
|
||||||
|
public FactionBlockEntity(BlockPos pos, BlockState state, String faction) {
|
||||||
|
this(pos, state);
|
||||||
|
this.faction = faction;
|
||||||
|
RegisterMobSpawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFaction(String faction) {
|
||||||
|
this.faction = faction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String GetFaction() {
|
||||||
|
return this.faction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FactionBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
super(BlockEntityRegistration.FACTION_BLOCK_ENTITY, pos, state);
|
||||||
|
storedBlockPos = new Position3d(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
this.propertyDelegate = new PropertyDelegate() {
|
||||||
|
@Override
|
||||||
|
public int get(int index) {
|
||||||
|
// The only value we need to get/delegate is faction power
|
||||||
|
return factionPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(int index, int value) {
|
||||||
|
factionPower = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
// We are only syncing 1 integer - faction power
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterMobSpawn() {
|
||||||
|
if (hasStopMobSpawn && !registeredMobSpawnCallback) {
|
||||||
|
MobSpawnCallback.EVENT.register((world, mob) -> {
|
||||||
|
HandleMobSpawn(world, mob);
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make sure mobs are within range before targeting!
|
||||||
|
private void HandleMobSpawn(World world, MobEntity mob) {
|
||||||
|
if (world.isClient()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mob.setDespawnCounter(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Text getDisplayName() {
|
||||||
|
return Text.literal("Faction Home Base Station"); // Replace with proper en_us format later
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) {
|
||||||
|
return new FactionBlockScreenHandler(syncId, playerInventory, this, this.propertyDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readNbt(NbtCompound nbt) {
|
||||||
|
super.readNbt(nbt);
|
||||||
|
Inventories.readNbt(nbt, inventory);
|
||||||
|
factionPower = nbt.getInt("faction_block_entity.power");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeNbt(NbtCompound nbt) {
|
||||||
|
super.writeNbt(nbt);
|
||||||
|
// Write the inventory of the block
|
||||||
|
Inventories.writeNbt(nbt, inventory);
|
||||||
|
nbt.putInt("faction_block_entity.power", factionPower);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefaultedList<ItemStack> getItems() {
|
||||||
|
return inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf) {
|
||||||
|
// Send position of this block entity from server->client->server etc
|
||||||
|
buf.writeBlockPos(this.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is uniquely only calculating the second coordinate on 'storedBlockPos' which is the center coordinate of the
|
||||||
|
// hypothetical sphere
|
||||||
|
private Boolean DistanceToCenterSphere(double x, double y, double z) {
|
||||||
|
// Distance between two points
|
||||||
|
double dist = Math.ceil(Math.sqrt(
|
||||||
|
Math.abs(Math.pow(Math.floor(x) - storedBlockPos.x, 2)) +
|
||||||
|
Math.abs(Math.pow(Math.floor(y) - storedBlockPos.y, 2)) +
|
||||||
|
Math.abs(Math.pow(Math.floor(z) - storedBlockPos.z, 2))));
|
||||||
|
|
||||||
|
// Arbitrarily for now; each point of faction power increases the distance by 10. Testing will confirm if this
|
||||||
|
// is too much or too little. Making this configurable would probably be good to
|
||||||
|
// Default radius; increased by power
|
||||||
|
double factionBlockRadius = factionDefaultRadiusBlocks + (10 * factionPower);
|
||||||
|
return Math.ceil(dist) <= factionBlockRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean IsPlayerInBounds(PlayerEntity player, BlockPos pos) {
|
||||||
|
Boolean isNearBlock = false;
|
||||||
|
String playerFaction = FactionManager.GetInstance().GetFactionOfPlayer(player.getUuidAsString());
|
||||||
|
|
||||||
|
return playerFaction.equals(faction) && DistanceToCenterSphere(player.getX(), player.getY(), player.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call when the block attached to this entity is broken so we can send out our last messages to reset players correctly before perishing
|
||||||
|
public void ResetBlock() {
|
||||||
|
System.out.println("Reset block called. Is world null? " + (world == null ? "YES" : "NO"));
|
||||||
|
if (world != null) {
|
||||||
|
for (PlayerEntity player : world.getPlayers()) {
|
||||||
|
Boolean isPlayerInFactionRadius = IsPlayerInBounds(player, pos);
|
||||||
|
if (isPlayerInFactionRadius) {
|
||||||
|
ActionResult result = PlayerExitedBaseCallback.EVENT.invoker().interact(player, world, factionPower, factionTier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("Error, world is null and FactionBlockEntity cannot reset players!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: There has GOT to be a better way of validating the inventory than this... but it's okay for now! *cries*
|
||||||
|
public void ValidateInventory() {
|
||||||
|
// Slots 1, 3, 5 are ATTACK/PASSIVE slots
|
||||||
|
// Slots 2, 4, 6 are DEFENSE/PASSIVE slots
|
||||||
|
// Slot 7 is the special slot reserved EXCLUSIVELY for LEGENDARY Tier only! Legendary CANNOT go in other slots!
|
||||||
|
for (ItemStack item : inventory) {
|
||||||
|
System.out.println("Item name: " + item.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tick method is called 20 times a second
|
||||||
|
public void tick(World world, BlockPos pos, BlockState state) {
|
||||||
|
if (world.isClient() || faction == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.world = world;
|
||||||
|
//TODO: The below values can ABSOLUTELY be moved to a one-time call-out when the block is created & when a player
|
||||||
|
// leaves or joins a faction with a simple callback subscriber. Leaving because not doing now, BUT REFACTOR
|
||||||
|
factionPlayers = FactionManager.GetInstance().GetFactionPlayers(faction);
|
||||||
|
factionPower = FactionManager.GetInstance().GetFactionPower(faction);
|
||||||
|
factionTier = FactionManager.GetInstance().GetFactionTier(faction);
|
||||||
|
|
||||||
|
for (PlayerEntity player : world.getPlayers()) {
|
||||||
|
Boolean isPlayerInFactionRadius = IsPlayerInBounds(player, pos);
|
||||||
|
if (isPlayerInFactionRadius) {
|
||||||
|
// Run individual faction modules for players here
|
||||||
|
// First time entry callback check
|
||||||
|
if (!playersInRadius.contains(player.getUuidAsString())) {
|
||||||
|
playersInRadius.add(player.getUuidAsString());
|
||||||
|
ActionResult result = PlayerEnteredBaseCallback.EVENT.invoker().interact(player, world, factionPower, factionTier);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke the flight attribute on this player
|
||||||
|
if (hasBuildFlight) {
|
||||||
|
AttributeMgr.ApplyAttribute(player.getUuidAsString(), "faction_flight");
|
||||||
|
ActionResult result = PlayerInBaseCallback.EVENT.invoker().interact(player, world, factionPower, factionTier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSuperBeacon) {
|
||||||
|
AttributeMgr.ApplyAttribute(player.getUuidAsString(), "faction_beacon");
|
||||||
|
}
|
||||||
|
} else if (!isPlayerInFactionRadius && playersInRadius.contains(player.getUuidAsString())) {
|
||||||
|
playersInRadius.remove(player.getUuidAsString());
|
||||||
|
ActionResult result = PlayerExitedBaseCallback.EVENT.invoker().interact(player, world, factionPower, factionTier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
// package jesse.keeblarcraft.CustomBlocks.BlockEntities;
|
||||||
|
|
||||||
|
// import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
// import jesse.keeblarcraft.CustomBlocks.BlockManager;
|
||||||
|
// import jesse.keeblarcraft.world.ImplementedInventory;
|
||||||
|
|
||||||
|
// import net.minecraft.block.BlockState;
|
||||||
|
// import net.minecraft.block.entity.BlockEntity;
|
||||||
|
// import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
// import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
// import net.minecraft.inventory.Inventories;
|
||||||
|
// import net.minecraft.item.ItemStack;
|
||||||
|
// import net.minecraft.nbt.NbtCompound;
|
||||||
|
// import net.minecraft.registry.RegistryWrapper;
|
||||||
|
// import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||||
|
// import net.minecraft.screen.PropertyDelegate; // for syncing client + server
|
||||||
|
// import net.minecraft.screen.ScreenHandler;
|
||||||
|
// import net.minecraft.text.Text;
|
||||||
|
// import net.minecraft.util.collection.DefaultedList;
|
||||||
|
// import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
// public class MagicChestBlockEntity extends BlockEntity implements NamedScreenHandlerFactory, ImplementedInventory {
|
||||||
|
// private final DefaultedList<ItemStack> inventory = DefaultedList.ofSize(256, ItemStack.EMPTY);
|
||||||
|
|
||||||
|
// protected final PropertyDelegate propertyDelegate;
|
||||||
|
// private int progress = 0;
|
||||||
|
// private int maxProgress = 72;
|
||||||
|
|
||||||
|
// public MagicChestBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
// super(Keeblarcraft.MAGIC_CHEST_BLOCK_ENTITY, pos, state);
|
||||||
|
// this.propertyDelegate = new PropertyDelegate() {
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public int get(int index) {
|
||||||
|
// return switch(index) {
|
||||||
|
// case 0 -> MagicChestBlockEntity.this.progress;
|
||||||
|
// case 1 -> MagicChestBlockEntity.this.maxProgress;
|
||||||
|
// default -> 0;
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public void set(int index, int value) {
|
||||||
|
// switch (index) {
|
||||||
|
// case 0 -> MagicChestBlockEntity.this.progress = value;
|
||||||
|
// case 1 -> MagicChestBlockEntity.this.maxProgress = value;
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // MUST be size of how many integers we are synchronizing
|
||||||
|
// @Override
|
||||||
|
// public int size() {
|
||||||
|
// return 2;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) {
|
||||||
|
// // Screen handler will sync the inventory
|
||||||
|
// return new MagicChestScreenHandler(syncId, playerInventory, this);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public DefaultedList<ItemStack> getItems() {
|
||||||
|
// return inventory;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public Text getDisplayName() {
|
||||||
|
// return Text.translatable(getCachedState().getBlock().getTranslationKey());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public void readNbt(NbtCompound nbt) {
|
||||||
|
// super.readNbt(nbt);
|
||||||
|
// Inventories.readNbt(nbt, this.inventory);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public void writeNbt(NbtCompound nbt) {
|
||||||
|
// super.writeNbt(nbt);
|
||||||
|
// Inventories.writeNbt(nbt, this.inventory);
|
||||||
|
// }
|
||||||
|
// }
|
@ -1,7 +1,7 @@
|
|||||||
package jesse.keeblarcraft.CustomBlocks;
|
package jesse.keeblarcraft.CustomBlocks;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.CustomBlocks.Blocks.FactionBaseBlock;
|
||||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||||
import net.minecraft.block.AbstractBlock;
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.ExperienceDroppingBlock;
|
import net.minecraft.block.ExperienceDroppingBlock;
|
||||||
@ -19,6 +19,7 @@ public class BlockList {
|
|||||||
public static void RegisterBlocks() {
|
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_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_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)));
|
BlockManager.RegisterBlock("example_statue", new Block(FabricBlockSettings.copyOf(Blocks.BELL).nonOpaque()));
|
||||||
|
BlockManager.RegisterBlock("faction_base_block", new FactionBaseBlock(FabricBlockSettings.copyOf(Blocks.COBBLESTONE).requiresTool().nonOpaque()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,143 @@
|
|||||||
|
package jesse.keeblarcraft.CustomBlocks.Blocks;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatFormatting;
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatMsg;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionConfig;
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Position3d;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.CustomBlocks.BlockEntities.BlockEntityRegistration;
|
||||||
|
import jesse.keeblarcraft.CustomBlocks.BlockEntities.FactionBlockEntity;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionManager;
|
||||||
|
import net.minecraft.block.*;
|
||||||
|
import net.minecraft.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.block.entity.BlockEntityTicker;
|
||||||
|
import net.minecraft.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.ItemScatterer;
|
||||||
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class FactionBaseBlock extends BlockWithEntity implements BlockEntityProvider {
|
||||||
|
// public static final VoxelShape SHAPE = Block.createCuboidShape(0, 0, 0, 16, 12, 16);
|
||||||
|
private String faction; // Faction attached to this block
|
||||||
|
|
||||||
|
public FactionBaseBlock(Settings settings) {
|
||||||
|
super(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// protected VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||||
|
// return SHAPE;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockRenderType getRenderType(BlockState state) {
|
||||||
|
return BlockRenderType.MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {
|
||||||
|
if (world.isClient()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placer != null && placer.isPlayer()) {
|
||||||
|
// We need to run faction checks here and make sure this player owns a faction otherwise they are NOT allowed to place it!
|
||||||
|
ServerPlayerEntity player = (ServerPlayerEntity) placer;
|
||||||
|
String fac = FactionManager.GetInstance().GetFactionOfPlayer(player.getUuidAsString());
|
||||||
|
|
||||||
|
// We need to verify the faction does not already have a block placed in the world; and make sure the placer
|
||||||
|
// is the owner of the faction.
|
||||||
|
Boolean canPlaceFactionBlock = FactionManager.GetInstance().CanPlaceFactionBlock(fac);
|
||||||
|
System.out.println("hasFacBlock: " + canPlaceFactionBlock);
|
||||||
|
FactionConfig.VALID_FACTION_ROLES role = FactionManager.GetInstance().GetPlayerRole(fac, placer.getUuidAsString());
|
||||||
|
System.out.println("Can place block?: " + canPlaceFactionBlock);
|
||||||
|
System.out.println("Role: " + role.name());
|
||||||
|
|
||||||
|
if (canPlaceFactionBlock && role == FactionConfig.VALID_FACTION_ROLES.OWNER) {
|
||||||
|
FactionBlockEntity bEntity = (FactionBlockEntity) world.getBlockEntity(pos);
|
||||||
|
// Update block entity - this is the "ultimate success" portion
|
||||||
|
if (bEntity != null) {
|
||||||
|
bEntity.SetFaction(fac);
|
||||||
|
// Enable chunk loading
|
||||||
|
world.getChunkManager().setChunkForced(world.getChunk(pos).getPos(), true);
|
||||||
|
faction = fac;
|
||||||
|
FactionManager.GetInstance().SetFactionBlock(faction, new Position3d(pos.getX(), pos.getY(), pos.getZ()));
|
||||||
|
player.sendMessage(Text.of(ChatMsg.ColorMsg("This block now begins to the " + fac + " faction!", ChatFormatting.COLOR_CODE.GOLD)));
|
||||||
|
}
|
||||||
|
} else if (canPlaceFactionBlock) {
|
||||||
|
player.sendMessage(Text.of(ChatMsg.ColorMsg("You cannot place more than one faction block per faction!", ChatFormatting.COLOR_CODE.RED)));
|
||||||
|
world.breakBlock(pos, true);
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of(ChatMsg.ColorMsg("You do not appear to be in a faction or are not the leader of this faction. You cannot place this block!", ChatFormatting.COLOR_CODE.RED)));
|
||||||
|
world.breakBlock(pos, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Only a player should be able to place the block in order to set faction appropriately. Destroy!
|
||||||
|
world.breakBlock(pos, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
return new FactionBlockEntity(pos, state, faction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If block is destroyed; drop inventory
|
||||||
|
@Override
|
||||||
|
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
|
||||||
|
if (state.getBlock() != newState.getBlock()) {
|
||||||
|
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||||
|
if (blockEntity instanceof FactionBlockEntity) {
|
||||||
|
ItemScatterer.spawn(world, pos, (FactionBlockEntity) blockEntity);
|
||||||
|
world.updateComparators(pos, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is pulled directly from #AbstractBlock$AbstractBlockState.class:onStateReplaced
|
||||||
|
// Catch if the block is being broken. Update our block entity to reset all
|
||||||
|
if (state.hasBlockEntity() && !state.isOf(newState.getBlock())) {
|
||||||
|
FactionBlockEntity bEntity = (FactionBlockEntity) world.getBlockEntity(pos);
|
||||||
|
if (bEntity != null) {
|
||||||
|
bEntity.ResetBlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable chunk loading
|
||||||
|
world.getChunkManager().setChunkForced(world.getChunk(pos).getPos(), false);
|
||||||
|
FactionManager.GetInstance().RemoveFactionBlock(faction, new Position3d(pos.getX(), pos.getY(), pos.getZ()));
|
||||||
|
super.onStateReplaced(state, world, pos, newState, moved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the inventory
|
||||||
|
// Calls ScreenHandler inside createMenu of entity class
|
||||||
|
@Override
|
||||||
|
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||||
|
// Server side handling is different from that of client side handling; we MUST check if we are on a server first because then we must
|
||||||
|
// request information about this block entity from the server
|
||||||
|
System.out.println("onUse of faction base block called");
|
||||||
|
if (!world.isClient()) {
|
||||||
|
NamedScreenHandlerFactory screenHandlerFactory = (FactionBlockEntity) world.getBlockEntity(pos);
|
||||||
|
|
||||||
|
if (screenHandlerFactory != null) {
|
||||||
|
player.openHandledScreen(screenHandlerFactory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ActionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
|
||||||
|
return validateTicker(type, BlockEntityRegistration.FACTION_BLOCK_ENTITY,
|
||||||
|
(world1, pos, state1, blockEntity) -> blockEntity.tick(world1, pos, state1));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
// package jesse.keeblarcraft.CustomBlocks.Blocks;
|
||||||
|
|
||||||
|
// import jesse.keeblarcraft.CustomBlocks.BlockEntities.MagicChestBlockEntity;
|
||||||
|
// import net.minecraft.block.BlockRenderType;
|
||||||
|
// import net.minecraft.block.BlockState;
|
||||||
|
// import net.minecraft.block.BlockWithEntity;
|
||||||
|
// import net.minecraft.block.entity.BlockEntity;
|
||||||
|
// import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
// import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||||
|
// import net.minecraft.util.ActionResult;
|
||||||
|
// import net.minecraft.util.Hand;
|
||||||
|
// import net.minecraft.util.hit.BlockHitResult;
|
||||||
|
// import net.minecraft.util.math.BlockPos;
|
||||||
|
// import net.minecraft.world.World;
|
||||||
|
|
||||||
|
// public class MagicChestBlock extends BlockWithEntity {
|
||||||
|
// public MagicChestBlock(Settings settings) {
|
||||||
|
// super(settings);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
// return new MagicChestBlockEntity(pos, state);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public BlockRenderType getRenderType(BlockState state) {
|
||||||
|
// return BlockRenderType.MODEL;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||||
|
// if (!world.isClient) {
|
||||||
|
// NamedScreenHandlerFactory screenHandlerFactory = ((MagicChestBlockEntity) world.getBlockEntity(pos));
|
||||||
|
|
||||||
|
// if (screenHandlerFactory != null) {
|
||||||
|
// player.openHandledScreen(screenHandlerFactory);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return ActionResult.SUCCESS;
|
||||||
|
// }
|
||||||
|
// }
|
@ -13,8 +13,13 @@ package jesse.keeblarcraft.CustomItems;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.CustomItems.Items.FactionBeaconItem;
|
||||||
|
import jesse.keeblarcraft.CustomItems.Items.FactionFlightItem;
|
||||||
|
import jesse.keeblarcraft.Entities.EntityRegistration;
|
||||||
import jesse.keeblarcraft.Keeblarcraft;
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.SpawnEggItem;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.registry.Registry;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
@ -34,7 +39,8 @@ public class ItemManager {
|
|||||||
/// 1. The name provided here must match these names:
|
/// 1. The name provided here must match these names:
|
||||||
/// * This items models/item name
|
/// * This items models/item name
|
||||||
/// * This items textures/item name
|
/// * This items textures/item name
|
||||||
/// 2 Name must be lowercase & no special characters besides '_'
|
/// 2. Name must be lowercase & no special characters besides '_'
|
||||||
|
/// 3. Do NOT provide the Mod ID inside the name part
|
||||||
///
|
///
|
||||||
/// @arg[in] item is the item to be added to the item list
|
/// @arg[in] item is the item to be added to the item list
|
||||||
///
|
///
|
||||||
@ -62,8 +68,8 @@ public class ItemManager {
|
|||||||
CustomItemGroups.RegisterGroups();
|
CustomItemGroups.RegisterGroups();
|
||||||
|
|
||||||
// The example item provides a demo of how you could make an item in your class
|
// The example item provides a demo of how you could make an item in your class
|
||||||
// Item exampleItem = new Item(new FabricItemSettings());
|
RegisterItem("faction_upgrade_flight", new FactionFlightItem(new FabricItemSettings().maxCount(1)));
|
||||||
// RegisterItem("metaljacket_helmet", exampleItem);
|
RegisterItem("faction_upgrade_beacon", new FactionBeaconItem(new FabricItemSettings().maxCount(1)));
|
||||||
|
RegisterItem("shop_keeper_spawn_egg", new SpawnEggItem(EntityRegistration.SHOP_KEEPER_ENTITY_TYPE, 0xc4c4c4, 0xadadad, new FabricItemSettings()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package jesse.keeblarcraft.CustomItems.Items;
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class FactionBeaconItem extends Item {
|
||||||
|
public FactionBeaconItem(Settings settings) {
|
||||||
|
super(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
|
||||||
|
if (world.isClient()) {
|
||||||
|
user.sendMessage(Text.of("This item can only be placed inside the faction home block!"));
|
||||||
|
}
|
||||||
|
return super.use(world, user, hand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDamageable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package jesse.keeblarcraft.CustomItems.Items;
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class FactionFlightItem extends Item {
|
||||||
|
public FactionFlightItem(Settings settings) {
|
||||||
|
super(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
|
||||||
|
if (world.isClient()) {
|
||||||
|
user.sendMessage(Text.of("This item can only be placed inside the faction home block!"));
|
||||||
|
}
|
||||||
|
return super.use(world, user, hand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDamageable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package jesse.keeblarcraft.Entities;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.SpawnGroup;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.registry.Registry;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class EntityRegistration {
|
||||||
|
public static final EntityType<ShopKeeper> SHOP_KEEPER_ENTITY_TYPE = Registry.register(
|
||||||
|
Registries.ENTITY_TYPE,
|
||||||
|
Identifier.of(Keeblarcraft.MOD_ID, "shop_keeper"),
|
||||||
|
EntityType.Builder.create(ShopKeeper::new, SpawnGroup.CREATURE).setDimensions(0.75f, 2.0f).build("cube")
|
||||||
|
);
|
||||||
|
|
||||||
|
public static void RegisterEntities() {
|
||||||
|
Keeblarcraft.LOGGER.info("Registering custom entities...");
|
||||||
|
FabricDefaultAttributeRegistry.register(SHOP_KEEPER_ENTITY_TYPE, ShopKeeper.createMobAttributes());
|
||||||
|
}
|
||||||
|
}
|
79
src/main/java/jesse/keeblarcraft/Entities/ShopKeeper.java
Normal file
79
src/main/java/jesse/keeblarcraft/Entities/ShopKeeper.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package jesse.keeblarcraft.Entities;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.GuiMgr.ShopKeeper.ShopKeeperHandler;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.passive.VillagerEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.screen.SimpleNamedScreenHandlerFactory;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.village.TradeOffer;
|
||||||
|
import net.minecraft.village.TradeOfferList;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
public class ShopKeeper extends VillagerEntity {
|
||||||
|
public ShopKeeper(EntityType<? extends VillagerEntity> entityType, World world) {
|
||||||
|
super(entityType, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionResult interactMob(PlayerEntity player, Hand hand) {
|
||||||
|
BeginTrades(player);
|
||||||
|
return ActionResult.success(this.getWorld().isClient());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginTrades(PlayerEntity player) {
|
||||||
|
super.setCustomer(player);
|
||||||
|
this.sendOffers(player, this.getDisplayName(), this.getVillagerData().getLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendOffers(PlayerEntity player, Text name, int levelProgress) {
|
||||||
|
OptionalInt optInt = player.openHandledScreen(
|
||||||
|
new SimpleNamedScreenHandlerFactory((syncId, playerInventory, playerx) ->
|
||||||
|
new ShopKeeperHandler(syncId, playerInventory, this), name)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (optInt.isPresent()) {
|
||||||
|
TradeOfferList offers = this.getOffers();
|
||||||
|
if (!offers.isEmpty()) {
|
||||||
|
player.sendTradeOffers(optInt.getAsInt(), offers, levelProgress, this.getExperience(), this.isLeveledMerchant(), this.canRefreshTrades());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shop Keepers do not breed!
|
||||||
|
@Override
|
||||||
|
public boolean canBreed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Text getDefaultName() {
|
||||||
|
return Text.of("Shop Keeper");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void afterUsing(TradeOffer offer) {
|
||||||
|
System.out.println("After using called");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the offer list upon opening handled screen if valid
|
||||||
|
@Override
|
||||||
|
public TradeOfferList getOffers() {
|
||||||
|
if (this.offers == null) {
|
||||||
|
this.offers = new TradeOfferList();
|
||||||
|
this.fillRecipes();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.offers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canSummonGolem(long time) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
package jesse.keeblarcraft.EventMgr;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
|
import jesse.keeblarcraft.world.dimension.ModDimensions;
|
||||||
|
import net.minecraft.nbt.NbtElement;
|
||||||
|
import net.minecraft.nbt.NbtList;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
|
||||||
|
public class DimensionLoadingEvent {
|
||||||
|
private static DimensionLoadingEvent static_inst;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetInstance
|
||||||
|
///
|
||||||
|
/// @brief Static instance getter for this class
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static DimensionLoadingEvent GetInstance() {
|
||||||
|
if (static_inst == null) {
|
||||||
|
static_inst = new DimensionLoadingEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper class to manage the single inventory cache of dimension loading
|
||||||
|
private static class InventoryWrapper {
|
||||||
|
public HashMap<String, NbtList> inventories = new HashMap<String, NbtList>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InventoryWrapper iw = new InventoryWrapper();
|
||||||
|
|
||||||
|
private static String CONFIG_LOCATION = "misc/dim_loading_cached_inventories/";
|
||||||
|
ConfigManager config = new ConfigManager();
|
||||||
|
|
||||||
|
public DimensionLoadingEvent() {
|
||||||
|
// read config
|
||||||
|
iw.inventories = config.ReadAllNbtListFromDirectory(CONFIG_LOCATION, NbtElement.COMPOUND_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn HandleWorldMove
|
||||||
|
///
|
||||||
|
/// @param[in] player is the player object
|
||||||
|
///
|
||||||
|
/// @param[in] origin is the FROM destination world
|
||||||
|
///
|
||||||
|
/// @param[in] destination is the TO destination world
|
||||||
|
///
|
||||||
|
/// @brief Callback handler for player world move events on server
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void HandleWorldMove(ServerPlayerEntity player, ServerWorld origin, ServerWorld destination) {
|
||||||
|
System.out.println("World move event called!");
|
||||||
|
|
||||||
|
// Player is ENTERING the custom dimension; strip their inventory!
|
||||||
|
if (destination.getDimensionEntry().matchesKey(ModDimensions.KEEBLAR_DIM_TYPE) && (!iw.inventories.containsKey(player.getUuidAsString()))) {
|
||||||
|
// Make sure player is in map. For now we only care about storing OVERWORLD inventory. We DO NOT care about
|
||||||
|
// the dimension inventory!
|
||||||
|
// if (!iw.inventories.containsKey(player.getUuidAsString())) {
|
||||||
|
// Copy the nbt into the list
|
||||||
|
NbtList inventoryNbt = new NbtList();
|
||||||
|
player.getInventory().writeNbt(inventoryNbt);
|
||||||
|
|
||||||
|
iw.inventories.put(player.getUuidAsString(), inventoryNbt);
|
||||||
|
player.getInventory().clear();
|
||||||
|
// }
|
||||||
|
// Player is LEAVING the custom dimension. Give them their stuff back
|
||||||
|
} else if (origin.getDimensionEntry().matchesKey(ModDimensions.KEEBLAR_DIM_TYPE) && iw.inventories.containsKey(player.getUuidAsString())) {
|
||||||
|
// if (iw.inventories.containsKey(player.getUuidAsString())) {
|
||||||
|
player.getInventory().readNbt(iw.inventories.get(player.getUuidAsString()));
|
||||||
|
iw.inventories.remove(player.getUuidAsString());
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn SaveInventories
|
||||||
|
///
|
||||||
|
/// @brief Flashes the configuration file on disk (call before server exit
|
||||||
|
/// to not lose memory!)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void SaveInventories() {
|
||||||
|
System.out.println("Call to save inventories. Flashing IW.Inventories with size " + iw.inventories.size());
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetInventories
|
||||||
|
///
|
||||||
|
/// @param Player uuid
|
||||||
|
///
|
||||||
|
/// @brief Gets a player inventory from the map. Calling this action also
|
||||||
|
/// removes the inventory from the stored map so be sure to use
|
||||||
|
/// it if you call it!
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public NbtList GetInventory(String uuid) {
|
||||||
|
NbtList nbt = iw.inventories.get(uuid);
|
||||||
|
iw.inventories.remove(uuid);
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn FlashConfig
|
||||||
|
///
|
||||||
|
/// @brief Flashes configuration file to disk
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void FlashConfig() {
|
||||||
|
try {
|
||||||
|
// config.WriteToJsonFile(CONFIG_LOCATION, iw);
|
||||||
|
// First, ensure list is size > 0
|
||||||
|
for (Entry<String, NbtList> list : iw.inventories.entrySet()) {
|
||||||
|
if (list.getValue().size() > 0) {
|
||||||
|
config.WriteNbtListToFile(CONFIG_LOCATION + list.getKey() + ".nbt", list.getKey(), list.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Could not flash dimension loading configuration file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
package jesse.keeblarcraft.EventMgr;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeTree;
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.GeneralConfig;
|
||||||
|
import jesse.keeblarcraft.Utils.DirectionalVec;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public class PlayerJoinListener {
|
||||||
|
private static PlayerJoinListener static_inst;
|
||||||
|
ConfigManager config = new ConfigManager();
|
||||||
|
String CACHED_PLAYER_LOGIN_CONFIG = "misc/cached_uuids.json";
|
||||||
|
|
||||||
|
private class CachedUUIDConfig {
|
||||||
|
HashMap<String, String> cached_uuids = new HashMap<String, String>();
|
||||||
|
}
|
||||||
|
CachedUUIDConfig cachedPlayerConfig;
|
||||||
|
|
||||||
|
// Get the static instance for this class
|
||||||
|
public static PlayerJoinListener GetInstance() {
|
||||||
|
if (static_inst == null) {
|
||||||
|
static_inst = new PlayerJoinListener();
|
||||||
|
}
|
||||||
|
return static_inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerJoinListener() {
|
||||||
|
Boolean existingFile = false;
|
||||||
|
cachedPlayerConfig = new CachedUUIDConfig();
|
||||||
|
|
||||||
|
try {
|
||||||
|
cachedPlayerConfig = config.GetJsonObjectFromFile(CACHED_PLAYER_LOGIN_CONFIG, CachedUUIDConfig.class);
|
||||||
|
existingFile = cachedPlayerConfig != null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
// intentionally empty
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existingFile) {
|
||||||
|
try {
|
||||||
|
cachedPlayerConfig = new CachedUUIDConfig();
|
||||||
|
config.CreateFile(CACHED_PLAYER_LOGIN_CONFIG);
|
||||||
|
FlashCachedConfig();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Failed to parse or create cached uuid file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn HandleServerJoinEvent
|
||||||
|
///
|
||||||
|
/// @param[in] handler is the network handler
|
||||||
|
///
|
||||||
|
/// @param[in] sender is the packet sender
|
||||||
|
///
|
||||||
|
/// @param[in] server is the MinecraftServer instance
|
||||||
|
///
|
||||||
|
/// @brief Callback function for player join event in minecraft server
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void HandleServerJoinEvent(ServerPlayNetworkHandler handler, PacketSender sender, MinecraftServer server) {
|
||||||
|
var player = handler.player;
|
||||||
|
|
||||||
|
// Handle skill tree map instance
|
||||||
|
if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == false) {
|
||||||
|
AttributeMgr.activeTrees.put(player.getUuidAsString(), new AttributeTree(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle first time joining events (world spawn teleport, MOTD, etc)
|
||||||
|
System.out.println("Running first time login stuff");
|
||||||
|
IsFirstTimeLogin(player, server);
|
||||||
|
CachePlayersUuid(player.getUuidAsString(), player.getEntityName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IsFirstTimeLogin
|
||||||
|
///
|
||||||
|
/// @param[in] player is the player who is joining
|
||||||
|
///
|
||||||
|
/// @param[in] server is the MinecraftServer instance
|
||||||
|
///
|
||||||
|
/// @brief Check to see if player is first time log-in. If so, we teleport
|
||||||
|
/// them to spawn. This function may be expanded in future
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private void IsFirstTimeLogin(ServerPlayerEntity player, MinecraftServer server) {
|
||||||
|
// Send the MOTD + Spawn in global spawn
|
||||||
|
player.sendMessage(Text.of(GeneralConfig.GetInstance().GetMOTD()));
|
||||||
|
if (GeneralConfig.GetInstance().IsNewPlayer(player.getUuidAsString())) {
|
||||||
|
DirectionalVec coords = GeneralConfig.GetInstance().GetSpawnCoords();
|
||||||
|
if (coords != null) {
|
||||||
|
for (ServerWorld world : player.getServer().getWorlds()) {
|
||||||
|
if (world.getRegistryKey().toString().equals(coords.world.toString())) {
|
||||||
|
try {
|
||||||
|
player.teleport(world, coords.x, coords.y, coords.z, coords.yaw, coords.pitch);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String TryGetPlayerUuidByName(String name) {
|
||||||
|
String uuid = "";
|
||||||
|
if (cachedPlayerConfig != null && cachedPlayerConfig.cached_uuids.containsKey(name)) {
|
||||||
|
uuid = cachedPlayerConfig.cached_uuids.get(name);
|
||||||
|
}
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CachePlayersUuid(String uuid, String entityName) {
|
||||||
|
if (cachedPlayerConfig.cached_uuids.containsKey(entityName)) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
cachedPlayerConfig.cached_uuids.put(entityName, uuid);
|
||||||
|
FlashCachedConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FlashCachedConfig() {
|
||||||
|
try {
|
||||||
|
config.WriteToJsonFile(CACHED_PLAYER_LOGIN_CONFIG, cachedPlayerConfig);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Encountered exception in writing cached uuid file!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package jesse.keeblarcraft.FactionMgr.Callbacks;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
|
||||||
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public interface PlayerCommandFlightCallback {
|
||||||
|
Event<PlayerCommandFlightCallback> EVENT = EventFactory.createArrayBacked(PlayerCommandFlightCallback.class,
|
||||||
|
(listeners) -> (player, world, power, factionTier) -> {
|
||||||
|
for (PlayerCommandFlightCallback listener : listeners) {
|
||||||
|
ActionResult result = listener.interact(player, world, power, factionTier);
|
||||||
|
|
||||||
|
if (result != ActionResult.PASS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
|
||||||
|
ActionResult interact(PlayerEntity player, World world, Integer factionPower, FactionTierEnum factionTier);
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package jesse.keeblarcraft.FactionMgr.Callbacks;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
|
||||||
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public interface PlayerEnteredBaseCallback {
|
||||||
|
Event<PlayerEnteredBaseCallback> EVENT = EventFactory.createArrayBacked(PlayerEnteredBaseCallback.class,
|
||||||
|
(listeners) -> (player, world, power, factionTier) -> {
|
||||||
|
for (PlayerEnteredBaseCallback listener : listeners) {
|
||||||
|
ActionResult result = listener.interact(player, world, power, factionTier);
|
||||||
|
|
||||||
|
if (result != ActionResult.PASS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
|
||||||
|
ActionResult interact(PlayerEntity player, World world, Integer factionPower, FactionTierEnum factionTier);
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package jesse.keeblarcraft.FactionMgr.Callbacks;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
|
||||||
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public interface PlayerExitedBaseCallback {
|
||||||
|
Event<PlayerExitedBaseCallback> EVENT = EventFactory.createArrayBacked(PlayerExitedBaseCallback.class,
|
||||||
|
(listeners) -> (player, world, power, factionTier) -> {
|
||||||
|
for (PlayerExitedBaseCallback listener : listeners) {
|
||||||
|
ActionResult result = listener.interact(player, world, power, factionTier);
|
||||||
|
|
||||||
|
if (result != ActionResult.PASS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
|
||||||
|
ActionResult interact(PlayerEntity player, World world, Integer factionPower, FactionTierEnum factionTier);
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package jesse.keeblarcraft.FactionMgr.Callbacks;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
|
||||||
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public interface PlayerInBaseCallback {
|
||||||
|
Event<PlayerInBaseCallback> EVENT = EventFactory.createArrayBacked(PlayerInBaseCallback.class,
|
||||||
|
(listeners) -> (player, world, power, factionTier) -> {
|
||||||
|
for (PlayerInBaseCallback listener : listeners) {
|
||||||
|
ActionResult result = listener.interact(player, world, power, factionTier);
|
||||||
|
|
||||||
|
if (result != ActionResult.PASS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionResult.PASS;
|
||||||
|
});
|
||||||
|
|
||||||
|
ActionResult interact(PlayerEntity player, World world, Integer factionPower, FactionTierEnum factionTier);
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package jesse.keeblarcraft.FactionMgr;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static java.util.Map.entry;
|
||||||
|
|
||||||
|
// This class is going to keep track of everything related to items that the faction block is allowed to accept and
|
||||||
|
// information regarding those items.
|
||||||
|
public class FactionBlockItems {
|
||||||
|
public static enum ITEM_TIER {
|
||||||
|
COMMON,
|
||||||
|
UNCOMMON,
|
||||||
|
RARE,
|
||||||
|
VERY_RARE,
|
||||||
|
LEGENDARY
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Need to add the Item information for these down below; but I haven't made them yet! The string should
|
||||||
|
// make it obvious what needs to go here though.
|
||||||
|
public static Map<String, ITEM_TIER> FACTION_UPGRADES = Map.ofEntries(
|
||||||
|
entry("keeblarcraft:faction_flight", ITEM_TIER.UNCOMMON),
|
||||||
|
entry("keeblarcraft:faction_beacon", ITEM_TIER.RARE)
|
||||||
|
);
|
||||||
|
}
|
607
src/main/java/jesse/keeblarcraft/FactionMgr/FactionConfig.java
Normal file
607
src/main/java/jesse/keeblarcraft/FactionMgr/FactionConfig.java
Normal file
@ -0,0 +1,607 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* FactionConfig
|
||||||
|
*
|
||||||
|
* This class is the configuration file for factions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jesse.keeblarcraft.FactionMgr;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Position3d;
|
||||||
|
|
||||||
|
import static java.util.Map.entry;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
// This class is written to a config file typically and represents
|
||||||
|
// all the details surrounding a faction
|
||||||
|
public class FactionConfig {
|
||||||
|
// Key = Faction identifier
|
||||||
|
// Val = Faction object
|
||||||
|
HashMap<String, WriteableFaction> allFactions = new HashMap<String, WriteableFaction>();
|
||||||
|
|
||||||
|
// Enum may be extended in future
|
||||||
|
public static enum VALID_FACTION_ROLES {
|
||||||
|
OWNER,
|
||||||
|
COOWNER,
|
||||||
|
MANAGEMENT,
|
||||||
|
EMPLOYEE,
|
||||||
|
INVALID
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<VALID_FACTION_ROLES, Integer> ROLE_LEVELS = Map.ofEntries
|
||||||
|
(
|
||||||
|
entry (VALID_FACTION_ROLES.EMPLOYEE, 0),
|
||||||
|
entry (VALID_FACTION_ROLES.MANAGEMENT, 1),
|
||||||
|
entry (VALID_FACTION_ROLES.COOWNER, 2),
|
||||||
|
entry (VALID_FACTION_ROLES.OWNER, 3)
|
||||||
|
);
|
||||||
|
|
||||||
|
// The below map is 100x easier to just have statically typed here and maintained manually than expensively getting value by key (I am also lazy)
|
||||||
|
private static Map<Integer, VALID_FACTION_ROLES> ROLES_BY_LEVEL = Map.ofEntries
|
||||||
|
(
|
||||||
|
entry (0, VALID_FACTION_ROLES.EMPLOYEE),
|
||||||
|
entry (1, VALID_FACTION_ROLES.MANAGEMENT),
|
||||||
|
entry (2, VALID_FACTION_ROLES.COOWNER),
|
||||||
|
entry (3, VALID_FACTION_ROLES.OWNER)
|
||||||
|
);
|
||||||
|
|
||||||
|
// This is the actual faction configuration object that is written to a json file
|
||||||
|
public static class WriteableFaction {
|
||||||
|
// Key = Player UUID
|
||||||
|
// Val = Faction role of player
|
||||||
|
HashMap<String, VALID_FACTION_ROLES> factionPlayerList = new HashMap<String, VALID_FACTION_ROLES>();
|
||||||
|
// Key = Player DISPLAY name
|
||||||
|
// Val = Faction role of player
|
||||||
|
HashMap<String, VALID_FACTION_ROLES> DISPLAY_ONLY_LIST = new HashMap<String, VALID_FACTION_ROLES>();
|
||||||
|
|
||||||
|
// List contains UUID of players who are openly invited to this faction
|
||||||
|
// TODO: Refactor to map so players can un-invite by name not UUID...
|
||||||
|
List<String> openInvites = new ArrayList<String>();
|
||||||
|
|
||||||
|
Position3d factionBlockLocation; // May be null until faction places it; but only one can be placed!
|
||||||
|
int numFactionBlocks = 0;
|
||||||
|
|
||||||
|
Integer factionBankBalance;
|
||||||
|
Integer factionPower;
|
||||||
|
String factionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn CreateFaction
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] creatorUuid is the caller of the command's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] creatorDisplayName is the caller's display name
|
||||||
|
///
|
||||||
|
/// @brief Creates a faction on the server
|
||||||
|
///
|
||||||
|
/// @return True if a faction can be created, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean CreateFaction(String factionName, String creatorUuid, String creatorDisplayName) {
|
||||||
|
Boolean success = false;
|
||||||
|
if (!IsValid(factionName)) {
|
||||||
|
WriteableFaction newFaction = new WriteableFaction();
|
||||||
|
newFaction.factionPlayerList.put(creatorUuid, VALID_FACTION_ROLES.OWNER);
|
||||||
|
newFaction.DISPLAY_ONLY_LIST.put(creatorDisplayName, VALID_FACTION_ROLES.OWNER);
|
||||||
|
newFaction.factionBankBalance = 0;
|
||||||
|
newFaction.factionPower = 1;
|
||||||
|
allFactions.put(factionName, newFaction);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFactionBlock(String factionName, Position3d blockPos) {
|
||||||
|
if (IsValid(factionName) && blockPos != null) {
|
||||||
|
allFactions.get(factionName).numFactionBlocks++;
|
||||||
|
allFactions.get(factionName).factionBlockLocation = blockPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveFactionBlock(String factionName) {
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
allFactions.get(factionName).factionBlockLocation = null;
|
||||||
|
allFactions.get(factionName).numFactionBlocks--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Position3d GetFactionBlock(String factionName) {
|
||||||
|
Position3d blockLoc = null;
|
||||||
|
if (IsValid(factionName)){
|
||||||
|
blockLoc = allFactions.get(factionName).factionBlockLocation;
|
||||||
|
}
|
||||||
|
return blockLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will return amount of faction blocks in a faction, where any number less than 0 should be treated
|
||||||
|
// as an invalid case where the faction may have not existed when this function was called.
|
||||||
|
public Integer GetNumberOfFactionBlocks(String factionName) {
|
||||||
|
int amount = -1;
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
amount = allFactions.get(factionName).numFactionBlocks;
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is assumed that the person calling this function has verified that the person
|
||||||
|
// can in fact set faction power. This is generally just an admin command
|
||||||
|
public Boolean SetPower(String factionName, Integer amount) {
|
||||||
|
Boolean success = false;
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
allFactions.get(factionName).factionPower = amount;
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The user should verify the faction exists prior to calling this. 0 is default
|
||||||
|
// return if faction does not exist (or the faction actually has a balance of 0)
|
||||||
|
public Integer GetPower(String factionName) {
|
||||||
|
Integer amount = 0;
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
amount = allFactions.get(factionName).factionPower;
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer GetBankBalance(String factionName) {
|
||||||
|
Integer amount = 0;
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
amount = allFactions.get(factionName).factionBankBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// You should probably verify the player is in the faction before calling this so the object is not empty
|
||||||
|
public HashMap<String, VALID_FACTION_ROLES> GetMemberNames(String factionName) {
|
||||||
|
HashMap<String, VALID_FACTION_ROLES> members = new HashMap<String, VALID_FACTION_ROLES>();
|
||||||
|
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
members = allFactions.get(factionName).DISPLAY_ONLY_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets faction members in a pair return; KEY = UUID values. PAIR = Ranks of each UUID
|
||||||
|
// Alternatively you could just call @see GetMemberNames(String) to get member names
|
||||||
|
// and their ranks.
|
||||||
|
public HashMap<String, VALID_FACTION_ROLES> GetFactionPlayers(String factionName) {
|
||||||
|
HashMap<String, VALID_FACTION_ROLES> players = null;
|
||||||
|
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
players = allFactions.get(factionName).factionPlayerList;
|
||||||
|
}
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VALID_FACTION_ROLES GetPlayerRole(String factionName, String playerUuid) {
|
||||||
|
VALID_FACTION_ROLES role = VALID_FACTION_ROLES.INVALID;
|
||||||
|
// Check to make sure faction exists & player is in faction
|
||||||
|
if (IsValid(factionName) && allFactions.get(factionName).factionPlayerList.containsKey(playerUuid)) {
|
||||||
|
role = allFactions.get(factionName).factionPlayerList.get(playerUuid);
|
||||||
|
}
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn DeleteFaction
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] creatorUuid is the caller of the command's UUID
|
||||||
|
///
|
||||||
|
/// @brief Deletes a faction on the server
|
||||||
|
///
|
||||||
|
/// @return True if a faction can be deleted, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean DeleteFaction(String factionName, String callerUuid) {
|
||||||
|
Boolean success = false;
|
||||||
|
// faction must exist
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
// faction must contain player
|
||||||
|
if (allFactions.get(factionName).factionPlayerList.containsKey(callerUuid)) {
|
||||||
|
// player must be owner of faction
|
||||||
|
if (allFactions.get(factionName).factionPlayerList.get(callerUuid) == VALID_FACTION_ROLES.OWNER) {
|
||||||
|
//TODO: BankManager will connect with this in future and the money of the faction must go somewhere!
|
||||||
|
allFactions.remove(factionName);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn CanInvite
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] creatorUuid is the caller of the command's UUID
|
||||||
|
///
|
||||||
|
/// @brief Determines if the player is capable of inviting another player
|
||||||
|
/// to the faction
|
||||||
|
///
|
||||||
|
/// @return True if player can invite another player, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private Boolean CanInvite(String factionName, String callerUuid) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
if (allFactions.get(factionName).factionPlayerList.containsKey(callerUuid)) {
|
||||||
|
VALID_FACTION_ROLES callerRole = allFactions.get(factionName).factionPlayerList.get(callerUuid);
|
||||||
|
if (callerRole == VALID_FACTION_ROLES.MANAGEMENT || callerRole == VALID_FACTION_ROLES.COOWNER || callerRole == VALID_FACTION_ROLES.OWNER) {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IsOnInviteList
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] playerUuid is the caller of the command's UUID
|
||||||
|
///
|
||||||
|
/// @brief Checks to see if a player has been invited to a faction
|
||||||
|
///
|
||||||
|
/// @return True if player is on invite list, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private Boolean IsOnInviteList(String factionName, String playerUuid) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
if (allFactions.get(factionName).openInvites.contains(playerUuid)) {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AddToFaction
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] playerUuid is the caller of the command's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] playerDisplayName is the caller's display name
|
||||||
|
///
|
||||||
|
/// @brief Adds a player to a faction
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private void AddToFaction(String factionName, String playerUuid, String playerDisplayName) {
|
||||||
|
if (allFactions.containsKey(factionName)) {
|
||||||
|
allFactions.get(factionName).factionPlayerList.put(playerUuid, VALID_FACTION_ROLES.EMPLOYEE);
|
||||||
|
allFactions.get(factionName).DISPLAY_ONLY_LIST.put(playerDisplayName, VALID_FACTION_ROLES.EMPLOYEE);
|
||||||
|
allFactions.get(factionName).openInvites.remove(playerUuid); // Remove them from the invite list if they joined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn InvitePlayerToFaction
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] callerUuid is the player inviting another player's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] invitedUuid is the player being invited's UUID
|
||||||
|
///
|
||||||
|
/// @brief Invites a player to a faction
|
||||||
|
///
|
||||||
|
/// @return True if player successfully can invite another player
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean InvitePlayerToFaction(String factionName, String callerUuid, String invitedUuid) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (CanInvite(factionName, callerUuid)) {
|
||||||
|
allFactions.get(factionName).openInvites.add(invitedUuid);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn JoinFaction
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] playerUuid is the player inviting another player's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] playerDisplayName is the player being invited's UUID
|
||||||
|
///
|
||||||
|
/// @brief Function to determine if a player can join a faction
|
||||||
|
///
|
||||||
|
/// @return True if they join, false if they cannot
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean JoinFaction(String factionName, String playerUuid, String playerDisplayName) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (IsOnInviteList(factionName, playerUuid) ) {
|
||||||
|
AddToFaction(factionName, playerUuid, playerDisplayName);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn LeaveFaction
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] playerUuid is the player inviting another player's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] playerName is the player being invited's UUID
|
||||||
|
///
|
||||||
|
/// @brief Function to let player leave a faction
|
||||||
|
///
|
||||||
|
/// @return True if they leave, false if they did not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean LeaveFaction(String factionName, String playerUuid, String playerName) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
allFactions.get(factionName).factionPlayerList.remove(playerUuid);
|
||||||
|
allFactions.get(factionName).DISPLAY_ONLY_LIST.remove(playerName);
|
||||||
|
|
||||||
|
// TODO: In future add ability if owner leave then promote next person
|
||||||
|
// Delete faction if all the players are gone
|
||||||
|
if (allFactions.get(factionName).factionPlayerList.size() == 0) {
|
||||||
|
allFactions.remove(factionName);
|
||||||
|
}
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn HasPlayer
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] playerUuid is the player inviting another player's UUID
|
||||||
|
///
|
||||||
|
/// @brief Determines if a faction has a specific player by UUID
|
||||||
|
///
|
||||||
|
/// @return True if they have the player, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private Boolean HasPlayer(String factionName, String playerUuid) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (IsValid(factionName)) {
|
||||||
|
success = allFactions.get(factionName).factionPlayerList.containsKey(playerUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn IsValid
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @brief Determines if a faction exists
|
||||||
|
///
|
||||||
|
/// @return True if a faction exists with the specified name, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean IsValid(String factionName) {
|
||||||
|
return allFactions.containsKey(factionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn FindFactionOfPlayer
|
||||||
|
///
|
||||||
|
/// @param[in] playerUuid is the uuid of the player to find
|
||||||
|
///
|
||||||
|
/// @brief Determine the faction of a specified player
|
||||||
|
///
|
||||||
|
/// @return Returns the faction name of the player if the player is in
|
||||||
|
/// any faction. If the player is not found in any faction, an
|
||||||
|
/// empty string is returned
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public String FindFactionOfPlayer(String playerUuid) {
|
||||||
|
String faction = "";
|
||||||
|
|
||||||
|
for (Entry<String, WriteableFaction> entry : allFactions.entrySet()) {
|
||||||
|
if (entry.getValue().factionPlayerList.containsKey(playerUuid)) {
|
||||||
|
faction = entry.getKey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return faction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn PromotePlayer
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] callerUuid is the caller of the command's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] promoteeUuid is the player to be promoted's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] promoteeDisplayName is the player ot be promoted's display name
|
||||||
|
///
|
||||||
|
/// @brief Attempts to promote a player in a faction. Whether or not a
|
||||||
|
/// player is promoted is determined by their level in the faction
|
||||||
|
/// and the promoter's level in the faction. Factors that can affect
|
||||||
|
/// this are:
|
||||||
|
/// 1. Both the caller and promotee must exist inside
|
||||||
|
/// the same faction
|
||||||
|
/// 2. The promoter must be a higher rank than the promotee
|
||||||
|
/// 3. The promotee's post-promotion rank still must be below
|
||||||
|
/// the promoter's rank
|
||||||
|
///
|
||||||
|
/// @return True if the player was successfully promoted, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean PromotePlayer(String factionName, String callerUuid, String promoteeUuid, String promoteeDisplayName) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (CanInvite(factionName, callerUuid) && HasPlayer(factionName, promoteeUuid)) {
|
||||||
|
VALID_FACTION_ROLES callerRole = allFactions.get(factionName).factionPlayerList.get(callerUuid);
|
||||||
|
VALID_FACTION_ROLES promoteeRole = allFactions.get(factionName).factionPlayerList.get(promoteeUuid);
|
||||||
|
Integer callerRoleLevel = ROLE_LEVELS.get(callerRole);
|
||||||
|
Integer promoteeRoleLevel = ROLE_LEVELS.get(promoteeRole);
|
||||||
|
|
||||||
|
// Factions is setup so that anyone can promote anybody UNDERNEATH them. However, you CANNOT promote a player to your level!
|
||||||
|
if (callerRoleLevel > promoteeRoleLevel + 1) {
|
||||||
|
// Get the new employee role
|
||||||
|
promoteeRole = ROLES_BY_LEVEL.get(promoteeRoleLevel + 1);
|
||||||
|
|
||||||
|
// Update role in faction
|
||||||
|
allFactions.get(factionName).factionPlayerList.put(promoteeUuid, promoteeRole);
|
||||||
|
allFactions.get(factionName).DISPLAY_ONLY_LIST.put(promoteeDisplayName, promoteeRole);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn CanKickPlayer
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] callerUuid is the caller of the command's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] kickeeUuid is the player to be kickee's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] kickeeDisplayName is the player ot be kickeeDisplayName's
|
||||||
|
/// display name
|
||||||
|
///
|
||||||
|
/// @brief Determines whether or not a player can be kicked. The caller
|
||||||
|
/// must be a higher rank to kick a player (and they both must
|
||||||
|
/// exist inside the faction)
|
||||||
|
///
|
||||||
|
/// @return True if the player was successfully kicked, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean CanKickPlayer(String factionName, String callerUuid, String kickeeUuid, String kickeeDisplayName) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (IsValid(factionName) && HasPlayer(factionName, kickeeUuid)) {
|
||||||
|
VALID_FACTION_ROLES callerRole = allFactions.get(factionName).factionPlayerList.get(callerUuid);
|
||||||
|
VALID_FACTION_ROLES kickeeRole = allFactions.get(factionName).factionPlayerList.get(kickeeUuid);
|
||||||
|
Integer callerRoleLevel = ROLE_LEVELS.get(callerRole);
|
||||||
|
Integer kickeeRoleLevel = ROLE_LEVELS.get(kickeeRole);
|
||||||
|
|
||||||
|
if (callerRoleLevel > kickeeRoleLevel) {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn KickPlayer
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] callerUuid is the caller of the command's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] kickeeUuid is the player to be kickee's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] kickeeDisplayName is the player ot be kickeeDisplayName's
|
||||||
|
/// display name
|
||||||
|
///
|
||||||
|
/// @brief Kicks a player from a faction
|
||||||
|
///
|
||||||
|
/// @return True if the player was successfully kicked, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private Boolean KickPlayer(String factionName, String callerUuid, String kickeeUuid, String kickeeDisplayName) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (CanKickPlayer(factionName, callerUuid, kickeeUuid, kickeeDisplayName)) {
|
||||||
|
allFactions.get(factionName).factionPlayerList.remove(kickeeUuid);
|
||||||
|
allFactions.get(factionName).DISPLAY_ONLY_LIST.remove(kickeeDisplayName);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn DemotePlayer
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the name of the faction
|
||||||
|
///
|
||||||
|
/// @param[in] callerUuid is the caller of the command's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] demoteeUuid is the player to be promoted's UUID
|
||||||
|
///
|
||||||
|
/// @param[in] demoteeDisplayName is the player ot be promoted's display name
|
||||||
|
///
|
||||||
|
/// @brief Attempts to demote a player in a faction. Whether or not a
|
||||||
|
/// player is demoted is determined by their level in the faction
|
||||||
|
/// and the demoter's level in the faction. Factors that can affect
|
||||||
|
/// this are:
|
||||||
|
/// 1. Both the caller and demotee must exist inside
|
||||||
|
/// the same faction
|
||||||
|
/// 2. The demoter must be a higher rank than the promotee
|
||||||
|
/// 3. Should there be no lower rank left to demote to, the
|
||||||
|
/// player is kicked from the faction
|
||||||
|
///
|
||||||
|
/// @return True if the player was successfully demoted, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean DemotePlayer(String factionName, String callerUuid, String demoteeUuid, String demoteeDisplayName) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (CanInvite(factionName, callerUuid) && HasPlayer(factionName, demoteeUuid)) {
|
||||||
|
VALID_FACTION_ROLES callerRole = allFactions.get(factionName).factionPlayerList.get(callerUuid);
|
||||||
|
VALID_FACTION_ROLES demoteeRole = allFactions.get(factionName).factionPlayerList.get(demoteeUuid);
|
||||||
|
Integer callerRoleLevel = ROLE_LEVELS.get(callerRole);
|
||||||
|
Integer demoteeRoleLevel = ROLE_LEVELS.get(demoteeRole);
|
||||||
|
|
||||||
|
// Factions is setup so that anyone can demote anybody underneath them & the lowest level will cause a demotion to be a KICK from faction
|
||||||
|
if (callerRoleLevel > demoteeRoleLevel) {
|
||||||
|
// If the role level would be lower than bottom level, KICK player
|
||||||
|
if (demoteeRoleLevel - 1 < ROLE_LEVELS.get(VALID_FACTION_ROLES.EMPLOYEE)) {
|
||||||
|
success = KickPlayer(factionName, callerUuid, demoteeUuid, demoteeDisplayName);
|
||||||
|
} else {
|
||||||
|
// Regular demotion!
|
||||||
|
demoteeRole = ROLES_BY_LEVEL.get(demoteeRoleLevel - 1);
|
||||||
|
|
||||||
|
// Update faction
|
||||||
|
allFactions.get(factionName).factionPlayerList.put(demoteeUuid, demoteeRole);
|
||||||
|
allFactions.get(factionName).DISPLAY_ONLY_LIST.put(demoteeDisplayName, demoteeRole);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ListOfAllFactions
|
||||||
|
///
|
||||||
|
/// @brief Get a list of all factions on the server
|
||||||
|
///
|
||||||
|
/// @return List of factions
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public List<String> ListOfAllFactions() {
|
||||||
|
List<String> facs = new ArrayList<String>();
|
||||||
|
|
||||||
|
System.out.println("ListOfFactions - map size: " + allFactions.size());
|
||||||
|
for (Entry<String, WriteableFaction> entry : allFactions.entrySet()) {
|
||||||
|
facs.add(entry.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
return facs;
|
||||||
|
}
|
||||||
|
}
|
385
src/main/java/jesse/keeblarcraft/FactionMgr/FactionManager.java
Normal file
385
src/main/java/jesse/keeblarcraft/FactionMgr/FactionManager.java
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* FactionManager
|
||||||
|
*
|
||||||
|
* Class is responsible for keeping track of 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;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionConfig.VALID_FACTION_ROLES;
|
||||||
|
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
|
||||||
|
import jesse.keeblarcraft.MailSystem.MailMgr;
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatMenu;
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatMsg;
|
||||||
|
import jesse.keeblarcraft.ChatStuff.ChatFormatting.COLOR_CODE;
|
||||||
|
import jesse.keeblarcraft.Utils.CommonStructures.Position3d;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public class FactionManager {
|
||||||
|
private static String FACTION_CFG_FILE = "factions/factions.json";
|
||||||
|
ConfigManager config = new ConfigManager();
|
||||||
|
private static FactionManager static_inst;
|
||||||
|
|
||||||
|
public static FactionManager GetInstance() {
|
||||||
|
if (static_inst == null) {
|
||||||
|
static_inst = new FactionManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FactionConfigClassWrapper {
|
||||||
|
FactionConfig factions = new FactionConfig();
|
||||||
|
}
|
||||||
|
FactionConfigClassWrapper factionConfig;// = new FactionConfigClassWrapper();
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public FactionManager() {
|
||||||
|
// Read in config at start of object
|
||||||
|
System.out.println("FACTIONMANAGER CONSTRUCTOR CALLED");
|
||||||
|
Boolean existingFile = false;
|
||||||
|
factionConfig = new FactionConfigClassWrapper();
|
||||||
|
|
||||||
|
Boolean tmpchck = factionConfig == null;
|
||||||
|
System.out.println("Is factionConfig null still? " + (tmpchck ? "YES" : "NO"));
|
||||||
|
try {
|
||||||
|
factionConfig = config.GetJsonObjectFromFile(FACTION_CFG_FILE, FactionConfigClassWrapper.class);
|
||||||
|
tmpchck = factionConfig == null;
|
||||||
|
System.out.println("Is factionconfig null after trying to load stuff? " + (tmpchck ? "YES" : "NO"));
|
||||||
|
existingFile = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the file if it didn't exist before
|
||||||
|
if (!existingFile)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
config.CreateDirectory(FACTION_CFG_FILE);
|
||||||
|
FlashConfig();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Keeblarcraft.LOGGER.error("Could not write to file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (factionConfig == null) {
|
||||||
|
// the only way for this to be possible is if the read-in was bad. flash config file then try again
|
||||||
|
factionConfig = new FactionConfigClassWrapper();
|
||||||
|
|
||||||
|
//TODO: Add safe-guard in here to check if default faction dir exists and move it to OLD/CORRUPTED (so data is not nuked from orbit)
|
||||||
|
factionConfig.factions = new FactionConfig();
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
FactionTier.InitializeFactionTiers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the faction is allowed to place a faction block. False if not
|
||||||
|
public Boolean CanPlaceFactionBlock(String factionName) {
|
||||||
|
return factionConfig.factions.GetNumberOfFactionBlocks(factionName) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFactionBlock(String factionName, Position3d newPos) {
|
||||||
|
// Only consider the faction block now "placed" if we (the manager) agree there are no others
|
||||||
|
if (factionConfig.factions.GetNumberOfFactionBlocks(factionName) == 0) {
|
||||||
|
factionConfig.factions.SetFactionBlock(factionName, newPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveFactionBlock(String factionName, Position3d blockPos) {
|
||||||
|
// In order to "remove" a block (NOT from the world, just the manager) - it must be the LAST remaining faction
|
||||||
|
// block. In general, it should NOT be possible (for now) to set more than one faction block in the world from
|
||||||
|
// the manager's perspective.
|
||||||
|
Position3d origBlock = factionConfig.factions.GetFactionBlock(factionName);
|
||||||
|
if (origBlock != null && origBlock.equals(blockPos)) {
|
||||||
|
factionConfig.factions.RemoveFactionBlock(factionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetNumberOfFactionBlocks(String factionName) {
|
||||||
|
return factionConfig.factions.GetNumberOfFactionBlocks(factionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VALID_FACTION_ROLES GetPlayerRole(String factionName, String uuid) {
|
||||||
|
return factionConfig.factions.GetPlayerRole(factionName, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is purely a chat-based call. Here to help with `/faction info` basically.
|
||||||
|
public void GetFactionInformation(ServerPlayerEntity player) {
|
||||||
|
String factionName = GetFactionOfPlayer(player.getUuidAsString());
|
||||||
|
|
||||||
|
if (!factionName.equals("")) {
|
||||||
|
Integer fPower = factionConfig.factions.GetPower(factionName);
|
||||||
|
HashMap<String, VALID_FACTION_ROLES> displayNames = factionConfig.factions.GetMemberNames(factionName);
|
||||||
|
Integer fBankBalance = factionConfig.factions.GetBankBalance(factionName);
|
||||||
|
|
||||||
|
System.out.println((fPower == null ? "YES":"NO") + " " + (displayNames == null ? "YES":"NO") + " " + (fBankBalance == null ? "YES":"NO"));
|
||||||
|
|
||||||
|
ArrayList<ChatMsg> chatPlayerList = new ArrayList<>();
|
||||||
|
for (Entry<String, VALID_FACTION_ROLES> entry : displayNames.entrySet()) {
|
||||||
|
ChatMsg temp = new ChatMsg();
|
||||||
|
temp.ColorMsg(entry.getKey() + " - " + entry.getValue().name(), COLOR_CODE.BLUE);
|
||||||
|
chatPlayerList.add(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's make our chat objects first so things are copyable and whatnot
|
||||||
|
ChatMsg chatHeader = new ChatMsg();
|
||||||
|
chatHeader.ColorMsg(Text.of("----[" + factionName + "]----"), COLOR_CODE.GOLD);
|
||||||
|
|
||||||
|
ChatMsg chatBalance = new ChatMsg();
|
||||||
|
chatBalance.ColorMsg(Text.of("Balance: " + Integer.toString(fBankBalance)), COLOR_CODE.GREEN);
|
||||||
|
|
||||||
|
ChatMsg chatPower = new ChatMsg();
|
||||||
|
chatPower.ColorMsg(Text.of("Power: " + Integer.toString(fPower)), COLOR_CODE.RED);
|
||||||
|
|
||||||
|
ChatMenu chatBlock = new ChatMenu();
|
||||||
|
chatBlock.SetHeader(chatHeader);
|
||||||
|
chatBlock.AddMsg(chatBalance);
|
||||||
|
chatBlock.AddMsg(chatPower);
|
||||||
|
|
||||||
|
chatBlock.SendMsg(player);
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("You aren't in a faction!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn LeaveFaction
|
||||||
|
///
|
||||||
|
/// @param[in] player is the player on the server
|
||||||
|
///
|
||||||
|
/// @brief Leave a faction
|
||||||
|
///
|
||||||
|
/// @return True if player can leave their faction, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean LeaveFaction(ServerPlayerEntity player) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
String playerFac = factionConfig.factions.FindFactionOfPlayer(player.getUuidAsString());
|
||||||
|
|
||||||
|
if (playerFac != "") {
|
||||||
|
success = factionConfig.factions.LeaveFaction(playerFac, player.getUuidAsString(), player.getEntityName());
|
||||||
|
player.sendMessage(Text.of("[Factions]: You left your faction!"));
|
||||||
|
FlashConfig();
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("[Factions]: You are not in a faction!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn CreateFaction
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the faction to be created
|
||||||
|
///
|
||||||
|
/// @param[in] player is the player on the server
|
||||||
|
///
|
||||||
|
/// @brief Create a new faction
|
||||||
|
///
|
||||||
|
/// @return True if successfully created, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean CreateFaction(String factionName, ServerPlayerEntity creator) {
|
||||||
|
Boolean success = false;
|
||||||
|
String facOfPlayer = factionConfig.factions.FindFactionOfPlayer(creator.getUuidAsString());
|
||||||
|
|
||||||
|
if (facOfPlayer == "") {
|
||||||
|
// creator.sendMessage(Text.of("Your display name: " + creator.getDisplayName().toString()));
|
||||||
|
// creator.sendMessage(Text.of("Your name: " + creator.getName()));
|
||||||
|
// creator.sendMessage(Text.of("Your custom name: " + creator.getCustomName()));
|
||||||
|
// creator.sendMessage(Text.of("Your entity name: " + creator.getEntityName()));
|
||||||
|
success = factionConfig.factions.CreateFaction(factionName, creator.getUuidAsString(), creator.getEntityName());
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
creator.sendMessage(Text.of("[Factions]: Could not create faction - faction already exists."));
|
||||||
|
} else {
|
||||||
|
creator.sendMessage(Text.of("[Factions]: Successfully created faction!"));
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
creator.sendMessage(Text.of("[Factions]: You are already in a faction! You cannot create one."));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn DeleteFaction
|
||||||
|
///
|
||||||
|
/// @param[in] factionName is the faction to be created
|
||||||
|
///
|
||||||
|
/// @param[in] caller is the player on the server
|
||||||
|
///
|
||||||
|
/// @brief Delete a faction
|
||||||
|
///
|
||||||
|
/// @return True if successfully deleted, false if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean DeleteFaction(String factionName, ServerPlayerEntity caller) {
|
||||||
|
Boolean success = factionConfig.factions.DeleteFaction(factionName, caller.getUuidAsString());
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
caller.sendMessage(Text.of("[Factions]: Could not delete faction. You must be owner & faction must exist."));
|
||||||
|
} else {
|
||||||
|
caller.sendMessage(Text.of("[Factions]: Successfully deleted faction."));
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean JoinFaction(ServerPlayerEntity player, String factionName) {
|
||||||
|
Boolean joinedFaction = factionConfig.factions.JoinFaction(factionName, player.getUuidAsString(), player.getEntityName());
|
||||||
|
|
||||||
|
if (joinedFaction) {
|
||||||
|
player.sendMessage(Text.of("Successfully joined the faction " + factionName));
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("Failed to join faction - you were not on the invite list!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return joinedFaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ListOfFactions
|
||||||
|
///
|
||||||
|
/// @brief Get a list of all factions on the server
|
||||||
|
///
|
||||||
|
/// @return Faction list. Empty list if no factions
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public List<String> ListOfFactions() {
|
||||||
|
System.out.println("Callthrough of listoffactions");
|
||||||
|
return factionConfig.factions.ListOfAllFactions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetFactionOfPlayer
|
||||||
|
///
|
||||||
|
/// @param[in] playerUuid is the uuid of the player
|
||||||
|
///
|
||||||
|
/// @brief Gets the faction of a player on the server
|
||||||
|
///
|
||||||
|
/// @return String with faction name. Empty string if no faction tie
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public String GetFactionOfPlayer(String playerUuid) {
|
||||||
|
return factionConfig.factions.FindFactionOfPlayer(playerUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean InvitePlayerToFaction(ServerPlayerEntity caller, String inviteeUuid, String inviteeDisplayName) {
|
||||||
|
String playerFaction = factionConfig.factions.FindFactionOfPlayer(caller.getUuidAsString());
|
||||||
|
Boolean success = false;
|
||||||
|
if (!playerFaction.equals("")) {
|
||||||
|
success = factionConfig.factions.InvitePlayerToFaction(playerFaction, caller.getUuidAsString(), inviteeUuid);
|
||||||
|
} else {
|
||||||
|
caller.sendMessage(Text.of("You aren't in a faction!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
String mailMsg = "You received a faction invite from " + caller.getEntityName() + "! You can join with /faction join " + playerFaction;
|
||||||
|
MailMgr.GetInstance().SendMail(inviteeUuid, mailMsg);
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean SetFactionPower(ServerPlayerEntity caller, String factionName, Integer amount) {
|
||||||
|
Boolean success = false;
|
||||||
|
|
||||||
|
if (caller.hasPermissionLevel(4)) {
|
||||||
|
success = factionConfig.factions.SetPower(factionName, amount);
|
||||||
|
FlashConfig();
|
||||||
|
} else {
|
||||||
|
caller.sendMessage(Text.of("You do not have permission to use this command"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, VALID_FACTION_ROLES> GetFactionPlayers(String factionName) {
|
||||||
|
return factionConfig.factions.GetFactionPlayers(factionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer GetFactionPower(String factionName) {
|
||||||
|
int fPower = 0;
|
||||||
|
if (factionConfig.factions.IsValid(factionName)) {
|
||||||
|
fPower = factionConfig.factions.GetPower(factionName);
|
||||||
|
}
|
||||||
|
return fPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FactionTierEnum GetFactionTier(String factionName) {
|
||||||
|
return FactionTier.GetFactionTier(factionConfig.factions.GetPower(factionName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer GetFactionPower(ServerPlayerEntity caller) {
|
||||||
|
Integer amount = 0;
|
||||||
|
|
||||||
|
String playerFaction = factionConfig.factions.FindFactionOfPlayer(caller.getUuidAsString());
|
||||||
|
if (!playerFaction.equals("")) {
|
||||||
|
amount = factionConfig.factions.GetPower(playerFaction);
|
||||||
|
caller.sendMessage(Text.of("[" + playerFaction + " - POWER]: " + Integer.toString(amount)));
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean PromotePlayer(ServerPlayerEntity caller, String promoteeUuid, String promoteeDisplayName) {
|
||||||
|
Boolean success = factionConfig.factions.PromotePlayer(GetFactionOfPlayer(caller.getUuidAsString()), caller.getUuidAsString(), promoteeUuid, promoteeDisplayName);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
caller.sendMessage(Text.of("[Factions]: Could not promote player - you need to be a higher rank than them and they cannot be promoted to your level!"));
|
||||||
|
} else {
|
||||||
|
caller.sendMessage(Text.of("[Factions]: Successfully promoted player!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn DemotePlayer
|
||||||
|
///
|
||||||
|
/// @param[in] caller is the player who is demoting another player
|
||||||
|
///
|
||||||
|
/// @param[in] demoteeUuid is the player's uuid who is being demoted
|
||||||
|
///
|
||||||
|
/// @param[in] demoteeDisplayName is the players display name who is being demoted
|
||||||
|
///
|
||||||
|
/// @brief Demote a player from a faction
|
||||||
|
///
|
||||||
|
/// @return True if player is demoted. False if not
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean DemotePlayer(ServerPlayerEntity caller, String demoteeUuid, String demoteeDisplayName) {
|
||||||
|
Boolean success = factionConfig.factions.DemotePlayer(GetFactionOfPlayer(caller.getUuidAsString()), caller.getUuidAsString(), demoteeUuid, demoteeDisplayName);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
caller.sendMessage(Text.of("[Factions]: Could not demote player - you need to be a higher rank than them to demote them!"));
|
||||||
|
} else {
|
||||||
|
caller.sendMessage(Text.of("[Factions]: Successfully demoted player!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn FlashConfig
|
||||||
|
///
|
||||||
|
/// @brief Update the faction configuration file on disk
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void FlashConfig() {
|
||||||
|
config.WriteToJsonFile(FACTION_CFG_FILE, factionConfig);
|
||||||
|
}
|
||||||
|
}
|
65
src/main/java/jesse/keeblarcraft/FactionMgr/FactionTier.java
Normal file
65
src/main/java/jesse/keeblarcraft/FactionMgr/FactionTier.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package jesse.keeblarcraft.FactionMgr;
|
||||||
|
|
||||||
|
import com.google.common.collect.Range;
|
||||||
|
import com.google.common.collect.RangeMap;
|
||||||
|
import com.google.common.collect.TreeRangeMap;
|
||||||
|
|
||||||
|
public class FactionTier {
|
||||||
|
public static enum FactionTierEnum {
|
||||||
|
TIER_INVALID,
|
||||||
|
TIER_I,
|
||||||
|
TIER_II,
|
||||||
|
TIER_III,
|
||||||
|
TIER_IV,
|
||||||
|
TIER_V,
|
||||||
|
TIER_VI
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RangeMap<Integer, FactionTierEnum> factionTiers = TreeRangeMap.create();
|
||||||
|
|
||||||
|
public static void InitializeFactionTiers() {
|
||||||
|
factionTiers.put(Range.closed(0, 29), FactionTierEnum.TIER_I);
|
||||||
|
factionTiers.put(Range.closed(30, 74), FactionTierEnum.TIER_II);
|
||||||
|
factionTiers.put(Range.closed(75, 99), FactionTierEnum.TIER_III);
|
||||||
|
factionTiers.put(Range.closed(100, 149), FactionTierEnum.TIER_IV);
|
||||||
|
factionTiers.put(Range.closed(150, 999), FactionTierEnum.TIER_V);
|
||||||
|
factionTiers.put(Range.closed(1000, Integer.MAX_VALUE), FactionTierEnum.TIER_VI);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tier 1 can never be greater than anything (and not itself, obviously)
|
||||||
|
public static Boolean IsGreaterThan(FactionTierEnum tierInQuestion, FactionTierEnum tierToCompareAgainst) {
|
||||||
|
Boolean isGreater = false;
|
||||||
|
|
||||||
|
if (tierInQuestion == FactionTierEnum.TIER_II && tierToCompareAgainst == FactionTierEnum.TIER_I) {
|
||||||
|
isGreater = true;
|
||||||
|
} else if (tierInQuestion == FactionTierEnum.TIER_III && (tierToCompareAgainst == FactionTierEnum.TIER_II || tierToCompareAgainst == FactionTierEnum.TIER_I)) {
|
||||||
|
isGreater = true;
|
||||||
|
} else if (tierInQuestion == FactionTierEnum.TIER_IV && (tierToCompareAgainst == FactionTierEnum.TIER_III || tierToCompareAgainst == FactionTierEnum.TIER_II || tierToCompareAgainst == FactionTierEnum.TIER_I)) {
|
||||||
|
isGreater = true;
|
||||||
|
} else if (tierInQuestion == FactionTierEnum.TIER_V && (tierToCompareAgainst == FactionTierEnum.TIER_IV || tierToCompareAgainst == FactionTierEnum.TIER_III || tierToCompareAgainst == FactionTierEnum.TIER_II || tierToCompareAgainst == FactionTierEnum.TIER_I)) {
|
||||||
|
isGreater = true;
|
||||||
|
} else if (tierInQuestion == FactionTierEnum.TIER_VI && (tierToCompareAgainst == FactionTierEnum.TIER_V || tierToCompareAgainst == FactionTierEnum.TIER_IV || tierToCompareAgainst == FactionTierEnum.TIER_III || tierToCompareAgainst == FactionTierEnum.TIER_II || tierToCompareAgainst == FactionTierEnum.TIER_I)) {
|
||||||
|
isGreater = true;
|
||||||
|
}
|
||||||
|
return isGreater;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean IsEqualTo(FactionTierEnum tierInQuestion, FactionTierEnum tierToCompareAgainst) {
|
||||||
|
return tierInQuestion == tierToCompareAgainst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean IsGreaterOrEqualTo(FactionTierEnum tierInQuestion, FactionTierEnum tierToCompareAgainst) {
|
||||||
|
return IsEqualTo(tierInQuestion, tierToCompareAgainst) || IsGreaterThan(tierInQuestion, tierToCompareAgainst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure you initialize tiers by calling the above function first!
|
||||||
|
public static FactionTierEnum GetFactionTier(Integer value) {
|
||||||
|
FactionTierEnum tier = factionTiers.get(value);
|
||||||
|
|
||||||
|
if (tier == null) {
|
||||||
|
tier = FactionTierEnum.TIER_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tier;
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,110 @@
|
|||||||
|
package jesse.keeblarcraft.GuiMgr.Factions;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.CustomBlocks.BlockEntities.FactionBlockEntity;
|
||||||
|
import jesse.keeblarcraft.GuiMgr.ScreenHandlerRegistration;
|
||||||
|
import net.minecraft.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.inventory.Inventory;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.screen.ArrayPropertyDelegate;
|
||||||
|
import net.minecraft.screen.PropertyDelegate;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
|
||||||
|
public class FactionBlockScreenHandler extends ScreenHandler {
|
||||||
|
private final Inventory inventory;
|
||||||
|
private final PropertyDelegate propertyDelegate;
|
||||||
|
public final FactionBlockEntity blockEntity;
|
||||||
|
public int factionPower = 0;
|
||||||
|
|
||||||
|
public FactionBlockScreenHandler(int syncId, PlayerInventory inventory, PacketByteBuf buf) {
|
||||||
|
this(syncId, inventory, inventory.player.getWorld().getBlockEntity(buf.readBlockPos()), new ArrayPropertyDelegate(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
public FactionBlockScreenHandler(int syncId, PlayerInventory playerInventory, BlockEntity blockEntity, PropertyDelegate arrayPropertyDelegate) {
|
||||||
|
super(ScreenHandlerRegistration.FACTION_BLOCK_SCREEN_HANDLER, syncId);
|
||||||
|
checkSize((Inventory) blockEntity, 7);
|
||||||
|
this.inventory = (Inventory) blockEntity;
|
||||||
|
inventory.onOpen(playerInventory.player);
|
||||||
|
this.propertyDelegate = arrayPropertyDelegate;
|
||||||
|
this.blockEntity = (FactionBlockEntity) blockEntity;
|
||||||
|
|
||||||
|
// Need a better way of storing these coordinates...
|
||||||
|
this.addSlot(new Slot(inventory, 0, -1, 2)); // top row
|
||||||
|
this.addSlot(new Slot(inventory, 2, 35, 2));
|
||||||
|
this.addSlot(new Slot(inventory, 4, 71, 2));
|
||||||
|
|
||||||
|
this.addSlot(new Slot(inventory, 1, 17, 36));
|
||||||
|
this.addSlot(new Slot(inventory, 3, 54, 36));
|
||||||
|
this.addSlot(new Slot(inventory, 5, 90, 36));
|
||||||
|
|
||||||
|
this.addSlot(new Slot(inventory, 6, 148, 20));
|
||||||
|
|
||||||
|
addPlayerInventory(playerInventory);
|
||||||
|
addPlayerHotbar(playerInventory);
|
||||||
|
|
||||||
|
// Remainder stuff
|
||||||
|
addProperties(arrayPropertyDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer GetFactionPower() {
|
||||||
|
factionPower = this.propertyDelegate.get(0);
|
||||||
|
return factionPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is just for SHIFT+CLICK moving
|
||||||
|
@Override
|
||||||
|
public ItemStack quickMove(PlayerEntity player, int invSlot) {
|
||||||
|
System.out.println("Is client: " + player.getWorld().isClient());
|
||||||
|
ItemStack newStack = ItemStack.EMPTY;
|
||||||
|
Slot slot = this.slots.get(invSlot);
|
||||||
|
if (slot.hasStack()) {
|
||||||
|
ItemStack originalStack = slot.getStack();
|
||||||
|
newStack = originalStack.copy();
|
||||||
|
|
||||||
|
// TODO: This is from the YT video and it looks atrocious. Refactor this later
|
||||||
|
if ( (invSlot < this.inventory.size() && !this.insertItem(originalStack, this.inventory.size(), this.slots.size(), true) ) ||
|
||||||
|
(!this.insertItem(originalStack, 0, this.inventory.size(), false))) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalStack.isEmpty()) {
|
||||||
|
slot.setStack(ItemStack.EMPTY);
|
||||||
|
} else {
|
||||||
|
slot.markDirty();;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
// From Kaupenjoe video
|
||||||
|
private void addPlayerInventory(PlayerInventory playerInventory) {
|
||||||
|
int spacing = -8;
|
||||||
|
for (int i = 0; i < 3; ++i) { // Rows
|
||||||
|
for (int l = 0; l < 9; ++l) { // Columns
|
||||||
|
int index = l + i * 9 + 9; // l = col, i*9 = the row to be on (scaling by 9 bc slots are 1-(9*3) in amount), +9 = where on that row to be!
|
||||||
|
int x = l * 22 + spacing; // Texture draw position on image
|
||||||
|
int y = 89 + i * 22; // Texture draw position on image
|
||||||
|
this.addSlot(new Slot(playerInventory, index, x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// From Kaupenjoe video
|
||||||
|
private void addPlayerHotbar(PlayerInventory playerInventory) {
|
||||||
|
int spacing = -8;
|
||||||
|
for (int i = 0; i < 9; ++i) {
|
||||||
|
// int x = (8 + i * 18) + spacing; // Texture draw position
|
||||||
|
int x = i * 22 + spacing; // Texture draw position
|
||||||
|
int y = 162; // Texture draw position
|
||||||
|
this.addSlot(new Slot(playerInventory, i, x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUse(PlayerEntity player) {
|
||||||
|
return this.inventory.canPlayerUse(player);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package jesse.keeblarcraft.GuiMgr;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.GuiMgr.Factions.FactionBlockScreenHandler;
|
||||||
|
import jesse.keeblarcraft.GuiMgr.ShopKeeper.ShopKeeperHandler;
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.registry.Registry;
|
||||||
|
import net.minecraft.resource.featuretoggle.FeatureFlags;
|
||||||
|
import net.minecraft.screen.ScreenHandlerType;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class ScreenHandlerRegistration {
|
||||||
|
public static final ScreenHandlerType<FactionBlockScreenHandler> FACTION_BLOCK_SCREEN_HANDLER =
|
||||||
|
Registry.register(Registries.SCREEN_HANDLER, new Identifier(Keeblarcraft.MOD_ID, "faction_block"),
|
||||||
|
new ExtendedScreenHandlerType<>(FactionBlockScreenHandler::new));
|
||||||
|
|
||||||
|
public static final ScreenHandlerType<ShopKeeperHandler> SHOP_KEEPER_HANDLER_SCREEN_HANDLER_TYPE =
|
||||||
|
Registry.register(Registries.SCREEN_HANDLER, new Identifier(Keeblarcraft.MOD_ID, "shopkeeper"),
|
||||||
|
new ScreenHandlerType<>(ShopKeeperHandler::new, FeatureFlags.VANILLA_FEATURES));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void registerScreenHandlers() {
|
||||||
|
Keeblarcraft.LOGGER.info("Registering screen handlers for {}", Keeblarcraft.MOD_ID);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package jesse.keeblarcraft.GuiMgr.ShopKeeper;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.GuiMgr.ScreenHandlerRegistration;
|
||||||
|
import jesse.keeblarcraft.Utils.CustomSlot;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.village.Merchant;
|
||||||
|
import net.minecraft.village.MerchantInventory;
|
||||||
|
import net.minecraft.village.SimpleMerchant;
|
||||||
|
import net.minecraft.village.TradeOfferList;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ShopKeeperHandler extends ScreenHandler {
|
||||||
|
private Merchant merchant;
|
||||||
|
private MerchantInventory merchantInventory;
|
||||||
|
private boolean canRefreshTrades = false;
|
||||||
|
private boolean isLeveledMerchant = false;
|
||||||
|
private int levelAmount = 0;
|
||||||
|
private int merchantExperience = 0;
|
||||||
|
private Map<Text, Integer> slotIdByName = new HashMap<>();
|
||||||
|
ShopKeeperSlots allSlots = new ShopKeeperSlots();
|
||||||
|
|
||||||
|
public ShopKeeperHandler(int syncId, PlayerInventory playerInventory) {
|
||||||
|
this(syncId, playerInventory, new SimpleMerchant(playerInventory.player));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShopKeeperHandler(int syncId, PlayerInventory playerInventory, Merchant merchant) {
|
||||||
|
super(ScreenHandlerRegistration.SHOP_KEEPER_HANDLER_SCREEN_HANDLER_TYPE, syncId);
|
||||||
|
this.merchant = merchant;
|
||||||
|
this.merchantInventory = new MerchantInventory(merchant);
|
||||||
|
RegisterSlots();
|
||||||
|
// Add slots below
|
||||||
|
// this.addSlot(new Slot(this.merchantInventory, 0, 136, 37));
|
||||||
|
// this.addSlot(new CustomSlot(this.merchantInventory, 0, 136, 37), Text.of("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterSlots() {
|
||||||
|
CustomSlot slotOne = new CustomSlot(this.merchantInventory, 0, 136, 37);
|
||||||
|
|
||||||
|
|
||||||
|
allSlots.AddSlot("add_item_menu", "add_item_slot", slotOne);
|
||||||
|
this.addSlot(slotOne);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showSlot(String menuName, String slotName) {
|
||||||
|
allSlots.ShowSlot(menuName, slotName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideSlot(String menuName, String slotName) {
|
||||||
|
allSlots.HideSlot(menuName, slotName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomSlot getSlot(Text name) {
|
||||||
|
System.out.println("Printing slot map");
|
||||||
|
for (Slot slot : super.slots) {
|
||||||
|
System.out.println("Found slot with id: " + slot.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Printing self stored map");
|
||||||
|
for (Map.Entry<Text, Integer> entry : this.slotIdByName.entrySet()) {
|
||||||
|
System.out.println("entry set id value: " + "K: " + entry.getKey() + " -> V: " + entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (CustomSlot) super.getSlot(slotIdByName.get(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetOffers(TradeOfferList offers) {
|
||||||
|
this.merchant.setOffersFromServer(offers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetExperienceLevel(int xp) {
|
||||||
|
this.merchantExperience = xp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLevelProgress(int level) {
|
||||||
|
this.levelAmount = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLeveled(boolean leveled) {
|
||||||
|
this.isLeveledMerchant = leveled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCanRefreshTrades(boolean isRefreshable) {
|
||||||
|
this.canRefreshTrades = isRefreshable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack quickMove(PlayerEntity player, int slot) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called every tick
|
||||||
|
@Override
|
||||||
|
public boolean canUse(PlayerEntity player) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package jesse.keeblarcraft.GuiMgr.ShopKeeper;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Utils.CustomSlot;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// Until I find the will and way to mixin slots to be able to be removed (i.e: not backed by an Inventory) I am patching
|
||||||
|
// slots in its own registration class (like ShopKeeperSlots). The time to do the mixin stuff far exceeds what is worth
|
||||||
|
// it for the time being.
|
||||||
|
public class ShopKeeperSlots {
|
||||||
|
private final Map<String, HashMap<String, CustomSlot>> shopKeeperSlots = new HashMap<>();
|
||||||
|
|
||||||
|
public ShopKeeperSlots() {}
|
||||||
|
|
||||||
|
public void AddSlot(String menuName, String slotName, CustomSlot newSlot) {
|
||||||
|
if (!shopKeeperSlots.containsKey(slotName)) {
|
||||||
|
shopKeeperSlots.put(menuName, new HashMap<>());
|
||||||
|
shopKeeperSlots.get(menuName).put(slotName, newSlot);
|
||||||
|
} else {
|
||||||
|
shopKeeperSlots.get(menuName).put(slotName, newSlot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, CustomSlot> GetSlotsByMenu(String menu) {
|
||||||
|
return this.shopKeeperSlots.get(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HideSlot(String menuName, String slotName) {
|
||||||
|
for (Map.Entry<String, HashMap<String, CustomSlot>> entry : shopKeeperSlots.entrySet()) {
|
||||||
|
if (entry.getKey().equals(menuName)) {
|
||||||
|
for (Map.Entry<String, CustomSlot> menuSlots : entry.getValue().entrySet()) {
|
||||||
|
if (menuSlots.getKey().equals(slotName)) {
|
||||||
|
menuSlots.getValue().setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowSlot(String menuName, String slotName) {
|
||||||
|
for (Map.Entry<String, HashMap<String, CustomSlot>> entry : shopKeeperSlots.entrySet()) {
|
||||||
|
// System.out.println("Menu name: " + entry.getKey());
|
||||||
|
if (entry.getKey().equals(menuName)) {
|
||||||
|
for (Map.Entry<String, CustomSlot> menuSlots : entry.getValue().entrySet()) {
|
||||||
|
// System.out.println("Slot name: " + menuSlots.getKey());
|
||||||
|
if (menuSlots.getKey().equals(slotName)) {
|
||||||
|
menuSlots.getValue().setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package jesse.keeblarcraft.GuiMgr;
|
package jesse.keeblarcraft.GuiMgr.SkillTree;
|
||||||
|
|
||||||
import jesse.keeblarcraft.Keeblarcraft;
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
@ -11,9 +11,8 @@ import java.util.HashMap;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
import jesse.keeblarcraft.ChatStuff.ChatMsg;
|
||||||
import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION;
|
|
||||||
|
|
||||||
public class PlayerNote {
|
public class PlayerNote {
|
||||||
/// Class variables
|
/// Class variables
|
||||||
@ -86,21 +85,18 @@ public class PlayerNote {
|
|||||||
// In the event the above code failed out, this means a new file has to be created for the player's uuid
|
// In the event the above code failed out, this means a new file has to be created for the player's uuid
|
||||||
if (!existingFile)
|
if (!existingFile)
|
||||||
{
|
{
|
||||||
System.out.println(ChatUtil.ColoredString("Trying to create new file", CONSOLE_COLOR.BLUE));
|
|
||||||
try {
|
try {
|
||||||
thisNote.uuid = uuid;
|
thisNote.uuid = uuid;
|
||||||
FlashConfig();
|
FlashConfig();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println(ChatUtil.ColoredString("Could not write to file", CONSOLE_COLOR.RED));
|
Keeblarcraft.LOGGER.warn("Could not write to the player notes file");
|
||||||
}
|
}
|
||||||
} 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
|
// 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
|
// a new file with this players uuid
|
||||||
if ("".equals(thisNote.uuid)) {
|
if ("".equals(thisNote.uuid)) {
|
||||||
System.out.println(ChatUtil.ColoredString("Assigning new config file for this uuid. No previous existing", CONSOLE_COLOR.BLUE));
|
System.out.println("Assigning new config file for this uuid. No previous existing");
|
||||||
thisNote.uuid = uuid;
|
thisNote.uuid = uuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,10 +226,6 @@ public class PlayerNote {
|
|||||||
/// @brief Writes to the configuration file
|
/// @brief Writes to the configuration file
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
public void FlashConfig() {
|
public void FlashConfig() {
|
||||||
try {
|
config.WriteToJsonFile("notes/" + thisNote.uuid + ".json", thisNote);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,21 @@
|
|||||||
* Keeblarcraft
|
* Keeblarcraft
|
||||||
*
|
*
|
||||||
* This is the primary server side "main" object that is referenced by Fabric. This is where everything is setup for the mod
|
* 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
|
* and a very important class. Please be careful as you add to it
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// color colour
|
|
||||||
|
|
||||||
package jesse.keeblarcraft;
|
package jesse.keeblarcraft;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Entities.EntityRegistration;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
|
import net.kyrptonaught.customportalapi.api.CustomPortalBuilder;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.registry.Registry;
|
||||||
import net.minecraft.resource.featuretoggle.FeatureSet;
|
import net.minecraft.resource.featuretoggle.FeatureSet;
|
||||||
@ -23,16 +28,19 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
|
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
|
||||||
import jesse.keeblarcraft.AttributeMgr.AttributeTree;
|
import jesse.keeblarcraft.BankMgr.BankManager;
|
||||||
import jesse.keeblarcraft.Commands.CustomCommandManager;
|
import jesse.keeblarcraft.Commands.CustomCommandManager;
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.SQLUnitTest;
|
||||||
import jesse.keeblarcraft.CustomBlocks.BlockList;
|
import jesse.keeblarcraft.CustomBlocks.BlockList;
|
||||||
|
import jesse.keeblarcraft.CustomBlocks.BlockEntities.BlockEntityRegistration;
|
||||||
import jesse.keeblarcraft.CustomItems.ItemManager;
|
import jesse.keeblarcraft.CustomItems.ItemManager;
|
||||||
|
import jesse.keeblarcraft.EventMgr.DimensionLoadingEvent;
|
||||||
|
import jesse.keeblarcraft.EventMgr.PlayerJoinListener;
|
||||||
import jesse.keeblarcraft.EventMgr.ServerTickListener;
|
import jesse.keeblarcraft.EventMgr.ServerTickListener;
|
||||||
import jesse.keeblarcraft.GuiMgr.TreeHandler;
|
import jesse.keeblarcraft.GuiMgr.ScreenHandlerRegistration;
|
||||||
|
import jesse.keeblarcraft.GuiMgr.SkillTree.TreeHandler;
|
||||||
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
|
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
|
||||||
import jesse.keeblarcraft.Utils.Setup;
|
import jesse.keeblarcraft.Utils.Setup;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
|
||||||
|
|
||||||
public class Keeblarcraft implements ModInitializer {
|
public class Keeblarcraft implements ModInitializer {
|
||||||
public static String MOD_ID = "keeblarcraft";
|
public static String MOD_ID = "keeblarcraft";
|
||||||
@ -44,40 +52,55 @@ public class Keeblarcraft implements ModInitializer {
|
|||||||
Identifier.of(Keeblarcraft.MOD_ID, "tree_gui"),
|
Identifier.of(Keeblarcraft.MOD_ID, "tree_gui"),
|
||||||
new ScreenHandlerType<>(TreeHandler::new, FeatureSet.empty()));
|
new ScreenHandlerType<>(TreeHandler::new, FeatureSet.empty()));
|
||||||
|
|
||||||
|
// public static final Block MAGIC_CHEST_BLOCK = Registry.register(Registries.BLOCK, Identifier.of(Keeblarcraft.MOD_ID, "magic_chest_block"),
|
||||||
|
// new MagicChestBlock(AbstractBlock.Settings.copy(Blocks.CHEST)));
|
||||||
|
|
||||||
|
// public static final BlockEntityType<MagicChestBlockEntity> MAGIC_CHEST_BLOCK_ENTITY = Registry.register(Registry.BLOCK_ENTITY_TYPE,
|
||||||
|
// Identifier.of(Keeblarcraft.MOD_ID, "magic_chest_block_entity"), BlockEntityType.Builder.create(MagicChestBlockEntity::new, MAGIC_CHEST_BLOCK).build());
|
||||||
|
|
||||||
CustomCommandManager cmdMgr = new CustomCommandManager();
|
CustomCommandManager cmdMgr = new CustomCommandManager();
|
||||||
Setup setup = Setup.GetInstance();
|
Setup setup = Setup.GetInstance();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
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) {
|
if (setup != null) {
|
||||||
try {
|
try {
|
||||||
// Run setup. If setup fails; it throws SETUP_FAILED_EXCEPTION
|
// Run setup. If setup fails; it throws SETUP_FAILED_EXCEPTION
|
||||||
LOGGER.info("\033[34m Running setup stage \033[0m");
|
LOGGER.info("Running setup");
|
||||||
setup.RunSetup();
|
setup.RunSetup();
|
||||||
|
|
||||||
// This is a very special case where this must be in this classes' initializer
|
/// TODO: Move callbacks somewhere else
|
||||||
// method
|
|
||||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||||
var player = handler.player;
|
System.out.println("ServerPlayConnectionEvents.JOIN called");
|
||||||
Keeblarcraft.LOGGER.info("Player " + player.getName() + " has logged in. Creating tree...");
|
PlayerJoinListener.GetInstance().HandleServerJoinEvent(handler, sender, server);
|
||||||
|
|
||||||
if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == false) {
|
|
||||||
AttributeMgr.activeTrees.put(player.getUuidAsString(), new AttributeTree(player.getUuidAsString()));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
|
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
|
||||||
var player = handler.player;
|
var player = handler.player;
|
||||||
Keeblarcraft.LOGGER.info("Player " + player.getName() + " has logged out. Deleting tree...");
|
Keeblarcraft.LOGGER.info("Player " + player.getName() + " has logged out. Deleting tree...");
|
||||||
|
|
||||||
if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == true) {
|
AttributeMgr.activeTrees.remove(player.getUuidAsString());
|
||||||
AttributeMgr.activeTrees.remove(player.getUuidAsString());
|
});
|
||||||
}
|
|
||||||
|
ServerEntityWorldChangeEvents.AFTER_PLAYER_CHANGE_WORLD.register((player, origin, destination) -> {
|
||||||
|
System.out.println("Calling back...");
|
||||||
|
DimensionLoadingEvent.GetInstance().HandleWorldMove(player, origin, destination);
|
||||||
|
});
|
||||||
|
|
||||||
|
ServerLifecycleEvents.SERVER_STOPPING.register((server) -> {
|
||||||
|
// Stuff here
|
||||||
|
System.out.println("SERVER_STOPPING callback called.");
|
||||||
|
DimensionLoadingEvent.GetInstance().SaveInventories();
|
||||||
|
});
|
||||||
|
|
||||||
|
ServerEntityEvents.ENTITY_LOAD.register((entity, world) -> {
|
||||||
|
// System.out.println("ENTITY LOAD EVENT INFORMATION");
|
||||||
|
// System.out.println("Name: " + entity.getEntityName());
|
||||||
|
// System.out.println("World: " + world.asString());
|
||||||
|
// System.out.println("COORDS: " + entity.getX() + " " + entity.getY() + " " + entity.getZ());
|
||||||
|
// System.out.println("TYPE: " + entity.getType());
|
||||||
|
// System.out.println("SPAWN GROUP: " + entity.getType().getSpawnGroup().asString());
|
||||||
|
// System.out.println("Is hostile? " + (entity instanceof HostileEntity ? "YES":"NO"));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize our ticks!!
|
// Initialize our ticks!!
|
||||||
@ -90,6 +113,13 @@ public class Keeblarcraft implements ModInitializer {
|
|||||||
// Register attributes
|
// Register attributes
|
||||||
AttributeMgr.RegisterAttributes();
|
AttributeMgr.RegisterAttributes();
|
||||||
|
|
||||||
|
// Register the banking system
|
||||||
|
BankManager.GetInstance().InitializeBanks();
|
||||||
|
|
||||||
|
System.out.println("Attempting SQL Registration call");
|
||||||
|
|
||||||
|
SQLUnitTest sqlTests = new SQLUnitTest();
|
||||||
|
sqlTests.RunTests();
|
||||||
|
|
||||||
/// THE BELOW ITEMS MUST BE DONE LAST IN THE STEPS
|
/// THE BELOW ITEMS MUST BE DONE LAST IN THE STEPS
|
||||||
// Register items
|
// Register items
|
||||||
@ -97,15 +127,31 @@ public class Keeblarcraft implements ModInitializer {
|
|||||||
|
|
||||||
// Register blocks
|
// Register blocks
|
||||||
BlockList.RegisterBlocks();
|
BlockList.RegisterBlocks();
|
||||||
|
BlockEntityRegistration.RegisterBlockEntities();
|
||||||
|
|
||||||
|
// World generation
|
||||||
|
EntityRegistration.RegisterEntities();
|
||||||
|
|
||||||
|
// Custom portal generator
|
||||||
|
System.out.println("BUILDING CUSTOM PORTAL");
|
||||||
|
CustomPortalBuilder.beginPortal()
|
||||||
|
.frameBlock(Blocks.GOLD_BLOCK)
|
||||||
|
.lightWithItem(Items.ENDER_EYE)
|
||||||
|
.destDimID(new Identifier(Keeblarcraft.MOD_ID, "keeblarcraftdim"))
|
||||||
|
.tintColor(234, 183, 8)
|
||||||
|
.registerPortal();
|
||||||
|
|
||||||
|
// Screen handlers
|
||||||
|
ScreenHandlerRegistration.registerScreenHandlers();
|
||||||
|
|
||||||
|
|
||||||
} catch (SETUP_FAILED_EXCEPTION e) {
|
} 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));
|
Keeblarcraft.LOGGER.error("ERROR. Setup failed to initialize environment. Mod likely does not have read/write permissions inside area. Mod will now close out.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Program exit. Dual definition of setup somehow happened!
|
// 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));
|
Keeblarcraft.LOGGER.error("Dual definition of singleton attempted! Out of order initialization? How did this even happen?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
81
src/main/java/jesse/keeblarcraft/MailSystem/MailMgr.java
Normal file
81
src/main/java/jesse/keeblarcraft/MailSystem/MailMgr.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package jesse.keeblarcraft.MailSystem;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
|
|
||||||
|
public class MailMgr {
|
||||||
|
ConfigManager config = new ConfigManager();
|
||||||
|
MailConfigClass mailConfig;
|
||||||
|
String CONFIG_FILE = "mail/player_mail.json";
|
||||||
|
|
||||||
|
private static MailMgr static_inst;
|
||||||
|
public static MailMgr GetInstance() {
|
||||||
|
if (static_inst == null) {
|
||||||
|
static_inst = new MailMgr();
|
||||||
|
}
|
||||||
|
return static_inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MailConfigClass {
|
||||||
|
private HashMap<String, ArrayList<String>> mailList = new HashMap<String, ArrayList<String>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MailMgr() {
|
||||||
|
System.out.println("Mail manager called");
|
||||||
|
Boolean existingFile = false;
|
||||||
|
try {
|
||||||
|
mailConfig = config.GetJsonObjectFromFile(CONFIG_FILE, MailConfigClass.class);
|
||||||
|
existingFile = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Mail config could not correctly parse json file or it did not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existingFile) {
|
||||||
|
try {
|
||||||
|
config.CreateFile(CONFIG_FILE);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Failed to correctly make or parse mail config file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMail(String playerUuid, String mail) {
|
||||||
|
if (mailConfig != null) {
|
||||||
|
if (mailConfig.mailList.containsKey(playerUuid)) {
|
||||||
|
mailConfig.mailList.get(playerUuid).add(mail);
|
||||||
|
} else {
|
||||||
|
mailConfig.mailList.put(playerUuid, new ArrayList<>(Arrays.asList(mail)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("Mail config is null. Cannot send");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> GetMail(String playerUuid) {
|
||||||
|
List<String> mail = null;
|
||||||
|
if (mailConfig.mailList.containsKey(playerUuid)) {
|
||||||
|
mail = mailConfig.mailList.get(playerUuid);
|
||||||
|
}
|
||||||
|
return mail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearMail(String playerUuid) {
|
||||||
|
if (mailConfig != null && mailConfig.mailList.containsKey(playerUuid)) {
|
||||||
|
mailConfig.mailList.remove(playerUuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FlashConfig() {
|
||||||
|
if (mailConfig != null) {
|
||||||
|
try {
|
||||||
|
config.WriteToJsonFile(CONFIG_FILE, mailConfig);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Could not flash mail config");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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,27 @@
|
|||||||
|
package jesse.keeblarcraft.Utils.CommonStructures;
|
||||||
|
|
||||||
|
public class Pair<KEY, VALUE> {
|
||||||
|
KEY key;
|
||||||
|
VALUE value;
|
||||||
|
|
||||||
|
public Pair(KEY key, VALUE val) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KEY GetKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VALUE GetValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetKey(KEY newKey) {
|
||||||
|
this.key = newKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetValue(VALUE newValue) {
|
||||||
|
this.value = newValue;
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,19 @@ public class Position3d {
|
|||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
boolean isEqual = false;
|
||||||
|
if (this == obj) {
|
||||||
|
isEqual = true;
|
||||||
|
} else if (obj instanceof Position3d castedObj) {
|
||||||
|
if (castedObj.x == this.x && castedObj.y == this.y && castedObj.z == this.z) {
|
||||||
|
isEqual = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isEqual;
|
||||||
|
}
|
||||||
|
|
||||||
public int x;
|
public int x;
|
||||||
public int y;
|
public int y;
|
||||||
public int z;
|
public int z;
|
||||||
|
21
src/main/java/jesse/keeblarcraft/Utils/CustomSlot.java
Normal file
21
src/main/java/jesse/keeblarcraft/Utils/CustomSlot.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package jesse.keeblarcraft.Utils;
|
||||||
|
|
||||||
|
import net.minecraft.inventory.Inventory;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
|
||||||
|
public class CustomSlot extends Slot {
|
||||||
|
private boolean slotIsEnabled = false;
|
||||||
|
|
||||||
|
public CustomSlot(Inventory inventory, int index, int x, int y) {
|
||||||
|
super(inventory, index, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return slotIsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean value) {
|
||||||
|
this.slotIsEnabled = value;
|
||||||
|
}
|
||||||
|
}
|
20
src/main/java/jesse/keeblarcraft/Utils/DirectionalVec.java
Normal file
20
src/main/java/jesse/keeblarcraft/Utils/DirectionalVec.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package jesse.keeblarcraft.Utils;
|
||||||
|
|
||||||
|
import net.minecraft.registry.RegistryKey;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @class DirectionalVec
|
||||||
|
///
|
||||||
|
/// @brief DirectionalVec creates a vector of information that can store
|
||||||
|
/// world information and a players vector information of where they
|
||||||
|
/// are in the world + where their camera is looking (yaw & pitch)
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public class DirectionalVec {
|
||||||
|
public RegistryKey<World> world;
|
||||||
|
public double x;
|
||||||
|
public double y;
|
||||||
|
public double z;
|
||||||
|
public float yaw;
|
||||||
|
public float pitch;
|
||||||
|
}
|
26
src/main/java/jesse/keeblarcraft/Utils/PlayerChecks.java
Normal file
26
src/main/java/jesse/keeblarcraft/Utils/PlayerChecks.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package jesse.keeblarcraft.Utils;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
|
||||||
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public class PlayerChecks {
|
||||||
|
public static Boolean HasPermission(CommandContext<ServerCommandSource> context) {
|
||||||
|
if (context.getSource().isExecutedByPlayer() && HasPermission(context.getSource().getPlayer())) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean HasPermission(ServerPlayerEntity player) {
|
||||||
|
if (player.hasPermissionLevel(4)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("You do not have permission to use this command."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,9 +14,8 @@ import java.util.List;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
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;
|
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:
|
// Singleton class is designed to help the mod set itself up and create all the important things. It does two things:
|
||||||
@ -31,9 +30,7 @@ import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
|
|||||||
public final class Setup {
|
public final class Setup {
|
||||||
private static Setup static_inst;
|
private static Setup static_inst;
|
||||||
|
|
||||||
public Setup() {
|
public Setup() {}
|
||||||
System.out.println(ChatUtil.ColoredString("Running system setup and checks...", CONSOLE_COLOR.BLUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the singleton object
|
// Returns the singleton object
|
||||||
public static Setup GetInstance() {
|
public static Setup GetInstance() {
|
||||||
@ -57,6 +54,7 @@ public final class Setup {
|
|||||||
add("events"); // Expect 1 file per event that is configurable!
|
add("events"); // Expect 1 file per event that is configurable!
|
||||||
add("bank");
|
add("bank");
|
||||||
add("attributes");
|
add("attributes");
|
||||||
|
add("misc");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// These will be top-level config files above the directories this mod creates
|
// These will be top-level config files above the directories this mod creates
|
||||||
@ -77,45 +75,32 @@ public final class Setup {
|
|||||||
ConfigManager conf = new ConfigManager();
|
ConfigManager conf = new ConfigManager();
|
||||||
|
|
||||||
// Create directory check
|
// Create directory check
|
||||||
try {
|
has_write = conf.CreateDirectory("test_dir");
|
||||||
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) {
|
||||||
if (has_write) {
|
Keeblarcraft.LOGGER.error("Uh oh! It appears we could not successfully identify that we have write permissions. Attempt to create a directory failed.");
|
||||||
try {
|
} else {
|
||||||
has_write = conf.CreateFile("test_dir/test_note.txt");
|
has_write = conf.CreateFile("test_dir/test_note.txt");
|
||||||
has_write = conf.WriteToFile("test_dir/test_note.txt", "test_write_read", "w");
|
has_write = conf.WriteToFile("test_dir/test_note.txt", "test_write_read", "w");
|
||||||
|
|
||||||
List<String> lines = conf.GetFile("test_dir/test_note.txt");
|
List<String> lines = conf.GetFileLines("test_dir/test_note.txt");
|
||||||
if (lines.size() == 0) {
|
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;
|
has_read = false;
|
||||||
|
} else {
|
||||||
|
has_read = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
has_write = conf.DeleteFile("test_dir/test_note.txt");
|
||||||
|
has_write = conf.DeleteDirectory("test_dir");
|
||||||
|
|
||||||
|
if (!has_write) {
|
||||||
|
Keeblarcraft.LOGGER.error("Uh oh! It appears we lost the ability to write or delete files after making one. Something is seriously wrong!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete directory if created (it's a temporary dir)
|
Keeblarcraft.LOGGER.debug("CHECKS DEBUG: Value of has_write: "+has_write.toString()+". Value of has_read: "+has_read.toString());
|
||||||
if (has_write) {
|
// return has_write && has_read;
|
||||||
try {
|
return true; /// TODO: ConfigManager has been rewritten so much that the above code is out dated. Fix later return true for now
|
||||||
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
|
// RunSetup
|
||||||
@ -132,9 +117,9 @@ public final class Setup {
|
|||||||
for (Integer i = 0; i < DIRECTORY_LIST.size(); i++) {
|
for (Integer i = 0; i < DIRECTORY_LIST.size(); i++) {
|
||||||
if ( ! conf.DoesDirectoryExist(DIRECTORY_LIST.get(i))) {
|
if ( ! conf.DoesDirectoryExist(DIRECTORY_LIST.get(i))) {
|
||||||
conf.CreateDirectory(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));
|
Keeblarcraft.LOGGER.debug("Creating directory " + DIRECTORY_LIST.get(i));
|
||||||
} else {
|
} else {
|
||||||
System.out.println(ChatUtil.ColoredString("Directory ", CONSOLE_COLOR.BLUE) + conf.DoesDirectoryExist(DIRECTORY_LIST.get(i)) + ChatUtil.ColoredString(" already exists. Skipping... ", CONSOLE_COLOR.BLUE));
|
Keeblarcraft.LOGGER.debug(DIRECTORY_LIST.get(i) + " already exists. Skipping creation.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,20 +127,20 @@ public final class Setup {
|
|||||||
for (Integer i = 0; i < FILE_LIST.size(); i++) {
|
for (Integer i = 0; i < FILE_LIST.size(); i++) {
|
||||||
if ( ! conf.DoesFileExist(FILE_LIST.get(i))) {
|
if ( ! conf.DoesFileExist(FILE_LIST.get(i))) {
|
||||||
conf.CreateFile(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));
|
Keeblarcraft.LOGGER.debug("Creating file " + DIRECTORY_LIST.get(i));
|
||||||
} else {
|
} else {
|
||||||
System.out.println(ChatUtil.ColoredString("File ", CONSOLE_COLOR.BLUE) + conf.DoesDirectoryExist(FILE_LIST.get(i)) + ChatUtil.ColoredString(" already exists. Skipping...", CONSOLE_COLOR.BLUE));
|
Keeblarcraft.LOGGER.debug(DIRECTORY_LIST.get(i) + " already exists. Skipping creation.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new SETUP_FAILED_EXCEPTION();
|
throw new SETUP_FAILED_EXCEPTION();
|
||||||
}
|
}
|
||||||
} else {
|
} 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));
|
Keeblarcraft.LOGGER.error("The setup phase failed in its processing and has determined it does not have necessary read or write priviliges in this hosted area and will now exit.");
|
||||||
throw new SETUP_FAILED_EXCEPTION();
|
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)));
|
Keeblarcraft.LOGGER.debug("DID SETUP COMPLETE SUCCESSFULLY? " + (ret ? "YES":"NO"));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package jesse.keeblarcraft.datagen;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.CustomBlocks.BlockManager;
|
||||||
|
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
|
||||||
|
import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider;
|
||||||
|
import net.minecraft.data.client.BlockStateModelGenerator;
|
||||||
|
import net.minecraft.data.client.ItemModelGenerator;
|
||||||
|
|
||||||
|
public class KeeblarModelProvider extends FabricModelProvider {
|
||||||
|
|
||||||
|
public KeeblarModelProvider(FabricDataOutput output) {
|
||||||
|
super(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) {
|
||||||
|
blockStateModelGenerator.registerSimpleState(BlockManager.GetBlock("faction_base_block"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateItemModels(ItemModelGenerator itemModelGenerator) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/main/java/jesse/keeblarcraft/datagen/WorldGenerator.java
Normal file
28
src/main/java/jesse/keeblarcraft/datagen/WorldGenerator.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package jesse.keeblarcraft.datagen;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
|
||||||
|
import net.fabricmc.fabric.api.datagen.v1.provider.FabricDynamicRegistryProvider;
|
||||||
|
import net.minecraft.registry.RegistryKeys;
|
||||||
|
import net.minecraft.registry.RegistryWrapper;
|
||||||
|
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
||||||
|
|
||||||
|
public class WorldGenerator extends FabricDynamicRegistryProvider {
|
||||||
|
|
||||||
|
public WorldGenerator(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFeature) {
|
||||||
|
super(output, registriesFeature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Keeblarcraft World Generation";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(WrapperLookup registries, Entries entries) {
|
||||||
|
entries.addAll(registries.getWrapperOrThrow(RegistryKeys.PLACED_FEATURE));
|
||||||
|
entries.addAll(registries.getWrapperOrThrow(RegistryKeys.BIOME));
|
||||||
|
entries.addAll(registries.getWrapperOrThrow(RegistryKeys.DIMENSION_TYPE));
|
||||||
|
}
|
||||||
|
}
|
31
src/main/java/jesse/keeblarcraft/mixin/EntitySpawnMixin.java
Normal file
31
src/main/java/jesse/keeblarcraft/mixin/EntitySpawnMixin.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package jesse.keeblarcraft.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.ModifyReceiver;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Callbacks.MobSpawnCallback;
|
||||||
|
import net.minecraft.entity.EntityData;
|
||||||
|
import net.minecraft.entity.SpawnReason;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.world.LocalDifficulty;
|
||||||
|
import net.minecraft.world.ServerWorldAccess;
|
||||||
|
import net.minecraft.world.SpawnHelper;
|
||||||
|
|
||||||
|
@Mixin(SpawnHelper.class)
|
||||||
|
public class EntitySpawnMixin {
|
||||||
|
@ModifyReceiver(
|
||||||
|
method = "spawnEntitiesInChunk(Lnet/minecraft/entity/SpawnGroup;Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/Chunk;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/SpawnHelper$Checker;Lnet/minecraft/world/SpawnHelper$Runner;)V",
|
||||||
|
at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/mob/MobEntity;initialize(Lnet/minecraft/world/ServerWorldAccess;Lnet/minecraft/world/LocalDifficulty;Lnet/minecraft/entity/SpawnReason;Lnet/minecraft/entity/EntityData;Lnet/minecraft/nbt/NbtCompound;)Lnet/minecraft/entity/EntityData;")
|
||||||
|
)
|
||||||
|
private static MobEntity mobEntity(MobEntity instance, ServerWorldAccess world, LocalDifficulty difficulty, SpawnReason spawnReason, EntityData entityData, NbtCompound entityNbt) {
|
||||||
|
// Do stuff
|
||||||
|
ActionResult action = MobSpawnCallback.EVENT.invoker().interact(instance.getWorld(), instance);
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user