Compare commits

...

128 commits

Author SHA1 Message Date
c3d9096e63 Merge the 1.19 changes into the 1.20 codebase 2024-02-13 22:43:36 -07:00
c5637d7c44 Finish fixing multiple clicks being handled 2024-01-15 00:46:43 -07:00
bef8f89f97 Attempt to fix multiple clicks being triggered in chestgui 2024-01-15 00:38:37 -07:00
d773f34376 Attempt to fix multiple clicks being triggered in chestgui 2024-01-15 00:24:08 -07:00
5372fd2129 Update credits command to use new callback args 2024-01-14 19:52:41 -07:00
a4f66468ee Adds the lore container to the callback 2024-01-14 19:51:47 -07:00
2e0dce868b Fix compile error 2024-01-14 19:20:53 -07:00
66a7c382cd Add some javadoc, add container to callback 2024-01-14 19:18:59 -07:00
c6954add09 Add an API Helper to ChestGUI to allow inplace updating of the stack that was clicked. 2024-01-14 19:11:38 -07:00
95405f9e5a Adds a block imitator 2024-01-12 21:10:13 -07:00
46c7478aa7 Fix ChestGUIButton name 2024-01-12 21:10:03 -07:00
898a9b37f0 Fix utility buttons not being added properly 2024-01-10 03:13:59 -07:00
ee0c98ee51 Fix compile error 2024-01-10 02:01:26 -07:00
6b030a8116 Migrate to using a new identifier for chest gui 2024-01-10 01:26:13 -07:00
ac69c828a4 Fix index problem for chestGUI 2024-01-10 01:25:57 -07:00
b2a2c60dfd Fix chestgui 2024-01-10 00:11:20 -07:00
c633a1f52e Fixes a minor typo 2024-01-09 14:44:44 -07:00
2c12935250 Add a playerIsOp helper function to ServerUtilities 2024-01-09 14:21:40 -07:00
9cbdc6a9c1 Update version number 2024-01-09 03:29:48 -07:00
adceccc275 Send out a packet when the server is available to libzontreck 2024-01-09 03:28:59 -07:00
c8136451e0 ADD: Multipage chestgui support, javadoc 2024-01-09 03:14:14 -07:00
e1c522e7a1 Attempt to fix the Profiles unloading immediately on first join 2024-01-08 17:28:47 -07:00
5ad671cc73 Update repository 2024-01-07 17:37:53 -07:00
73481f0818 Update repository infos 2024-01-07 16:39:55 -07:00
0e50bb031d Allow overriding the head item name 2024-01-02 19:45:51 -07:00
8f550510a6 Allow overriding the head item name 2024-01-02 19:45:31 -07:00
b9150379dc Allow overriding the head item name 2024-01-02 19:43:26 -07:00
e1f79b6af7 Chest GUI add builder with name function 2024-01-02 19:11:48 -07:00
0fb37b1633 Chest GUI API now completed 2024-01-02 17:59:10 -07:00
01a6f1ddc7 Get the menu working, button click broken 2024-01-02 03:36:08 -07:00
848b6f495b Finish implementing initial chest-gui interface API 2024-01-02 00:28:17 -07:00
b034b2b388 Add vector 2i 2023-12-31 22:09:28 -07:00
409f6d407b Initial implementation of chest gui 2023-12-31 21:58:41 -07:00
a8048391a0 Start adding a chest gui system 2023-12-31 05:24:21 -07:00
d237912942 Attempt to fix profiles unloading while a player is still logged on 2023-12-21 16:11:07 -07:00
9edb1f40fe Add a public NBT data field for misc data retrieval and storage outside the Profile Load/Save events 2023-12-20 16:13:10 -07:00
8fdc29d4ea Adjust the profile obtaining command 2023-12-19 15:20:12 -07:00
19d99091b7 Add a handler in the case that the player instance is null in Profile 2023-12-19 11:06:01 -07:00
fdacdeb641 Update build version.... 2023-12-18 13:18:47 -07:00
19b348179a Update bundled LibAC version 2023-12-18 13:17:21 -07:00
815426607e Do internal updates 2023-12-14 22:11:54 -07:00
79ae46c505 Dependencies were not being saved in the 1.20 jar file in a embedded way 2023-11-19 06:46:51 -07:00
e2ef0a02f6 Add minecraft version to the library version string 2023-11-19 06:22:38 -07:00
d04e184b2b Updates libz mod version 2023-11-19 05:13:53 -07:00
29814e35b1 Fix a mod crash 2023-11-19 05:12:23 -07:00
cd2a48bdfb Finish updating to 1.20.1 2023-11-19 02:53:32 -07:00
46815aeb78 Update more to 1.20 2023-11-19 02:37:33 -07:00
f3b1ccbd3a Update to 1.20.1 2023-11-19 02:10:20 -07:00
0066b86d18 Update plugins maven reference to cache plugins 2023-07-30 14:26:47 -07:00
2eae027800 Update libac and maven details 2023-07-30 14:06:43 -07:00
d403b5981e Fix mods.toml 2023-05-15 21:34:59 -07:00
a5d69a1730 Update libac version
Update libz version
2023-05-15 21:28:38 -07:00
bddc923eca Update libac version
Update libz version
2023-05-06 03:41:51 -07:00
857d8eaf4a Ensure the system account is available, and has sufficient funds! 2023-04-22 06:31:28 -07:00
2d0504fec6 Alter return types of ChatHelpers to be MutableComponent 2023-04-22 04:51:02 -07:00
60517bfdf6 Adds some API calls to ChatHelpers
+ applyClickEvent
+ applyHoverEvent
2023-04-22 04:15:21 -07:00
c3590db1d8 Include LibAC in dev jar also 2023-04-22 03:23:19 -07:00
b6edb0b6d1 Comment out parchment librarian 2023-04-21 19:06:17 -07:00
445213ce8d Comment out parchment maven 2023-04-21 19:05:13 -07:00
8d99d0eec9 Build number update 2023-04-21 18:19:04 -07:00
a4916e0ac2 Remove leftover luckperms jars from libs folder 2023-04-21 18:18:11 -07:00
e8cb062534 Update jar version 2023-04-21 17:45:26 -07:00
1842387ec8 Add a custom currency API 2023-04-21 17:44:33 -07:00
c6ff1afbdc Upgrade back to 1.19.4
Increment API version
+ LibAC
- Lightmans Currency
- Parchment (Temporary)
2023-04-21 03:44:40 -07:00
00ea4681d8 Add dependency: LibAC
Remove compatibility with luckperms
2023-04-20 22:27:07 -07:00
5d024f425c Update major API Version to add some new interfaces. 2023-03-18 21:01:18 -07:00
1378a6fb21 Publish update to libzontreck with fixed version number 2023-03-06 01:55:47 -07:00
ede19b0572 Create a new event and add a few fields to existing events 2023-03-05 15:53:56 -07:00
957b65ebb3 Add a contributing guideline document 2023-03-05 15:38:53 -07:00
1994dc1a37 Fix compile error, remove head command 2023-03-02 17:59:58 -07:00
a989d1fe65 Temporarily remove the dynamic gui system until i have the energy to properly implement it 2023-03-02 17:49:07 -07:00
be1f961175 Finish implementing heads 2023-03-01 12:30:00 -07:00
1e2186d62d Finish implementing credits. 2023-03-01 12:29:53 -07:00
8fde794b65 Begin adding DynamicChest UI, and finish adding the HeadUtilities 2023-03-01 02:19:47 -07:00
5c70fb1291 Add a chat replacement helper 2023-02-28 09:26:46 -07:00
902cca2f42 convert tasks in delayed executor to utilize Timer 2023-02-28 08:33:28 -07:00
d94bb8e775 Fix delayed executor service 2023-02-28 07:59:58 -07:00
bc67d96382 Publish a fix to DelayedExecutor 2023-02-28 00:04:42 -07:00
a46ec5ec73 Mark logged in event as final, add logout event 2023-02-27 23:05:46 -07:00
579b6ca344 Attempt to improve profile unloading in singleplayer 2023-02-27 22:50:01 -07:00
e50238e37e Make a change to profile file extension 2023-02-27 22:16:56 -07:00
1d04b3eee7 Roll back fix 2023-02-27 22:06:56 -07:00
04ab8f8a11 Test fix for ClassDefNotFound 2023-02-27 21:43:50 -07:00
1095e3ce3d Fix invalid player data crash 2023-02-27 21:30:08 -07:00
e771155a2b Attempt to fix the directory issue again 2023-02-27 18:13:36 -07:00
ba007edb67 Attempt to fix again profiles not resolving 2023-02-27 17:45:43 -07:00
f43c5ba72b Fix folders not being generated 2023-02-27 17:31:20 -07:00
bc5b7bceee Try to fix the datastore not getting initialized 2023-02-27 17:25:01 -07:00
7df8d0e0b3 Fix a crash in libzontreck 2023-02-27 17:06:07 -07:00
fefb02bc8d Add chat helpers to libzontreck 2023-02-27 15:38:14 -07:00
6789b0f329 Move profiles into libzontreck, and create relevant events 2023-02-27 14:41:33 -07:00
453d5642b7 Move delayed executor and file tree system 2023-02-27 14:09:28 -07:00
b92a261c2c Add delayed executor service to libzontreck, moving it out of OTEMod 2023-02-27 14:03:41 -07:00
de6486ec44 Bugfix attempt #2 2023-02-22 20:36:54 -07:00
87ed217b97 Bugfix attempt: Try-catch in itemutils 2023-02-22 20:29:47 -07:00
e711ba6a2e Bugfix: Rollback clientlevel support 2023-02-22 20:19:26 -07:00
116e2d92e1 Deploy some new helper functions in the API 2023-02-22 03:52:00 -07:00
954642b922 Finalize mod downgrade to 1.18.2 2023-02-22 02:15:57 -07:00
7657509044 Downgrade to 1.18.2 2023-02-22 01:40:15 -07:00
48a4e126cb Stage changes pre-downgrade to 1.18.2 2023-02-22 01:33:03 -07:00
bd9a99e78e Publish a helper function to the API 2023-02-22 01:23:33 -07:00
7e5c273f4d Publish changes to Library API 2023-02-22 01:22:00 -07:00
b01d45f9ab Track player position for a custom event 2023-02-16 07:56:00 -07:00
4eee51709c Add a middle chunk position to the chunk pos interface 2023-02-14 10:47:03 -07:00
cf2f0a165b Make worldposition's helper return a global chunkpos not subarea 2023-02-14 10:11:13 -07:00
9636519147 Add a method to world position to get chunk position using minecraft positions 2023-02-14 10:06:37 -07:00
f911d4e9d2 Add new APIs to the vector system 2023-02-14 08:46:52 -07:00
8bfa308ba5 Set executable 2023-02-14 08:00:48 -07:00
621419a4b3 Make executable 2023-02-01 19:37:54 -07:00
65b3fc3e6d Serialize Json manually because... javax is apparently inaccessible in minecraft's classpath 2023-01-22 13:17:05 -07:00
41c98e8c3d Fix version number, push update to API version 2023-01-22 03:20:52 -07:00
9b67ed8d61 Add minecraft version as prefix to library version 2023-01-21 22:58:13 -07:00
608e17b34c Fix a small little typo 2023-01-21 22:54:57 -07:00
629a8a8bb8 Add the missing LoreContainer#Save function 2023-01-21 19:45:47 -07:00
20f405a809 Add some extra code statements as NBT was not updating properly 2023-01-21 19:41:10 -07:00
8f475afc9f Fix a index out of bounds error 2023-01-21 19:33:32 -07:00
de66f0b7ca Add lore manipulation helpers 2023-01-21 18:20:28 -07:00
78b5a5f790 Add a method for generating a list of every vector3 2023-01-07 21:47:58 -07:00
5fe283f745 Fix a crash in obtaining the file safe dimname 2023-01-07 18:10:48 -07:00
83a2bff15b Add an extra property to WorldPosition 2023-01-07 17:37:20 -07:00
7f2dca58d1 Downgrade to 1.19.2 2023-01-06 23:01:30 -07:00
1d7c89fb29 Release 1.19.3 version 2023-01-03 21:00:03 -07:00
a093a65f60 Begin retargetting to 1.19.3 2023-01-03 20:30:57 -07:00
14f9afb95e Revert forge version 2022-10-18 00:30:33 -07:00
4d25c900bb Update version to 1.0.1.1 2022-10-17 23:46:20 -07:00
51043006b5 1.0.1.0 Move more common code from OTEMod into this library 2022-10-17 05:33:33 -07:00
fa3961d85b Also allow lowercase 2022-10-13 19:43:39 -07:00
c3ed34322d Publish 1.0.0.2 to add reset to the chat color parser 2022-10-13 19:08:49 -07:00
112 changed files with 5527 additions and 187 deletions

1
.gitignore vendored
View file

@ -20,6 +20,7 @@ build
# other
eclipse
run
runServer
# Files from Forge MDK
forge*changelog.txt

28
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,28 @@
How to Contribute
=====
First of all, thank you for considering, or for contributing to any of the following mods
```
LibZontreck
Arias-Essentials
OTEMod
ClaimsMod
WatchMyDurability
```
It's people like you who make the contrinuted existence of these mods possible.
Contributing to any of the mods under my development is simple.
Code Contributions
---
1) To contribute code, fork the repository, then make a new branch. Name it something like `bugfix_somefeature`, or `feature_newfeature`. When done coding, submit a pull request to have your changes be integrated upstream.
Asset contribution
----
2) Contributions are also accepted in the form of artwork or music, or sound, or block models from blockbench. Just simply follow the above steps to create your working base. Then send it to us in a pull request. No coding knowledge is necessary for adding these resources. Someone else can tackle that if you do not know how to code. An example of this is the Possum animal model in OTEMod. This was contributed by PossumTheWarrior via discord.
Bug reporting or feature requests
----
3) Bug reports. Please be as detailed as possible when reporting a bug. Include steps on how to reproduce the bug if possible.
4) Feature requests. Please be sure to name your issue ticket accordingly to indicate you are requesting a new feature, and not reporting a bug. Then be as detailed as possible in how you want the feature to work. If the feature is requested for LibZontreck. Please be detailed in how the API would work. You can do this simply by providing a basic interface example.

15
README.md Normal file
View file

@ -0,0 +1,15 @@
LibZontreck
=======
This is a library mod for all of zontreck's mods. Also known as Aria.
The library can be used freely by other modders, but with the understanding that I may change something with little to no notice.
If the mod becomes widely used, I will begin using deprecation notices.
Compatibility
=====
1) Lightman's Currency

View file

@ -1,46 +0,0 @@
Source installation information for modders
-------------------------------------------
This code follows the Minecraft Forge installation methodology. It will apply
some small patches to the vanilla MCP source code, giving you and it access
to some of the data and functions you need to build a successful mod.
Note also that the patches are built against "un-renamed" MCP source code (aka
SRG Names) - this means that you will not be able to read them directly against
normal code.
Setup Process:
==============================
Step 1: Open your command-line and browse to the folder where you extracted the zip file.
Step 2: You're left with a choice.
If you prefer to use Eclipse:
1. Run the following command: `gradlew genEclipseRuns` (`./gradlew genEclipseRuns` if you are on Mac/Linux)
2. Open Eclipse, Import > Existing Gradle Project > Select Folder
or run `gradlew eclipse` to generate the project.
If you prefer to use IntelliJ:
1. Open IDEA, and import project.
2. Select your build.gradle file and have it import.
3. Run the following command: `gradlew genIntellijRuns` (`./gradlew genIntellijRuns` if you are on Mac/Linux)
4. Refresh the Gradle Project in IDEA if required.
If at any point you are missing libraries in your IDE, or you've run into problems you can
run `gradlew --refresh-dependencies` to refresh the local cache. `gradlew clean` to reset everything
{this does not affect your code} and then start the process again.
Mapping Names:
=============================
By default, the MDK is configured to use the official mapping names from Mojang for methods and fields
in the Minecraft codebase. These names are covered by a specific license. All modders should be aware of this
license, if you do not agree with it you can change your mapping names to other crowdsourced names in your
build.gradle. For the latest license text, refer to the mapping file itself, or the reference copy here:
https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
Additional Resources:
=========================
Community Documentation: https://mcforge.readthedocs.io/en/latest/gettingstarted/
LexManos' Install Video: https://www.youtube.com/watch?v=8VEdtQLuLO0
Forge Forum: https://forums.minecraftforge.net/
Forge Discord: https://discord.gg/UvedJ9m

View file

@ -1,12 +1,29 @@
plugins {
id 'eclipse'
id 'idea'
id 'maven-publish'
id 'net.minecraftforge.gradle' version '5.1.+'
id 'java-library'
id 'net.minecraftforge.gradle' version '[6.0,6.2)'
id 'org.parchmentmc.librarian.forgegradle' version '1.+'
}
version = "${myversion}"
group = 'dev.zontreck' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'libzontreck'
version = mod_version
group = mod_group_id
base {
archivesName = mod_id
}
java {
withSourcesJar()
withJavadocJar()
}
configurations {
provided
compile.extendsFrom(provided)
}
// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17.
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
@ -22,18 +39,40 @@ minecraft {
// See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
//
// Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge
// Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started
// Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started
//
// Use non-default mappings at your own risk. They may not always work.
// Simply re-run your setup task after changing the mappings to update your workspace.
mappings channel: 'official', version: "${mc_version}"
mappings channel: mapping_channel, version: mapping_version
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default.
// When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game.
// In most cases, it is not necessary to enable.
// enableEclipsePrepareRuns = true
// enableIdeaPrepareRuns = true
// This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game.
// It is REQUIRED to be set to true for this template to function.
// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html
copyIdeResources = true
// When true, this property will add the folder name of all declared run configurations to generated IDE run configurations.
// The folder name can be set on a run configuration using the "folderName" property.
// By default, the folder name of a run configuration is the name of the Gradle project containing it.
// generateRunFolders = true
// This property enables access transformers for use in development.
// They will be applied to the Minecraft artifact.
// The access transformer file can be anywhere in the project.
// However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge.
// This default location is a best practice to automatically put the file in the right place in the final jar.
// See https://docs.minecraftforge.net/en/latest/advanced/accesstransformers/ for more information.
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs {
client {
// applies to all the run configs below
configureEach {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
@ -48,66 +87,36 @@ minecraft {
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', 'libzontreck'
mods {
libzontreck {
"${mod_id}" {
source sourceSets.main
}
}
}
client {
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', mod_id
}
server {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
property 'forge.enabledGameTestNamespaces', 'libzontreck'
mods {
libzontreck {
source sourceSets.main
}
}
property 'forge.enabledGameTestNamespaces', mod_id
args '--nogui'
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
property 'forge.enabledGameTestNamespaces', 'libzontreck'
mods {
libzontreck {
source sourceSets.main
}
}
property 'forge.enabledGameTestNamespaces', mod_id
}
data {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
// example of overriding the workingDirectory set in configureEach above
workingDirectory project.file('run-data')
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', 'libzontreck', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
mods {
libzontreck {
source sourceSets.main
}
}
args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
}
}
}
@ -116,85 +125,131 @@ minecraft {
sourceSets.main.resources { srcDir 'src/generated/resources' }
repositories {
//mavenCentral()
maven {
name = "Aria's Creations Caches"
url = "https://maven.zontreck.com/repository/internal"
}
// Put repositories for dependencies here
// ForgeGradle automatically adds the Forge maven and Maven Central for you
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so:
// flatDir {
// dir 'libs'
// }
flatDir {
dir 'libs'
}
//maven {
// name = "CurseMaven"
// url = "https://cursemaven.com"
//}
maven {
name = "zontreck Maven"
url = "https://maven.zontreck.com/repository/zontreck"
}
}
dependencies {
// Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed
// that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied.
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
// Specify the version of Minecraft to use.
// Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact.
// The "userdev" classifier will be requested and setup by ForgeGradle.
// If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"],
// then special handling is done to allow a setup of a vanilla dependency without the use of an external repository.
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
// Real mod deobf dependency examples - these get remapped to your current mappings
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency
// runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency
// implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency
provided "dev.zontreck:LibAC:${libac}"
implementation "dev.zontreck:LibAC:${libac}"
minecraftLibrary "dev.zontreck:LibAC:${libac}"
// Examples using mod jars from ./libs
provided "dev.zontreck:EventsBus:${eventsbus}"
implementation "dev.zontreck:EventsBus:${eventsbus}"
minecraftLibrary "dev.zontreck:EventsBus:${eventsbus}"
// Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}")
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}")
// runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}")
// Example mod dependency using a mod jar from ./libs with a flat dir repository
// This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar
// The group id is ignored when searching -- in this case, it is "blank"
// implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}")
// For more info...
// For more info:
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html
}
// This block of code expands all declared replace properties in the specified resource targets.
// A missing property will result in an error. Properties are expanded using ${} Groovy notation.
// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments.
// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html
tasks.named('processResources', ProcessResources).configure {
var replaceProperties = [
minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range,
forge_version : forge_version, forge_version_range: forge_version_range,
loader_version_range: loader_version_range,
mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version,
mod_authors : mod_authors, mod_description: mod_description,
]
inputs.properties replaceProperties
filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) {
expand replaceProperties + [project: project]
}
}
// Example for how to get properties into the manifest for reading at runtime.
jar {
tasks.named('jar', Jar).configure {
from {
configurations.provided.asFileTree.collect{zipTree(it)}
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes([
"Specification-Title" : project.name,
"Specification-Vendor" : "zontreck",
"Specification-Version" : "1", // We are version 1 of ourselves
"Implementation-Title" : project.name,
"Implementation-Version" : project.jar.archiveVersion,
"Implementation-Vendor" : "zontreck",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
'Specification-Title' : mod_id,
'Specification-Vendor' : mod_authors,
'Specification-Version' : '1', // We are version 1 of ourselves
'Implementation-Title' : project.name,
'Implementation-Version' : project.jar.archiveVersion,
'Implementation-Vendor' : mod_authors,
'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
}
// This is the preferred method to reobfuscate your jar file
finalizedBy 'reobfJar'
}
// Example configuration to allow publishing using the maven-publish plugin
// This is the preferred method to reobfuscate your jar file
jar.finalizedBy('reobfJar')
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
// publish.dependsOn('reobfJar')
task devJar(type: Jar) {
from sourceSets.main.output
from sourceSets.main.allJava
classifier = 'dev'
manifest {
attributes([
"Specification-Title": project.name,
"Specification-Vendor": "zontreck",
"Specification-Version": "1",
"Implementation-Title": project.name,
"Implementation-Version": project.jar.archiveVersion,
"Implementation-Vendor": "zontreck",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
}
}
devJar.finalizedBy('reobfJar')
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing:
// tasks.named('publish').configure {
// dependsOn 'reobfJar'
// }
def MAVEN_PASSWORD_PROPERTY = "AriasCreationsMavenPassword"
publishing {
publications {
mavenJava(MavenPublication) {
artifact jar
artifact devJar
artifact sourcesJar
artifact javadocJar
}
}
repositories {
maven {
url "file://${project.projectDir}/mcmodsrepo"
url = "https://maven.zontreck.com/repository/zontreck"
name = "ariascreations"
if (project.findProperty(MAVEN_PASSWORD_PROPERTY) != null) {
credentials {
username = "admin"
password = project.findProperty(MAVEN_PASSWORD_PROPERTY)
}
}
}
}
}

View file

@ -3,6 +3,62 @@
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
mc_version=1.19.2
forge_version=43.1.16
myversion=1.0.0.1
parchment_version=2023.09.03
# luckperms_api_version=5.4
libac=1.4.46
eventsbus=1.0.45
## Environment Properties
# The Minecraft version must agree with the Forge version to get a valid artifact
minecraft_version=1.20.1
# The Minecraft version range can use any release version of Minecraft as bounds.
# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly
# as they do not follow standard versioning conventions.
minecraft_version_range=[1.20.1,1.21)
# The Forge version must agree with the Minecraft version to get a valid artifact
forge_version=47.2.0
# The Forge version range can use any version of Forge as bounds or match the loader version range
forge_version_range=[47,)
# The loader version range can only use the major version of Forge/FML as bounds
loader_version_range=[47,)
# The mapping channel to use for mappings.
# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"].
# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin.
#
# | Channel | Version | |
# |-----------|----------------------|--------------------------------------------------------------------------------|
# | official | MCVersion | Official field/method names from Mojang mapping files |
# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official |
#
# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings.
# See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
#
# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge.
# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started
mapping_channel=parchment
# The mapping version to query from the mapping channel.
# This must match the format required by the mapping channel.
mapping_version=2023.09.03-1.20.1
## Mod Properties
# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}
# Must match the String constant located in the main mod class annotated with @Mod.
mod_id=libzontreck
# The human-readable display name for the mod.
mod_name=Zontreck Library Mod
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=GPLv3
# The mod version. See https://semver.org/
mod_version=1.10.021324.2257
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
mod_group_id=dev.zontreck
# The authors of the mod. This is a simple text string that is used for display purposes in the mod list.
mod_authors=zontreck
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.
mod_description=LibZontreck\nLibrary Mod!

Binary file not shown.

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

12
gradlew vendored Normal file → Executable file
View file

@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -80,10 +80,10 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
@ -143,12 +143,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac

1
gradlew.bat vendored
View file

@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

0
libs/.placeholder Normal file
View file

View file

@ -1,8 +1,10 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven { url = 'https://maven.minecraftforge.net/' }
maven { url = "https://maven.zontreck.com/repository/internal" }
}
}
rootProject.name = "libzontreck"
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
}

View file

@ -1,17 +1,144 @@
package dev.zontreck.libzontreck;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import dev.zontreck.ariaslib.util.DelayedExecutorService;
import dev.zontreck.eventsbus.Bus;
import dev.zontreck.libzontreck.chestgui.ChestGUIRegistry;
import dev.zontreck.libzontreck.currency.Bank;
import dev.zontreck.libzontreck.currency.CurrencyHelper;
import dev.zontreck.libzontreck.items.ModItems;
import dev.zontreck.libzontreck.menus.ChestGUIScreen;
import dev.zontreck.libzontreck.types.ModMenuTypes;
import dev.zontreck.libzontreck.networking.NetworkEvents;
import net.minecraft.client.gui.screens.MenuScreens;
import org.slf4j.Logger;
import com.mojang.logging.LogUtils;
import dev.zontreck.libzontreck.commands.Commands;
import dev.zontreck.libzontreck.events.ForgeEventHandlers;
import dev.zontreck.libzontreck.memory.VolatilePlayerStorage;
import dev.zontreck.libzontreck.networking.ModMessages;
import dev.zontreck.libzontreck.profiles.Profile;
import dev.zontreck.libzontreck.util.FileTreeDatastore;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.server.ServerStartedEvent;
import net.minecraftforge.event.server.ServerStoppingEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@Mod(LibZontreck.MOD_ID)
public class LibZontreck {
public static final Logger LOGGER = LogUtils.getLogger();
public static final String MOD_ID = "libzontreck";
public static final Map<String, Profile> PROFILES;
public static MinecraftServer THE_SERVER;
public static VolatilePlayerStorage playerStorage;
public static boolean ALIVE=true;
public static final String FILESTORE = FileTreeDatastore.get();
public static final Path BASE_CONFIG;
public static final String PLAYER_INFO_URL = "https://api.mojang.com/users/profiles/minecraft/";
public static final String PLAYER_SKIN_URL = "https://sessionserver.mojang.com/session/minecraft/profile/";
public static final UUID NULL_ID;
public static boolean LIBZONTRECK_SERVER_AVAILABLE=false;
public static LogicalSide CURRENT_SIDE;
static{
NULL_ID = new UUID(0,0);
PROFILES = new HashMap<>();
BASE_CONFIG = FileTreeDatastore.of("libzontreck");
if(!BASE_CONFIG.toFile().exists())
{
try {
Files.createDirectory(BASE_CONFIG);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public LibZontreck(){
LibZontreck.playerStorage=new VolatilePlayerStorage();
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
// Register the setup method for modloading
bus.addListener(this::setup);
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(new ForgeEventHandlers());
MinecraftForge.EVENT_BUS.register(new Commands());
MinecraftForge.EVENT_BUS.register(new NetworkEvents());
MinecraftForge.EVENT_BUS.register(ChestGUIRegistry.class);
Bus.Reset();
ModMenuTypes.REGISTRY.register(bus);
//CreativeModeTabs.register(bus);
ModItems.register(bus);
Bus.Register(CurrencyHelper.class, null);
Bus.Register(Bank.class, null);
}
private void setup(final FMLCommonSetupEvent event)
{
ModMessages.register();
}
@SubscribeEvent
public void onServerStarted(final ServerStartedEvent event)
{
THE_SERVER = event.getServer();
ALIVE=true;
CURRENT_SIDE = LogicalSide.SERVER;
}
@SubscribeEvent
public void onServerStopping(final ServerStoppingEvent ev)
{
ALIVE=false;
DelayedExecutorService.stop();
Iterator<Profile> iProfile = PROFILES.values().iterator();
while(iProfile.hasNext())
{
Profile prof = iProfile.next();
iProfile.remove();
prof=null;
}
}
@Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public static class ClientModEvents
{
@SubscribeEvent
public static void onClientSetup(FMLClientSetupEvent ev) {
LibZontreck.CURRENT_SIDE = LogicalSide.CLIENT;
LibZontreck.ALIVE = false; // Prevents loops on the client that are meant for server tick processing
MenuScreens.register(ModMenuTypes.CHEST_GUI_MENU.get(), ChestGUIScreen::new);
}
}
}

View file

@ -0,0 +1,95 @@
package dev.zontreck.libzontreck.blocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
/**
* Code partially taken from HT's TreeChop
* <p>
* <a href="https://github.com/hammertater/treechop/blob/main/shared/src/main/java/ht/treechop/common/block/BlockImitator.java">Source Material</a>
*/
public abstract class BlockImitation extends Block
{
public BlockImitation(Properties pProperties) {
super(pProperties);
}
public abstract BlockState getImitatedBlockState(BlockGetter level, BlockPos pos);
public abstract void updateImitation(BlockState newState, BlockGetter level, BlockPos pos);
@Override
public void animateTick(BlockState blockState, Level level, BlockPos pos, RandomSource random) {
BlockState imitatedBlockState = getImitatedBlockState(level, pos);
imitatedBlockState.getBlock().animateTick(imitatedBlockState, level, pos, random);
}
@Override
public void stepOn(Level level, BlockPos pos, BlockState blockState, Entity entity) {
BlockState imitatedBlockState = getImitatedBlockState(level, pos);
imitatedBlockState.getBlock().stepOn(level, pos, imitatedBlockState, entity);
}
@Override
public void fallOn(Level level, BlockState blockState, BlockPos pos, Entity entity, float speed) {
BlockState imitatedBlockState = getImitatedBlockState(level, pos);
imitatedBlockState.getBlock().fallOn(level, imitatedBlockState, pos, entity, speed);
}
@Override
public ItemStack getCloneItemStack(BlockGetter level, BlockPos pos, BlockState blockState) {
BlockState imitatedBlockState = getImitatedBlockState(level, pos);
return imitatedBlockState.getBlock().getCloneItemStack(level, pos, imitatedBlockState);
}
@Override
public void handlePrecipitation(BlockState blockState, Level level, BlockPos pos, Biome.Precipitation precipitation) {
BlockState imitatedBlockState = getImitatedBlockState(level, pos);
imitatedBlockState.getBlock().handlePrecipitation(imitatedBlockState, level, pos, precipitation);
}
@Override
public int getLightBlock(BlockState blockState, BlockGetter level, BlockPos pos) {
return super.getLightBlock(blockState, level, pos);
}
@Override
public float getShadeBrightness(BlockState blockState, BlockGetter level, BlockPos pos) {
return super.getShadeBrightness(blockState, level, pos);
}
@Override
public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
return getImitatedBlockState(level, pos).getAnalogOutputSignal(level, pos);
}
@Override
public void randomTick(BlockState blockState, ServerLevel level, BlockPos pos, RandomSource random) {
getImitatedBlockState(level, pos).randomTick(level, pos, random);
}
@Override
public void tick(BlockState blockState, ServerLevel level, BlockPos pos, RandomSource random) {
getImitatedBlockState(level, pos).tick(level, pos, random);
}
@Override
public int getSignal(BlockState blockState, BlockGetter level, BlockPos pos, Direction direction) {
return getImitatedBlockState(level, pos).getSignal(level, pos, direction);
}
@Override
public int getDirectSignal(BlockState blockState, BlockGetter level, BlockPos pos, Direction direction) {
return getImitatedBlockState(level, pos).getDirectSignal(level, pos, direction);
}
}

View file

@ -0,0 +1,25 @@
package dev.zontreck.libzontreck.bossbars;
import net.minecraft.client.Minecraft;
import net.minecraft.server.bossevents.CustomBossEvents;
import net.minecraft.server.commands.BossBarCommands;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
public class BossBarUtils {
public class BossBarStructure
{
public String Header;
public int Percent;
}
public static void sendBossBarToPlayer(Player p, BossBarStructure struc)
{
if(Minecraft.getInstance().level.isClientSide())return;
ServerPlayer sp = (ServerPlayer)p;
if(sp==null)return;
//sp.server.getCustomBossEvents().create(null, null)
}
}

View file

@ -23,7 +23,8 @@ public class ChatColor {
Bold,
Italic,
Strikethrough,
Crazy
Crazy,
Reset
}
public static char CODE = '§';
public static String BLACK = build("0");
@ -55,6 +56,7 @@ public class ChatColor {
{
for(ChatColor.ColorOptions color : ChatColor.ColorOptions.values()){
msg = msg.replace("!"+color.toString()+"!", ChatColor.from(color));
msg = msg.replace("!"+color.toString().toLowerCase()+"!", ChatColor.from(color));
}
for(ChatColor.ColorOptions color : ChatColor.ColorOptions.values()){
String correctCode = ChatColor.from(color);
@ -164,6 +166,10 @@ public class ChatColor {
{
return CRAZY;
}
case Reset:
{
return RESET+WHITE;
}
default:
{
return RESET+CRAZY;

View file

@ -10,12 +10,17 @@ public class ChatColorFactory {
public String build(){
return built;
}
public void reset()
{
built="";
append(ChatColor.resetChat());
}
public ColorBuilder(){}
}
private ColorBuilder instance;
public ChatColorFactory reset()
{
instance.append(ChatColor.resetChat());
instance.reset();
return this;
}
public ChatColorFactory set(ChatColor.ColorOptions option)

View file

@ -1,17 +1,34 @@
package dev.zontreck.libzontreck.chat;
import dev.zontreck.libzontreck.util.ChatHelpers;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.HoverEvent;
import net.minecraft.network.chat.HoverEvent.Action;
import net.minecraft.world.item.ItemStack;
/*
* Because of some weird behavior with java not liking that both HoverEvent and ClickEvent have an Action implementation, these must both be in a custom factory here where Action can be imported by itself in both files
*/
public class HoverTip {
/**
* This will return a hover event that shows a string of text when hovered over
* @param text
* @return
*/
public static HoverEvent get(String text)
{
return new HoverEvent(Action.SHOW_TEXT, Component.literal(text));
return new HoverEvent(Action.SHOW_TEXT, ChatHelpers.macro(text));
}
/**
* Returns a hover event that shows an item when hovered over
* @param is
* @return
*/
public static HoverEvent getItem(ItemStack is)
{
return new HoverEvent(Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(is));
}
}

View file

@ -0,0 +1,275 @@
package dev.zontreck.libzontreck.chestgui;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.events.CloseGUIEvent;
import dev.zontreck.libzontreck.events.OpenGUIEvent;
import dev.zontreck.libzontreck.items.ModItems;
import dev.zontreck.libzontreck.menus.ChestGUIMenu;
import dev.zontreck.libzontreck.networking.ModMessages;
import dev.zontreck.libzontreck.networking.packets.S2CCloseChestGUI;
import dev.zontreck.libzontreck.util.ChatHelpers;
import dev.zontreck.libzontreck.util.ServerUtilities;
import dev.zontreck.libzontreck.vectors.Vector2;
import dev.zontreck.libzontreck.vectors.Vector2i;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.network.NetworkHooks;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.function.Function;
/**
* Zontreck's ChestGUI Interface
* <p>
* This was heavily inspired by some of the ChestGUI's seen in Spigot mods.
* The reason for creating this system is to rapidly prototype interfaces. This is meant to be a helper to add a GUI quickly and easily without all the mess and fuss of making a menu or a screen. This is meant to be a stepping stone, not a permanent replacement to a proper UI.
* <p>
* This implementation is unlikely to ever change much, as it is just meant to accomplish the above task, and it does, successfully.
*/
public class ChestGUI
{
private ItemStackHandler container = new ItemStackHandler((9*3));
private String MenuTitle = "";
private UUID player;
public List<ChestGUIButton> buttons = new ArrayList<>();
private ChestGUIIdentifier id;
private int page =0;
public boolean hasAdd = false;
public boolean hasReset = false;
public boolean hasRemove = false;
private IChestGUIButtonCallback onAdd;
private IChestGUIButtonCallback onReset;
private IChestGUIButtonCallback onRemove;
public ChestGUIButton addBtn = null;
public ChestGUIButton resetBtn = null;
public ChestGUIButton removeBtn = null;
public ChestGUI withAdd(IChestGUIButtonCallback onAdd)
{
hasAdd=true;
this.onAdd=onAdd;
return this;
}
public ChestGUI withReset(IChestGUIButtonCallback onReset)
{
hasReset = true;
this.onReset = onReset;
return this;
}
private ChestGUI withRemove(IChestGUIButtonCallback onRemove)
{
hasRemove = true;
this.onRemove=onRemove;
return this;
}
public ChestGUI withButton(ChestGUIButton button)
{
if(buttons.size()>=2*9)
{
return this;
}
buttons.add(button);
button.withContainer(container);
container.setStackInSlot(button.getSlotNum(), button.buildIcon());
return this;
}
/*
X X X X X X X X X
X X X X X X X X X
0 0 0 - @ + 0 0 0
*/
// LEGEND:
// X = ChestGUIButton
// 0 = Empty Slot
// - = Remove / Subtract
// @ = Reset / Refresh
// + = Add
/**
* Updates the menu's utility buttons
*/
public void updateUtilityButtons()
{
if(hasRemove)
{
ItemStack remStack = new ItemStack(ModItems.CHESTGUI_REM.get(), 1);
ChestGUIButton rem = new ChestGUIButton(remStack, onRemove, new Vector2i(2, 3));
rem.withContainer(container);
removeBtn = rem;
container.setStackInSlot(rem.getSlotNum(), rem.buildIcon());
}
if(hasReset)
{
ItemStack resStack = new ItemStack(ModItems.CHESTGUI_RESET.get(), 1);
ChestGUIButton rem = new ChestGUIButton(resStack, onReset, new Vector2i(2, 4));
rem.withContainer(container);
resetBtn = rem;
container.setStackInSlot(rem.getSlotNum(), rem.buildIcon());
}
if(hasAdd)
{
ItemStack remStack = new ItemStack(ModItems.CHESTGUI_ADD.get(), 1);
ChestGUIButton rem = new ChestGUIButton(remStack, onAdd, new Vector2i(2, 5));
rem.withContainer(container);
addBtn = rem;
container.setStackInSlot(rem.getSlotNum(), rem.buildIcon());
}
}
public boolean isFirstPage() {
return page == 0;
}
public boolean isLastPage() {
int maxPerPage = 2 * 9;
int totalButtons = buttons.size();
int totalPages = (totalButtons - 1) / maxPerPage;
return page >= totalPages;
}
/**
* Checks if the number of buttons warrants adding the next/previous buttons to the utility row
* @return True if the number of buttons exceeds (2*9)
*/
public boolean hasMultiPage()
{
return (buttons.size() > (2*9));
}
public ChestGUI withTitle(String title)
{
MenuTitle = title;
return this;
}
public static ChestGUI builder()
{
return new ChestGUI();
}
public ChestGUI withPlayer(UUID id)
{
player=id;
return this;
}
/**
* Open the GUI on the client
*/
public void open()
{
if(LibZontreck.CURRENT_SIDE == LogicalSide.SERVER)
{
updateUtilityButtons();
MinecraftForge.EVENT_BUS.post(new OpenGUIEvent(id, player, this));
NetworkHooks.openScreen(ServerUtilities.getPlayerByID(player.toString()), new SimpleMenuProvider(ChestGUIMenu.getServerMenu(this), ChatHelpers.macro((MenuTitle != "") ? MenuTitle : "No Title")));
}
}
/**
* Send a signal to trigger the GUI to close on the server, then send a signal to the client to also close the interface
*/
public void close()
{
if(LibZontreck.CURRENT_SIDE == LogicalSide.SERVER)
{
MinecraftForge.EVENT_BUS.post(new CloseGUIEvent(this, ServerUtilities.getPlayerByID(player.toString())));
ModMessages.sendToPlayer(new S2CCloseChestGUI(), ServerUtilities.getPlayerByID(player.toString()));
}
}
public boolean isPlayer(UUID ID)
{
return player.equals(ID);
}
public ChestGUI withGUIId(ChestGUIIdentifier id)
{
this.id = id;
return this;
}
public boolean matches(ChestGUIIdentifier id)
{
return this.id.equals(id);
}
public void handleButtonClicked(int slot, Vector2 pos, Item item) {
for(ChestGUIButton button : buttons)
{
if(button.getSlotNum() == slot)
{
if(button.buildIcon().getItem() == item)
{
button.clicked();
return;
}
}
}
}
public boolean hasSlot(Vector2i slot)
{
for(ChestGUIButton btn : buttons)
{
if(btn.matchesSlot(slot))
{
return true;
}
}
return false;
}
public ChestGUIButton getSlot(Vector2i slot) {
if(hasSlot(slot))
{
for(ChestGUIButton btn : buttons)
{
if(btn.matchesSlot(slot))
{
return btn;
}
}
}
return null;
}
}

View file

@ -0,0 +1,172 @@
package dev.zontreck.libzontreck.chestgui;
import dev.zontreck.libzontreck.lore.LoreContainer;
import dev.zontreck.libzontreck.lore.LoreEntry;
import dev.zontreck.libzontreck.util.ChatHelpers;
import dev.zontreck.libzontreck.vectors.Vector2;
import dev.zontreck.libzontreck.vectors.Vector2i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.ItemStackHandler;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
public class ChestGUIButton
{
private Item icon;
private String name;
private List<LoreEntry> tooltipInfo = new ArrayList<>();
private IChestGUIButtonCallback callback;
private CompoundTag NBT = new CompoundTag();
/**
* Position is Row (X), Column (Y)
*/
private Vector2i position;
private ItemStack built;
private ItemStackHandler container;
private LoreContainer lore;
/**
* Sets the name of the ChestGUI Button (Item Name)
* @param name Name to set
* @return Button instance
*/
public ChestGUIButton withName(String name)
{
this.name=name;
return this;
}
public ChestGUIButton(Item icon, String name, IChestGUIButtonCallback callback, Vector2i position)
{
this.icon = icon;
this.name = name;
this.callback = callback;
this.position = position;
tooltipInfo = new ArrayList<>();
}
public ChestGUIButton(ItemStack existing, IChestGUIButtonCallback callback, Vector2i position)
{
this.callback = callback;
this.position = position;
LoreContainer container = new LoreContainer(existing);
tooltipInfo = container.miscData.loreData;
name = existing.getHoverName().getString();
icon = existing.getItem();
NBT = existing.getTag();
}
public ChestGUIButton withNBT(CompoundTag tag)
{
this.NBT = tag;
return this;
}
public ItemStack buildIcon()
{
ItemStack ret = new ItemStack(icon,1);
NBT.putInt("slot", getSlotNum());
NBT.put("pos", position.serialize());
ret.setTag(NBT);
LoreContainer cont = new LoreContainer(ret);
cont.clear();
cont.miscData.loreData.addAll(tooltipInfo);
cont.commitLore();
ret = ret.setHoverName(ChatHelpers.macro(name));
built=ret;
lore=cont;
return ret;
}
public ItemStackHandler buildIconStack()
{
ItemStack stack = buildIcon();
ItemStackHandler st = new ItemStackHandler(1);
st.setStackInSlot(0, stack);
built=stack;
lore = new LoreContainer(built);
return st;
}
protected ChestGUIButton withContainer(ItemStackHandler handler)
{
this.container=handler;
return this;
}
/**
* Adds a line to the Lore (Tooltip) of the button
* @param line The line to add
* @return ChestGUIButton instance
*/
public ChestGUIButton withInfo(LoreEntry line)
{
tooltipInfo.add(line);
return this;
}
/**
* Sets the position and returns the builder
* @param pos New button position
* @return This button instance
*/
public ChestGUIButton withPosition(Vector2i pos)
{
this.position=pos;
return this;
}
/**
* Check if the slot's row and column match (X,Y)
* @param slot
* @return True if matches
*/
public boolean matchesSlot(Vector2i slot)
{
return position.same(slot);
}
/**
* Returns the slot number in the 32 item grid
* @return Slot number from vector (row, column)
*/
public int getSlotNum()
{
return (int) Math.floor((position.x * 9) + position.y);
}
private static long lastInvoked = 0;
/**
* Button was clicked!
*/
public void clicked()
{
if(Instant.now().getEpochSecond() > (lastInvoked + 1))
{
lastInvoked = Instant.now().getEpochSecond();
callback.run(built, container, lore);
}
}
}

View file

@ -0,0 +1,62 @@
package dev.zontreck.libzontreck.chestgui;
import net.minecraft.nbt.CompoundTag;
import java.util.Objects;
import java.util.UUID;
/**
* As of revision 0121, this is now used in place of ResourceLocation. This gives more flexibility without the restrictions imposed on naming of ResourceLocations
*/
public class ChestGUIIdentifier
{
public UUID ID;
public String nickname;
/**
* Default constructor. Generates a random UUID!
* @param nick GUI nickname
*/
public ChestGUIIdentifier(String nick)
{
ID = UUID.randomUUID();
nickname=nick;
}
/**
* Serialize out the identifier for transmitting over the network, or saving to disk
* @return
*/
public CompoundTag serialize()
{
CompoundTag ret = new CompoundTag();
ret.putUUID("id", ID);
ret.putString("name", nickname);
return ret;
}
/**
* Deserialize the identifier
* @param tag
*/
public ChestGUIIdentifier(CompoundTag tag)
{
ID = tag.getUUID("id");
nickname = tag.getString("name");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ChestGUIIdentifier that = (ChestGUIIdentifier) o;
return Objects.equals(ID, that.ID) && Objects.equals(nickname, that.nickname);
}
@Override
public int hashCode() {
return Objects.hash(ID, nickname);
}
}

View file

@ -0,0 +1,33 @@
package dev.zontreck.libzontreck.chestgui;
import dev.zontreck.libzontreck.events.CloseGUIEvent;
import dev.zontreck.libzontreck.events.OpenGUIEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class ChestGUIRegistry
{
private static Map<UUID, ChestGUI> GUIS = new HashMap<>();
@SubscribeEvent
public static void onGuiOpen(final OpenGUIEvent event)
{
GUIS.put(event.getPlayer().getUUID(), event.getGui());
}
@SubscribeEvent
public static void onGuiClose(final CloseGUIEvent event)
{
GUIS.remove(event.player.getUUID());
}
public static ChestGUI get(UUID ID)
{
if(GUIS.containsKey(ID)) return GUIS.get(ID);
return null;
}
}

View file

@ -0,0 +1,20 @@
package dev.zontreck.libzontreck.chestgui;
import dev.zontreck.libzontreck.lore.LoreContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.ItemStackHandler;
/**
* This should be used in place of Runnable for ChestGUI
*/
@FunctionalInterface
public interface IChestGUIButtonCallback
{
/**
* A callback function that when invoked will pass the ChestGUI ItemStack
* @param stack A temporary itemstack that is used for the ChestGUI
* @param container The container object for manipulating other items when this is invoked
* @param lore The lore's container instance
*/
void run(ItemStack stack, ItemStackHandler container, LoreContainer lore);
}

View file

@ -0,0 +1,17 @@
package dev.zontreck.libzontreck.commands;
import dev.zontreck.libzontreck.LibZontreck;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(modid=LibZontreck.MOD_ID, bus=Mod.EventBusSubscriber.Bus.FORGE)
public class Commands {
@SubscribeEvent
public void onCommandsRegister(RegisterCommandsEvent ev)
{
CreditsCommand.register(ev.getDispatcher());
//GetHead.register(ev.getDispatcher());
}
}

View file

@ -0,0 +1,60 @@
package dev.zontreck.libzontreck.commands;
import com.mojang.brigadier.CommandDispatcher;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.chestgui.ChestGUI;
import dev.zontreck.libzontreck.chestgui.ChestGUIButton;
import dev.zontreck.libzontreck.chestgui.ChestGUIIdentifier;
import dev.zontreck.libzontreck.networking.ModMessages;
import dev.zontreck.libzontreck.networking.packets.S2CCloseChestGUI;
import dev.zontreck.libzontreck.util.heads.CreditsEntry;
import dev.zontreck.libzontreck.util.heads.HeadCache;
import dev.zontreck.libzontreck.vectors.Vector2i;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
public class CreditsCommand {
public static void register(CommandDispatcher<CommandSourceStack> dispatch)
{
dispatch.register(Commands.literal("credits_ariasmods").executes(s->credits(s.getSource())));
}
private static int credits(CommandSourceStack source) {
// Open the credits GUI
if(source.getEntity() instanceof Player)
{
// OK.
ChestGUI gui = ChestGUI.builder().withGUIId(new ChestGUIIdentifier("creditsgui")).withPlayer(source.getEntity().getUUID()).withTitle("Aria's Mods - Credits");
int x = 0;
int y = 0;
for(CreditsEntry entry : HeadCache.CREDITS)
{
gui = gui.withButton(new ChestGUIButton(entry.compile(), (stack, container, lore)->{
}, new Vector2i(x,y)));
//LibZontreck.LOGGER.info("Add gui button : " + entry.name);
y++;
if(y>=9)
{
x++;
y=0;
}
}
gui.open();
return 0;
}else return 1;
}
}

View file

@ -0,0 +1,34 @@
package dev.zontreck.libzontreck.commands;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import dev.zontreck.libzontreck.util.heads.HeadUtilities;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
public class GetHead {
public static void register(CommandDispatcher<CommandSourceStack> dispatch)
{
dispatch.register(Commands.literal("aria_debug_get_head").executes(c-> getHead(c.getSource(), c.getSource().getEntity().getName().getString())).then(Commands.argument("name", StringArgumentType.string()).executes(c -> getHead(c.getSource(), StringArgumentType.getString(c, "name")))));
}
private static int getHead(CommandSourceStack source, String string) {
try {
ServerPlayer player= source.getPlayerOrException();
ItemStack head = HeadUtilities.get(string, "");
player.addItem(head);
} catch (CommandSyntaxException e) {
e.printStackTrace();
}
return 0;
}
}

View file

@ -0,0 +1,110 @@
package dev.zontreck.libzontreck.currency;
import dev.zontreck.eventsbus.Bus;
import dev.zontreck.libzontreck.chat.ChatColor;
import dev.zontreck.libzontreck.currency.events.TransactionHistoryFlushEvent;
import dev.zontreck.libzontreck.profiles.Profile;
import dev.zontreck.libzontreck.profiles.UserProfileNotYetExistsException;
import net.minecraft.core.UUIDUtil;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class Account
{
public UUID player_id;
public List<Transaction> history;
public int balance;
public String accountName = "";
public boolean isPlayer=true;
public AccountReference getRef()
{
return new AccountReference(player_id);
}
protected Account(UUID ID)
{
player_id=ID;
history=new ArrayList<>();
balance=0;
if(isValidPlayer()) {
try {
Profile prof = Profile.get_profile_of(ID.toString());
accountName = prof.name_color + prof.nickname;
isPlayer=true;
} catch (UserProfileNotYetExistsException e) {
accountName = ChatColor.doColors("!Dark_Red!SYSTEM!White!");
isPlayer=false;
}
} else {
accountName = ChatColor.doColors("!Dark_Red!SYSTEM!White!");
isPlayer=false;
}
}
public CompoundTag save()
{
CompoundTag tag = new CompoundTag();
tag.put("id", NbtUtils.createUUID(player_id));
tag.putInt("balance", balance);
ListTag txs = new ListTag();
for(Transaction tx : history)
{
txs.add(tx.save());
}
tag.put("history", txs);
tag.putString("name", accountName);
tag.putBoolean("player", isPlayer);
return tag;
}
public Account(CompoundTag tag)
{
player_id = NbtUtils.loadUUID(tag.get("id"));
balance = tag.getInt("balance");
accountName = tag.getString("name");
isPlayer = tag.getBoolean("player");
history=new ArrayList<>();
ListTag lst = tag.getList("history", Tag.TAG_COMPOUND);
for(Tag t : lst){
CompoundTag lTag = (CompoundTag) t;
history.add(new Transaction(lTag));
}
}
/**
* Internal function for use only by the garbage collector to reduce memory footprint. Maximum of 20 transactions will be retained in the memory
*
* When the TX history grows beyond 20, the history should clear and it should get transferred to the long-term tx history storage. That file is not retained in memory, and only gets loaded when clearing to merge the lists. It is immediately saved and unloaded
* @see LongTermTransactionHistoryRecord
*/
public void flushTxHistory() {
LongTermTransactionHistoryRecord rec = LongTermTransactionHistoryRecord.of(player_id);
rec.addHistory(history);
rec.commit();
Bus.Post(new TransactionHistoryFlushEvent(this, rec, history));
rec = null;
history = new ArrayList<>();
}
/**
* Checks if the account is a player or system account
* @return True if the player has a valid UUID
*/
public boolean isValidPlayer()
{
return isPlayer;
}
}

View file

@ -0,0 +1,17 @@
package dev.zontreck.libzontreck.currency;
import java.util.UUID;
public class AccountReference
{
public UUID id;
public Account get()
{
return Bank.getAccount(id);
}
protected AccountReference(UUID ID)
{
id=ID;
}
}

View file

@ -0,0 +1,240 @@
package dev.zontreck.libzontreck.currency;
import com.google.common.collect.Lists;
import dev.zontreck.eventsbus.Bus;
import dev.zontreck.eventsbus.Subscribe;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.chat.ChatColor;
import dev.zontreck.libzontreck.chat.ChatColorFactory;
import dev.zontreck.libzontreck.currency.events.BankAccountCreatedEvent;
import dev.zontreck.libzontreck.currency.events.BankReadyEvent;
import dev.zontreck.libzontreck.currency.events.TransactionEvent;
import dev.zontreck.libzontreck.currency.events.WalletUpdatedEvent;
import dev.zontreck.libzontreck.exceptions.InvalidSideException;
import dev.zontreck.libzontreck.networking.ModMessages;
import dev.zontreck.libzontreck.networking.packets.S2CWalletUpdatedPacket;
import dev.zontreck.libzontreck.profiles.Profile;
import dev.zontreck.libzontreck.profiles.UserProfileNotYetExistsException;
import dev.zontreck.libzontreck.util.ChatHelpers;
import dev.zontreck.libzontreck.util.ServerUtilities;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.Tag;
import net.minecraftforge.common.MinecraftForge;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* SERVER-SIDE ONLY
*/
public class Bank
{
public static final Path BANK_DATA;
public static Account SYSTEM;
public static final UUID SYSTEM_ACCOUNT_ID;
static {
SYSTEM_ACCOUNT_ID = new UUID(0x9fc8, 0x829fcc);
BANK_DATA = LibZontreck.BASE_CONFIG.resolve("bank.nbt");
}
private Bank(){
if(ServerUtilities.isServer())
load();
else {
if(BANK_DATA.toFile().exists())
BANK_DATA.toFile().delete();
return;
}
SYSTEM = getAccount(SYSTEM_ACCOUNT_ID);
if(SYSTEM == null)
{
makeAccount(SYSTEM_ACCOUNT_ID);
SYSTEM=getAccount(SYSTEM_ACCOUNT_ID);
SYSTEM.balance = 0xFFFFFF;
instance.commit();
}
}
/**
* Internal function to deserialize NBT
*/
private void load()
{
try {
CompoundTag data = NbtIo.read(BANK_DATA.toFile());
accounts=new ArrayList<>();
ListTag acts = data.getList("accounts", Tag.TAG_COMPOUND);
for(Tag t : acts)
{
accounts.add(new Account((CompoundTag) t));
}
Bus.Post(new BankReadyEvent());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Do not use manually, this saves the bank data to disk. This is fired automatically when transactions are posted to accounts.
*/
public void commit()
{
CompoundTag tag = new CompoundTag();
ListTag lst = new ListTag();
for(Account act : accounts)
{
lst.add(act.save());
}
tag.put("accounts", lst);
try {
NbtIo.write(tag, BANK_DATA.toFile());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static final Bank instance = new Bank();
public List<Account> accounts = new ArrayList<>();
public static Account getAccount(UUID ID)
{
if(!hasAccount(ID))return null;
return instance.accounts.stream().filter(c->c.player_id.equals(ID)).collect(Collectors.toList()).get(0);
}
public static boolean hasAccount(UUID ID)
{
return instance.accounts.stream().filter(c->c.player_id.equals(ID)).collect(Collectors.toList()).stream().count()>0;
}
public static void makeAccount(UUID ID)
{
if(!hasAccount(ID)){
instance.accounts.add(new Account(ID));
instance.commit();
Bus.Post(new BankAccountCreatedEvent(getAccount(ID)));
}else {
}
}
/**
* Attempts to post a transaction and perform the money transfer
*
* Please post your reason to the Reasons list when cancelling.
* @param tx The transaction being attempted
* @return True if the transaction has been accepted. False if the transaction was rejected, or insufficient funds.
*/
protected static boolean postTx(Transaction tx) throws InvalidSideException, InvocationTargetException, IllegalAccessException {
if(ServerUtilities.isClient())return false;
TransactionEvent ev = new TransactionEvent(tx);
if(Bus.Post(ev))
{
// Send the list of reasons to the user
String reasonStr = String.join("\n", ev.reasons);
Account from = ev.tx.from.get();
Account to = ev.tx.to.get();
if(from.isValidPlayer())
{
ChatHelpers.broadcastTo(from.player_id, ChatHelpers.macro("!Dark_Gray![!Dark_Blue!Bank!Dark_Gray!] !Dark_Red!The transaction could not be completed because of the following reasons: " + reasonStr), LibZontreck.THE_SERVER);
}
if(to.isValidPlayer())
{
ChatHelpers.broadcastTo(to.player_id, ChatHelpers.macro("!Dark_Gray![!Dark_Blue!Bank!Dark_Gray!] !Dark_Red!The transaction could not be completed because of the following reasons: " + reasonStr), LibZontreck.THE_SERVER);
}
return false;
}else {
// Tx accepted
// Process funds now
Account from = ev.tx.from.get();
Account to = ev.tx.to.get();
int fromOld = from.balance;
int toOld = to.balance;
from.balance -= tx.amount;
to.balance += tx.amount;
from.history.add(tx);
to.history.add(tx);
Profile toProf = null;
Profile fromProf = null;
try{
fromProf = Profile.get_profile_of(from.player_id.toString());
}catch(UserProfileNotYetExistsException e){
e.printStackTrace();
}
try {
toProf = Profile.get_profile_of(to.player_id.toString());
} catch (UserProfileNotYetExistsException e) {
e.printStackTrace();
}
if(!from.isValidPlayer())
{
fromProf = Profile.SYSTEM;
}
if(!to.isValidPlayer())
{
toProf = Profile.SYSTEM;
}
if(from.isValidPlayer())
ChatHelpers.broadcastTo(from.player_id, ChatHelpers.macro("!Dark_Gray![!Dark_Blue!Bank!Dark_Gray!] !Dark_Green!You sent !White!${0} !Dark_green!to {1}", String.valueOf(tx.amount), toProf.name_color+toProf.nickname), LibZontreck.THE_SERVER);
if(to.isValidPlayer())
ChatHelpers.broadcastTo(from.player_id, ChatHelpers.macro("!Dark_Gray![!Dark_Blue!Bank!Dark_Gray!] {0} !Dark_Green!paid you ${1}", String.valueOf(tx.amount), toProf.name_color+toProf.nickname), LibZontreck.THE_SERVER);
if(to.isValidPlayer() && ServerUtilities.playerIsOffline(to.player_id)) Profile.unload(toProf);
if(from.isValidPlayer() && ServerUtilities.playerIsOffline(from.player_id))
Profile.unload(fromProf);
Bus.Post(new WalletUpdatedEvent(from.player_id, fromOld, from.balance, tx));
Bus.Post(new WalletUpdatedEvent(to.player_id, toOld, to.balance, tx));
if(from.isValidPlayer() && !ServerUtilities.playerIsOffline(from.player_id))
{
ModMessages.sendToPlayer(new S2CWalletUpdatedPacket(from.player_id, tx, from.balance, fromOld), ServerUtilities.getPlayerByID(from.player_id.toString()));
}
if(to.isValidPlayer() && !ServerUtilities.playerIsOffline(to.player_id))
{
ModMessages.sendToPlayer(new S2CWalletUpdatedPacket(to.player_id, tx, to.balance, toOld), ServerUtilities.getPlayerByID(to.player_id.toString()));
}
instance.commit();
}
return true;
}
/**
* This event is fired when wallets get updated. It cannot be cancelled
* @param ev The event containing the player ID and new+old wallet data
*/
@Subscribe
public static void onWalletUpdate(WalletUpdatedEvent ev)
{
}
}

View file

@ -0,0 +1,6 @@
package dev.zontreck.libzontreck.currency;
public class CurrencyHelper {
}

View file

@ -0,0 +1,72 @@
package dev.zontreck.libzontreck.currency;
import dev.zontreck.libzontreck.LibZontreck;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.Tag;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class LongTermTransactionHistoryRecord
{
public static final Path BASE;
static{
BASE = LibZontreck.BASE_CONFIG.resolve("transaction_history");
if(!BASE.toFile().exists())
{
BASE.toFile().mkdir();
}
}
public static Path ofPath(String name)
{
return BASE.resolve(name);
}
public void commit()
{
ListTag txs = new ListTag();
for(Transaction tx : history)
{
txs.add(tx.save());
}
CompoundTag tag = new CompoundTag();
tag.put("history", txs);
try {
NbtIo.write(tag, ofPath(player_id.toString()+".nbt").toFile());
}catch(IOException e){}
}
public UUID player_id;
public List<Transaction> history;
private LongTermTransactionHistoryRecord(UUID ID)
{
player_id=ID;
try {
CompoundTag tag = NbtIo.read(ofPath(ID.toString()+".nbt").toFile());
ListTag hist = tag.getList("history", Tag.TAG_COMPOUND);
history = new ArrayList<>();
for(Tag t : hist){
history.add(new Transaction((CompoundTag) t));
}
} catch (IOException e) {
history = new ArrayList<>();
}
}
public void addHistory(List<Transaction> other)
{
for (Transaction tx : other)
{
history.add(tx);
}
}
public static LongTermTransactionHistoryRecord of(UUID ID)
{
return new LongTermTransactionHistoryRecord(ID);
}
}

View file

@ -0,0 +1,56 @@
package dev.zontreck.libzontreck.currency;
import dev.zontreck.libzontreck.exceptions.InvalidSideException;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
public class Transaction
{
public AccountReference from;
public AccountReference to;
public int amount;
public long timestamp;
public CompoundTag save()
{
CompoundTag tag = new CompoundTag();
tag.put("from", NbtUtils.createUUID(from.id));
tag.put("to", NbtUtils.createUUID(to.id));
tag.putInt("amount", amount);
tag.putLong("timestamp", timestamp);
return tag;
}
public Transaction(CompoundTag tag)
{
from = new AccountReference(NbtUtils.loadUUID(tag.get("from")));
to = new AccountReference(NbtUtils.loadUUID(tag.get("to")));
amount = tag.getInt("amount");
timestamp = tag.getLong("timestamp");
}
public Transaction(Account from, Account to, int amount, long ts)
{
this.from = from.getRef();
this.to = to.getRef();
this.amount=amount;
timestamp = ts;
}
/**
* Submits the transaction to the bank to be processed
* @return True if the transaction was successfully submitted.
*/
public boolean submit(){
try {
return Bank.postTx(this);
} catch (InvalidSideException | InvocationTargetException | IllegalAccessException e) {
return false;
}
}
}

View file

@ -0,0 +1,14 @@
package dev.zontreck.libzontreck.currency.events;
import dev.zontreck.eventsbus.Event;
import dev.zontreck.libzontreck.currency.Account;
public class BankAccountCreatedEvent extends Event
{
public Account account;
public BankAccountCreatedEvent(Account act)
{
account=act;
}
}

View file

@ -0,0 +1,14 @@
package dev.zontreck.libzontreck.currency.events;
import dev.zontreck.eventsbus.Event;
/**
* Contains no information by itself, it only signals that the Bank is open for business
*
* @see dev.zontreck.libzontreck.currency.Bank
*/
public class BankReadyEvent extends Event
{
}

View file

@ -0,0 +1,26 @@
package dev.zontreck.libzontreck.currency.events;
import dev.zontreck.eventsbus.Cancellable;
import dev.zontreck.eventsbus.Event;
import dev.zontreck.libzontreck.currency.Transaction;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
@Cancellable
public class TransactionEvent extends Event
{
public Transaction tx;
/**
* This is the list of reasons why a transaction was aborted or blocked
*/
public List<String> reasons;
public TransactionEvent(Transaction txNew)
{
tx=txNew;
}
}

View file

@ -0,0 +1,23 @@
package dev.zontreck.libzontreck.currency.events;
import dev.zontreck.eventsbus.Event;
import dev.zontreck.libzontreck.currency.Account;
import dev.zontreck.libzontreck.currency.LongTermTransactionHistoryRecord;
import dev.zontreck.libzontreck.currency.Transaction;
import java.util.List;
public class TransactionHistoryFlushEvent extends Event
{
public LongTermTransactionHistoryRecord txHistory;
public Account associatedAccount;
public List<Transaction> flushed;
public TransactionHistoryFlushEvent(Account act, LongTermTransactionHistoryRecord txHistory, List<Transaction> flushed)
{
associatedAccount=act;
this.txHistory=txHistory;
this.flushed=flushed;
}
}

View file

@ -0,0 +1,25 @@
package dev.zontreck.libzontreck.currency.events;
import dev.zontreck.libzontreck.currency.Account;
import dev.zontreck.libzontreck.currency.Bank;
import net.minecraftforge.eventbus.api.Event;
import java.util.UUID;
/**
* This event is not cancellable!!
*/
public class WalletSyncEvent extends Event
{
public Account walletInformation;
public WalletSyncEvent(UUID player)
{
walletInformation = Bank.getAccount(player);
}
public WalletSyncEvent(Account act)
{
walletInformation = act;
}
}

View file

@ -0,0 +1,26 @@
package dev.zontreck.libzontreck.currency.events;
import dev.zontreck.eventsbus.Event;
import dev.zontreck.libzontreck.currency.Transaction;
import net.minecraft.world.entity.player.Player;
import java.util.UUID;
/**
* This event is dispatched on both the Client and the Server
*/
public class WalletUpdatedEvent extends Event
{
public int newBal;
public int oldBal;
public UUID player;
public Transaction tx;
public WalletUpdatedEvent(UUID player, int old, int newBal, Transaction tx)
{
this.player = player;
this.oldBal = old;
this.newBal = newBal;
this.tx=tx;
}
}

View file

@ -0,0 +1,84 @@
package dev.zontreck.libzontreck.dynamicchest;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.chestgui.ChestGUI;
import dev.zontreck.libzontreck.chestgui.ChestGUIButton;
import dev.zontreck.libzontreck.chestgui.ChestGUIRegistry;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.ItemStackHandler;
import org.jetbrains.annotations.NotNull;
import java.time.Instant;
public class ChestGUIReadOnlyStackHandler extends ItemStackHandler
{
private ChestGUI gui;
private Player player;
public ChestGUIReadOnlyStackHandler(ChestGUI gui, Player player)
{
super((3*9));
this.gui = gui;
this.player = player;
LibZontreck.LOGGER.info("Logical Side : " + LibZontreck.CURRENT_SIDE);
if(gui!=null)
{
if(gui.buttons!=null)
{
LibZontreck.LOGGER.info("Generating chest gui button items");
for(ChestGUIButton btn : gui.buttons)
{
setStackInSlot(btn.getSlotNum(), btn.buildIcon());
}
if(gui.hasAdd)
{
setStackInSlot(gui.addBtn.getSlotNum(), gui.addBtn.buildIcon());
}
if(gui.hasReset)
{
setStackInSlot(gui.resetBtn.getSlotNum(), gui.resetBtn.buildIcon());
}
if(gui.hasRemove)
{
setStackInSlot(gui.removeBtn.getSlotNum(), gui.removeBtn.buildIcon());
}
} else LibZontreck.LOGGER.error("Gui Buttons list is null");
} else LibZontreck.LOGGER.error("Gui is null!");
}
@Override
public int getSlots() {
return (3*9);
}
@Override
public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) {
return stack;
}
@Override
public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) {
ChestGUI instance = ChestGUIRegistry.get(player.getUUID());
if(instance==null)return ItemStack.EMPTY;
ChestGUIButton btn = instance.buttons.stream().filter(x->x.getSlotNum()==slot).findFirst().orElse(null);
if(btn == null) return ItemStack.EMPTY;
btn.clicked();
return ItemStack.EMPTY;
}
}

View file

@ -0,0 +1,59 @@
package dev.zontreck.libzontreck.dynamicchest;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.ItemStackHandler;
public class ReadOnlyItemStackHandler extends ItemStackHandler
{
private final ItemStackHandler slot;
private Runnable onClick;
protected ReadOnlyItemStackHandler(ItemStackHandler item)
{
super();
slot=item;
}
public ReadOnlyItemStackHandler(ItemStackHandler item, Runnable onClick)
{
this(item);
this.onClick=onClick;
}
@Override
public void setSize(int size)
{
stacks = NonNullList.<ItemStack>withSize(size, ItemStack.EMPTY);
}
@Override
public void setStackInSlot(int num, ItemStack stack) {
slot.setStackInSlot(num, stack);
}
@Override
public int getSlots() {
return slot.getSlots();
}
@Override
public ItemStack getStackInSlot(int num) {
return slot.getStackInSlot(num);
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
return stack;
}
@Override
public ItemStack extractItem(int num, int amount, boolean simulate) {
if(onClick != null){
onClick.run();
return ItemStack.EMPTY;
}
return ItemStack.EMPTY;
}
}

View file

@ -0,0 +1,19 @@
package dev.zontreck.libzontreck.events;
import dev.zontreck.libzontreck.chestgui.ChestGUI;
import dev.zontreck.libzontreck.util.ServerUtilities;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.eventbus.api.Event;
public class CloseGUIEvent extends Event
{
public ChestGUI gui;
public Player player;
public CloseGUIEvent(ChestGUI gui, ServerPlayer player)
{
this.gui = gui;
this.player = player;
}
}

View file

@ -0,0 +1,91 @@
package dev.zontreck.libzontreck.events;
import dev.zontreck.ariaslib.terminal.Task;
import dev.zontreck.ariaslib.util.DelayedExecutorService;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.exceptions.InvalidSideException;
import dev.zontreck.libzontreck.memory.PlayerContainer;
import dev.zontreck.libzontreck.networking.ModMessages;
import dev.zontreck.libzontreck.networking.packets.S2CServerAvailable;
import dev.zontreck.libzontreck.networking.packets.S2CWalletInitialSyncPacket;
import dev.zontreck.libzontreck.profiles.Profile;
import dev.zontreck.libzontreck.profiles.UserProfileNotYetExistsException;
import dev.zontreck.libzontreck.util.ServerUtilities;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = LibZontreck.MOD_ID, bus=Mod.EventBusSubscriber.Bus.FORGE)
public class ForgeEventHandlers {
@SubscribeEvent
public void onPlayerTick(LivingEvent.LivingTickEvent ev)
{
if(ev.getEntity().level().isClientSide) return;
if(ev.getEntity() instanceof ServerPlayer player)
{
PlayerContainer cont = LibZontreck.playerStorage.get(player.getUUID());
if(cont.player.positionChanged())
{
cont.player.update();
PlayerChangedPositionEvent pcpe = new PlayerChangedPositionEvent(player, cont.player.position, cont.player.lastPosition);
MinecraftForge.EVENT_BUS.post(pcpe);
}
}
}
@SubscribeEvent
public void onPlayerJoin(final PlayerEvent.PlayerLoggedInEvent ev)
{
if(ev.getEntity().level().isClientSide)return;
ServerPlayer player = (ServerPlayer)ev.getEntity();
Profile prof = Profile.factory(player);
ServerLevel level = player.serverLevel();
MinecraftForge.EVENT_BUS.post(new ProfileLoadedEvent(prof, player, level));
DelayedExecutorService.getInstance().schedule(new Task("send-msg", true) {
@Override
public void run() {
// Check player wallet, then send wallet to client
//ModMessages.sendToPlayer(new S2CWalletInitialSyncPacket(player.getUUID()), player);
S2CServerAvailable avail = new S2CServerAvailable();
avail.send(player);
}
}, 10);
}
@SubscribeEvent
public void onLeave(final PlayerEvent.PlayerLoggedOutEvent ev)
{
LibZontreck.LIBZONTRECK_SERVER_AVAILABLE=false; // Yes do this even on the client!
if(ev.getEntity().level().isClientSide)return;
// Get player profile, send disconnect alert, then commit profile and remove it from memory
try {
if(ServerUtilities.playerIsOffline(ev.getEntity().getUUID()))
{
Profile px=null;
try {
px = Profile.get_profile_of(ev.getEntity().getStringUUID());
Profile.unload(px);
} catch (UserProfileNotYetExistsException e) {
e.printStackTrace();
}
}
} catch (InvalidSideException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,21 @@
package dev.zontreck.libzontreck.events;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.eventbus.api.Event;
import java.util.UUID;
public class GUIButtonClickedEvent extends Event
{
public ResourceLocation id;
public ItemStack stack;
public UUID player;
public GUIButtonClickedEvent(ItemStack stack, ResourceLocation id, UUID player)
{
this.id = id;
this.stack = stack;
this.player = player;
}
}

View file

@ -0,0 +1,39 @@
package dev.zontreck.libzontreck.events;
import dev.zontreck.libzontreck.chestgui.ChestGUI;
import dev.zontreck.libzontreck.chestgui.ChestGUIIdentifier;
import dev.zontreck.libzontreck.util.ServerUtilities;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
import java.util.UUID;
public class OpenGUIEvent extends Event
{
private ChestGUIIdentifier GUIId;
private UUID playerID;
private final ChestGUI gui;
public OpenGUIEvent(ChestGUIIdentifier ID, UUID player, ChestGUI gui)
{
GUIId = ID;
playerID = player;
this.gui = gui;
}
public boolean matches(ChestGUIIdentifier id)
{
return GUIId.equals(id);
}
public ServerPlayer getPlayer()
{
return ServerUtilities.getPlayerByID(playerID.toString());
}
public ChestGUI getGui() {
return gui;
}
}

View file

@ -0,0 +1,20 @@
package dev.zontreck.libzontreck.events;
import dev.zontreck.libzontreck.vectors.WorldPosition;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.eventbus.api.Event;
public class PlayerChangedPositionEvent extends Event
{
public Player player;
public WorldPosition position;
public WorldPosition lastPosition;
public PlayerChangedPositionEvent (Player current, WorldPosition pos, WorldPosition last)
{
player=current;
position=pos;
lastPosition=last;
}
}

View file

@ -0,0 +1,13 @@
package dev.zontreck.libzontreck.events;
import dev.zontreck.libzontreck.profiles.Profile;
import net.minecraftforge.eventbus.api.Event;
public class ProfileCreatedEvent extends Event
{
public String playerID;
public ProfileCreatedEvent(Profile newProfile)
{
playerID = newProfile.user_id;
}
}

View file

@ -0,0 +1,19 @@
package dev.zontreck.libzontreck.events;
import dev.zontreck.libzontreck.profiles.Profile;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.eventbus.api.Event;
public class ProfileLoadedEvent extends Event
{
public Profile profile;
public ServerPlayer player;
public ServerLevel level;
public ProfileLoadedEvent(Profile prof, ServerPlayer player, ServerLevel level)
{
profile=prof;
this.player=player;
this.level=level;
}
}

View file

@ -0,0 +1,23 @@
package dev.zontreck.libzontreck.events;
import dev.zontreck.libzontreck.profiles.Profile;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.eventbus.api.Event;
/**
* This class is not cancelable.
* This event is fired while the profile is saving. It is used to acquire misc data.
*
* The only part of this that is modifiable at this stage of saving is the tag.
*/
public class ProfileSavingEvent extends Event
{
public final Profile profile;
public CompoundTag tag;
public ProfileSavingEvent(Profile profile, CompoundTag tag)
{
this.profile=profile;
this.tag=tag;
}
}

View file

@ -0,0 +1,12 @@
package dev.zontreck.libzontreck.events;
import net.minecraftforge.eventbus.api.Event;
public class ProfileUnloadedEvent extends Event
{
public String user_id;
public ProfileUnloadedEvent(String id)
{
user_id=id;
}
}

View file

@ -0,0 +1,19 @@
package dev.zontreck.libzontreck.events;
import dev.zontreck.libzontreck.profiles.Profile;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
@Cancelable
public class ProfileUnloadingEvent extends Event
{
public Profile profile;
public ServerPlayer player;
public ProfileUnloadingEvent(Profile profile, ServerPlayer player)
{
this.profile=profile;
this.player=player;
}
}

View file

@ -0,0 +1,16 @@
package dev.zontreck.libzontreck.events;
import java.util.ArrayList;
import java.util.List;
import dev.zontreck.libzontreck.networking.packets.IPacket;
import net.minecraftforge.eventbus.api.Event;
/**
* Used to register your packets with LibZontreck. Packets must extend IPacket and implement PacketSerializable. This is dispatched on both logical sides, and is considered a final event. It is not cancelable
* @see IPacket
*/
public class RegisterPacketsEvent extends Event
{
public final List<IPacket> packets = new ArrayList<>();
}

View file

@ -0,0 +1,12 @@
package dev.zontreck.libzontreck.exceptions;
public class InvalidDeserialization extends Exception
{
public InvalidDeserialization(String error){
super(error);
}
public InvalidDeserialization(){
super("Incorrect information was provided to the deserializer");
}
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.libzontreck.exceptions;
/**
* Thrown when requesting a world position's level on the client when in the wrong dimension.
*/
public class InvalidSideException extends Exception
{
public InvalidSideException(String msg){
super(msg);
}
}

View file

@ -0,0 +1,29 @@
package dev.zontreck.libzontreck.items;
import dev.zontreck.libzontreck.LibZontreck;
import net.minecraft.world.item.Item;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class ModItems
{
public static final DeferredRegister<Item> REGISTRY = DeferredRegister.create(ForgeRegistries.ITEMS, LibZontreck.MOD_ID);
public static final RegistryObject<Item> CHESTGUI_ADD = REGISTRY.register("chestgui_add", ()->new Item(new Item.Properties()));
public static final RegistryObject<Item> CHESTGUI_REM = REGISTRY.register("chestgui_remove", ()->new Item(new Item.Properties()));
public static final RegistryObject<Item> CHESTGUI_BACK = REGISTRY.register("chestgui_back", ()->new Item(new Item.Properties()));
public static final RegistryObject<Item> CHESTGUI_RESET = REGISTRY.register("chestgui_reset", ()->new Item(new Item.Properties()));
public static final RegistryObject<Item> CHESTGUI_FORWARD = REGISTRY.register("chestgui_forward", ()->new Item(new Item.Properties()));
public static void register(IEventBus bus)
{
REGISTRY.register(bus);
}
}

View file

@ -0,0 +1,96 @@
package dev.zontreck.libzontreck.lore;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import dev.zontreck.libzontreck.lore.LoreEntry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
/**
* Represents a container for multiple LoreEntry instances.
*/
public class ExtraLore {
@SerializedName("extra")
public List<LoreEntry> loreData = new ArrayList<>();
/**
* Saves the lore entries into a CompoundTag for storage.
*
* @param tag The CompoundTag to save the entries.
*/
public void save(CompoundTag tag) {
ListTag lores = saveEntries();
// Extra entry in display:Lore list
tag.put("extra", lores);
}
/**
* Saves the lore entries into a ListTag.
*
* @return The ListTag containing saved lore entries.
*/
public ListTag saveEntries() {
ListTag lores = new ListTag();
for (LoreEntry loreEntry : loreData) {
lores.add(StringTag.valueOf(loreEntry.saveJson()));
}
return lores;
}
/**
* Generates a JSON string representing the lore entries.
*
* @return The JSON string representing the lore entries.
*/
public String saveJson() {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
return gson.toJson(this);
}
/**
* Parses a JSON string to create an ExtraLore object with LoreEntry instances.
*
* @param json The JSON string representing lore entries.
* @return An ExtraLore object created from the JSON string.
*/
public static ExtraLore parseJson(String json) {
Gson gson = new Gson();
return gson.fromJson(json, ExtraLore.class);
}
/**
* Constructs an ExtraLore object from a CompoundTag.
*
* @param tags The CompoundTag containing lore entries.
*/
public ExtraLore(CompoundTag tags) {
ListTag tag = tags.getList("extra", CompoundTag.TAG_COMPOUND);
for (Tag t : tag) {
CompoundTag ct = (CompoundTag) t;
loreData.add(new LoreEntry(ct));
}
}
public ExtraLore(ListTag tag)
{
for(Tag t : tag)
{
loreData.add(LoreEntry.parseJson(t.getAsString()));
}
}
/**
* Constructs an empty ExtraLore object.
*/
public ExtraLore() {
// Empty constructor
}
}

View file

@ -0,0 +1,91 @@
package dev.zontreck.libzontreck.lore;
import dev.zontreck.libzontreck.chat.ChatColor;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.item.ItemStack;
public class LoreContainer {
private int loreEntryNumber;
public ExtraLore miscData = new ExtraLore();
private final ItemStack associatedItem;
public LoreContainer(ItemStack stack) {
associatedItem = stack;
loreEntryNumber = getLoreEntryNumber(stack);
parseExistingLore(stack);
}
public void commitLore() {
assertLoreExists();
CompoundTag tag = associatedItem.getOrCreateTag();
CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY);
ListTag lore = miscData.saveEntries();
display.put(ItemStack.TAG_LORE, lore);
tag.put(ItemStack.TAG_DISPLAY, display);
associatedItem.setTag(tag);
}
public void clear() {
loreEntryNumber = 0;
miscData.loreData.clear();
CompoundTag tag = associatedItem.getOrCreateTag().getCompound(ItemStack.TAG_DISPLAY);
tag.remove(ItemStack.TAG_LORE);
commitLore();
}
private void setOrUpdateIndex(ListTag lst, int pos, Tag insert) {
if (lst.size() <= pos) {
lst.add(insert);
loreEntryNumber = lst.size() - 1;
} else {
lst.set(pos, insert);
}
}
private void assertLoreExists() {
assertTag();
assertDisplay();
assertLore();
}
private void assertTag() {
if (!associatedItem.hasTag()) {
associatedItem.setTag(new CompoundTag());
}
}
private void assertDisplay() {
CompoundTag tag = associatedItem.getOrCreateTag();
CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY);
if (display.isEmpty()) {
tag.put(ItemStack.TAG_DISPLAY, new CompoundTag());
associatedItem.setTag(tag);
}
}
private void assertLore() {
CompoundTag tag = associatedItem.getOrCreateTag();
CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY);
ListTag lore = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING);
if (lore.isEmpty()) {
display.put(ItemStack.TAG_LORE, new ListTag());
associatedItem.setTag(tag);
}
}
private int getLoreEntryNumber(ItemStack stack) {
CompoundTag display = stack.getOrCreateTag().getCompound(ItemStack.TAG_DISPLAY);
ListTag loreEntries = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING);
return (loreEntries != null) ? loreEntries.size() : 0;
}
private void parseExistingLore(ItemStack stack) {
CompoundTag display = stack.getOrCreateTag().getCompound(ItemStack.TAG_DISPLAY);
ListTag loreEntries = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING);
miscData = new ExtraLore(loreEntries);
}
}

View file

@ -0,0 +1,160 @@
package dev.zontreck.libzontreck.lore;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import java.util.ArrayList;
import java.util.List;
public class LoreEntry {
/**
* Builder pattern for creating a LoreEntry object.
*/
public static class Builder {
private boolean bold;
private boolean italic;
private boolean underlined;
private boolean strikethrough;
private boolean obfuscated;
private String color = "";
private String text = "";
public Builder bold(boolean bold) {
this.bold = bold;
return this;
}
public Builder italic(boolean italic) {
this.italic = italic;
return this;
}
public Builder underlined(boolean underlined) {
this.underlined = underlined;
return this;
}
public Builder strikethrough(boolean strikethrough) {
this.strikethrough = strikethrough;
return this;
}
public Builder obfuscated(boolean obfuscated) {
this.obfuscated = obfuscated;
return this;
}
public Builder color(String color) {
this.color = color;
return this;
}
public Builder text(String text) {
this.text = text;
return this;
}
public LoreEntry build() {
return new LoreEntry(this);
}
}
public boolean bold;
public boolean italic;
public boolean underlined;
public boolean strikethrough;
public boolean obfuscated;
public String color = "";
public String text = "";
/**
* Constructs a LoreEntry object from a Builder
*/
LoreEntry(Builder builder) {
bold = builder.bold;
italic = builder.italic;
underlined = builder.underlined;
strikethrough = builder.strikethrough;
obfuscated = builder.obfuscated;
color = builder.color;
text = builder.text;
}
public LoreEntry (CompoundTag tag)
{
bold = tag.getBoolean("bold");
italic = tag.getBoolean("italic");
underlined = tag.getBoolean("underlined");
strikethrough = tag.getBoolean("strikethrough");
obfuscated = tag.getBoolean("obfuscated");
color = tag.getString("color");
text = tag.getString("text");
}
/**
* Saves the lore attributes into a ListTag for storage.
*
* @param parentTag The parent ListTag to save the attributes.
*/
public void save(ListTag parentTag) {
CompoundTag tag = new CompoundTag();
tag.putBoolean("bold", bold);
tag.putBoolean("italic", italic);
tag.putBoolean("underlined", underlined);
tag.putBoolean("strikethrough", strikethrough);
tag.putBoolean("obfuscated", obfuscated);
tag.putString("color", color);
tag.putString("text", text);
parentTag.add(tag);
}
/**
* Generates a JSON string representing the lore entry.
*
* @return The JSON string representing the lore entry.
*/
public String saveJson() {
List<LoreEntry> list = new ArrayList<>();
list.add(this);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
return gson.toJson(list);
}
/**
* Parses a JSON string to create a LoreEntry object.
*
* @param json The JSON string representing lore attributes.
* @return A LoreEntry object created from the JSON string.
*/
public static LoreEntry parseJson(String json) {
Gson gson = new Gson();
List<LoreEntry> list = gson.fromJson(json, new TypeToken<List<LoreEntry>>() {}.getType());
if (list != null && !list.isEmpty()) {
return list.get(0);
}
return null;
}
/**
* Converts a boolean value to its string representation.
*
* @param a The boolean value to convert.
* @return The string representation of the boolean.
*/
private String bool2str(boolean a) {
return a ? "true" : "false";
}
}

View file

@ -0,0 +1,25 @@
package dev.zontreck.libzontreck.lore;
public enum LoreType {
UNKNOWN((byte) 0x00),
STATS((byte) 0x01),
ORIGINAL_CRAFTER((byte)0x02);
private final byte type;
private LoreType(byte Option) {
type = Option;
}
public static LoreType valueOf(byte b) {
LoreType _T = LoreType.UNKNOWN;
_T = values()[b];
return _T;
}
public byte get()
{
return type;
}
}

View file

@ -0,0 +1,60 @@
package dev.zontreck.libzontreck.memory;
import java.util.UUID;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.exceptions.InvalidDeserialization;
import dev.zontreck.libzontreck.vectors.WorldPosition;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
public class PlayerComponent
{
public ServerPlayer player;
public WorldPosition position;
public WorldPosition lastPosition;
public PlayerComponent(ServerPlayer play)
{
player=play;
position = new WorldPosition(play);
}
public boolean positionChanged()
{
WorldPosition wp = new WorldPosition(player);
return !(wp.same(position));
}
public void update()
{
lastPosition=position;
position = new WorldPosition(player);
}
public static PlayerComponent fromID(UUID ID)
{
return new PlayerComponent(LibZontreck.THE_SERVER.getPlayerList().getPlayer(ID));
}
public CompoundTag serialize()
{
CompoundTag tag = new CompoundTag();
tag.putUUID("id", player.getUUID());
tag.put("pos", position.serialize());
return tag;
}
public static PlayerComponent deserialize(CompoundTag tag)
{
PlayerComponent comp = PlayerComponent.fromID(tag.getUUID("id"));
try {
comp.position = new WorldPosition(tag.getCompound("pos"), false);
} catch (InvalidDeserialization e) {
e.printStackTrace();
}
return comp;
}
}

View file

@ -0,0 +1,24 @@
package dev.zontreck.libzontreck.memory;
import java.util.UUID;
import dev.zontreck.libzontreck.LibZontreck;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
public class PlayerContainer {
public UUID ID;
public PlayerComponent player;
public CompoundTag miscData;
public PlayerContainer(UUID ID)
{
this(LibZontreck.THE_SERVER.getPlayerList().getPlayer(ID));
}
public PlayerContainer(ServerPlayer player)
{
this.player = new PlayerComponent(player);
miscData=new CompoundTag();
ID = player.getUUID();
}
}

View file

@ -0,0 +1,67 @@
package dev.zontreck.libzontreck.memory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
// This class is a universal data storage class for per-player data storage
// If a player logs out, this memory gets erased. Do not store anything here that requires persistence. Store it on the player instead.
public class VolatilePlayerStorage {
private List<PlayerContainer> datas = new ArrayList<>();
public void update(UUID player, PlayerContainer comp)
{
int indexOf = index(player);
if(indexOf!=-1)
datas.set(indexOf, comp);
}
public PlayerContainer getNew(UUID player)
{
if(index(player)==-1)
{
PlayerContainer comp = new PlayerContainer(player);
datas.add(comp);
return comp;
}else return get(player);
}
public PlayerContainer get(UUID player)
{
int indexOf = index(player);
if(indexOf!=-1)
{
return datas.get(indexOf);
}else return getNew(player);
}
public void delete(UUID id)
{
int index = index(id);
if(index!=-1)
{
datas.remove(index);
}
}
// Returns the index of the component by ID, or -1 if not found
public int index(UUID id)
{
int ret=-1;
Iterator<PlayerContainer> it = datas.iterator();
while(it.hasNext())
{
PlayerContainer comp = it.next();
if(comp.ID.equals(id))
{
ret=datas.indexOf(comp);
break;
}
}
return ret;
}
}

View file

@ -0,0 +1,71 @@
package dev.zontreck.libzontreck.menus;
import dev.zontreck.libzontreck.chestgui.ChestGUI;
import dev.zontreck.libzontreck.chestgui.ChestGUIButton;
import dev.zontreck.libzontreck.dynamicchest.ChestGUIReadOnlyStackHandler;
import dev.zontreck.libzontreck.dynamicchest.ReadOnlyItemStackHandler;
import dev.zontreck.libzontreck.types.ModMenuTypes;
import dev.zontreck.libzontreck.vectors.Vector2i;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerListener;
import net.minecraft.world.inventory.MenuConstructor;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
import org.jetbrains.annotations.Nullable;
public class ChestGUIMenu extends AbstractContainerMenu
{
public final ChestGUI gui;
public final ItemStackHandler slots;
public final Player player;
public ChestGUIMenu(int id, Inventory playerInv, FriendlyByteBuf buf)
{
this(id, playerInv, BlockPos.ZERO, playerInv.player, null);
}
public ChestGUIMenu(int id, Inventory playerInv, BlockPos position, Player player, ChestGUI gui)
{
super(ModMenuTypes.CHEST_GUI_MENU.get(), id);
this.gui = gui;
this.player = player;
slots = new ChestGUIReadOnlyStackHandler(gui, player);
int slotSize = 18;
int startX = 16;
int startY = 16;
for (int row = 0; row < 3; row++)
{
for(int column=0;column<9;column++)
{
addSlot(new SlotItemHandler(slots, row*9 + column, startX + column * slotSize, startY + row * slotSize));
}
}
}
@Override
public ItemStack quickMoveStack(Player player, int i) {
return ItemStack.EMPTY;
}
@Override
public boolean stillValid(Player player) {
return true;
}
public static MenuConstructor getServerMenu(ChestGUI gui)
{
return (id, playerInv, player) -> new ChestGUIMenu(id, playerInv, BlockPos.ZERO, player, gui);
}
}

View file

@ -0,0 +1,66 @@
package dev.zontreck.libzontreck.menus;
import com.mojang.blaze3d.systems.RenderSystem;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.chestgui.ChestGUI;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
public class ChestGUIScreen extends AbstractContainerScreen<ChestGUIMenu> {
public final Player player;
public final ChestGUIMenu menu;
private static final ResourceLocation TEXTURE = new ResourceLocation(LibZontreck.MOD_ID, "textures/gui/chest_gui.png");
public ChestGUIScreen(ChestGUIMenu menu, Inventory playerInv, Component comp)
{
super(menu, playerInv, comp);
this.menu = menu;
this.player = playerInv.player;
this.leftPos = 0;
this.topPos=0;
this.imageWidth = 191;
this.imageHeight = 82;
this.titleLabelX = 32;
this.titleLabelY =5;
}
@Override
public void render(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) {
this.renderBackground(pGuiGraphics);
super.render(pGuiGraphics, pMouseX, pMouseY, pPartialTick);
this.renderTooltip(pGuiGraphics, pMouseX, pMouseY);
}
@Override
protected void init() {
super.init();
this.inventoryLabelX = 32;
this.inventoryLabelY = 5;
}
@Override
protected void renderBg(GuiGraphics guiGraphics, float v, int i, int i1) {
renderBackground(guiGraphics);
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1,1,1,1);
RenderSystem.setShaderTexture(0, TEXTURE);
guiGraphics.blit(TEXTURE, this.leftPos, this.topPos, 0, 0, imageWidth, imageHeight);
}
@Override
protected void renderLabels(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY) {
pGuiGraphics.drawString(this.font, this.title, this.titleLabelX, this.titleLabelY, 4210752, false);
}
}

View file

@ -0,0 +1,85 @@
package dev.zontreck.libzontreck.networking;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.events.RegisterPacketsEvent;
import dev.zontreck.libzontreck.networking.packets.IPacket;
import dev.zontreck.libzontreck.networking.packets.S2CCloseChestGUI;
import dev.zontreck.libzontreck.networking.packets.S2CPlaySoundPacket;
import dev.zontreck.libzontreck.networking.packets.S2CServerAvailable;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Networking system!
*/
public class ModMessages {
private static SimpleChannel INSTANCE;
/**
* INTERNAL USE ONLY
*/
private static AtomicInteger PACKET_ID=new AtomicInteger(0);
public static int id()
{
return PACKET_ID.getAndIncrement();
}
public static void register()
{
SimpleChannel net = NetworkRegistry.ChannelBuilder.named(new ResourceLocation(LibZontreck.MOD_ID, "messages"))
.networkProtocolVersion(()->"1.0")
.clientAcceptedVersions(s->true)
.serverAcceptedVersions(s->true)
.simpleChannel();
RegisterPacketsEvent event = new RegisterPacketsEvent();
MinecraftForge.EVENT_BUS.post(event);
INSTANCE=net;
for(IPacket packet : event.packets)
{
packet.register(net);
}
net.messageBuilder(S2CPlaySoundPacket.class, PACKET_ID.getAndIncrement(), NetworkDirection.PLAY_TO_CLIENT)
.decoder(S2CPlaySoundPacket::new)
.encoder(S2CPlaySoundPacket::toBytes)
.consumerMainThread(S2CPlaySoundPacket::handle)
.add();
net.messageBuilder(S2CCloseChestGUI.class, PACKET_ID.getAndIncrement(), NetworkDirection.PLAY_TO_CLIENT)
.decoder(S2CCloseChestGUI::new)
.encoder(S2CCloseChestGUI::toBytes)
.consumerMainThread(S2CCloseChestGUI::handle)
.add();
net.messageBuilder(S2CServerAvailable.class, PACKET_ID.getAndIncrement(),
NetworkDirection.PLAY_TO_CLIENT)
.decoder(S2CServerAvailable::new)
.encoder(S2CServerAvailable::toBytes)
.consumerMainThread(S2CServerAvailable::handle)
.add();
}
public static <MSG> void sendToServer(MSG message){
INSTANCE.sendToServer(message);
}
public static <MSG> void sendToPlayer(MSG message, ServerPlayer player)
{
INSTANCE.send(PacketDistributor.PLAYER.with(()->player), message);
}
public static <MSG> void sendToAll(MSG message)
{
INSTANCE.send(PacketDistributor.ALL.noArg(), message);
}
}

View file

@ -0,0 +1,17 @@
package dev.zontreck.libzontreck.networking;
import dev.zontreck.libzontreck.events.RegisterPacketsEvent;
import dev.zontreck.libzontreck.networking.packets.S2CPlaySoundPacket;
import dev.zontreck.libzontreck.networking.packets.S2CWalletInitialSyncPacket;
import dev.zontreck.libzontreck.networking.packets.S2CWalletUpdatedPacket;
import net.minecraftforge.eventbus.api.SubscribeEvent;
public class NetworkEvents
{
@SubscribeEvent
public void onRegisterPackets(RegisterPacketsEvent ev)
{
ev.packets.add(new S2CWalletUpdatedPacket());
ev.packets.add(new S2CWalletInitialSyncPacket());
}
}

View file

@ -0,0 +1,21 @@
About Chest GUI
=====
A chest GUI is basically a dynamic menu that uses items and the standard chest layout to present a list of options in game.
These items cannot be removed from the chest and the click event is instead passed on as a ChestGUIEvent. Because the mod requesting this might not be on the client, the event is sent in both locations by utilizing a network packet.
ChestGUIEvent
====
This event is the parent of several other events.
OptionInteractEvent
----
This event gets dispatched on both the client and server when a option is interacted with.
OptionUpdateEvent
----
To be sent by the mod originating this dynamic menu. This event will instruct the ChestGUI to update a item, or multiple items after a interaction, or something else occuring. If the GUI is not open, this event gets ignored. This event should only be sent when we know the GUI is actually open!

View file

@ -0,0 +1,35 @@
package dev.zontreck.libzontreck.networking.packets;
import java.util.function.Supplier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.simple.SimpleChannel;
public interface IPacket {
void deserialize(CompoundTag data);
void serialize(CompoundTag data);
void toBytes(FriendlyByteBuf buf);
boolean handle(Supplier<NetworkEvent.Context> supplier);
/**
* @return The network direction of the packet
*/
NetworkDirection getDirection();
/**
* EXAMPLE:
* chan.messageBuilder(S2CPlaySoundPacket.class, ModMessages.id(), getDirection())
* .encoder(S2CPlaySoundPacket::toBytes)
* .decoder(S2CPlaySoundPacket::new)
* .consumer(S2CPlaySoundPacket::handle)
* .add();
* @param chan
*/
void register(SimpleChannel chan);
}

View file

@ -0,0 +1,39 @@
package dev.zontreck.libzontreck.networking.packets;
import dev.zontreck.libzontreck.chestgui.ChestGUI;
import dev.zontreck.libzontreck.menus.ChestGUIScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
public class S2CCloseChestGUI
{
public S2CCloseChestGUI()
{
}
public S2CCloseChestGUI(FriendlyByteBuf buf)
{
}
public void toBytes(FriendlyByteBuf buf)
{
}
public void handle(Supplier<NetworkEvent.Context> supplier)
{
NetworkEvent.Context ctx = supplier.get();
ctx.enqueueWork(()->{
// Close the GUI
if(Minecraft.getInstance().screen instanceof ChestGUIScreen)
Minecraft.getInstance().setScreen(null);
});
}
}

View file

@ -0,0 +1,69 @@
package dev.zontreck.libzontreck.networking.packets;
import java.util.function.Supplier;
import dev.zontreck.libzontreck.util.BinUtil;
import dev.zontreck.libzontreck.util.ServerUtilities;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.NetworkEvent.Context;
import net.minecraftforge.network.simple.SimpleChannel;
public class S2CPlaySoundPacket implements IPacket
{
public ResourceLocation sound;
public S2CPlaySoundPacket(FriendlyByteBuf buf) {
sound = buf.readResourceLocation();
}
public S2CPlaySoundPacket(ResourceLocation loc) {
sound=loc;
}
public S2CPlaySoundPacket(){}
@Override
public void deserialize(CompoundTag data) {
}
@Override
public void serialize(CompoundTag data) {
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeResourceLocation(sound);
}
@Override
public boolean handle(Supplier<Context> supplier) {
NetworkEvent.Context ctx=supplier.get();
ctx.enqueueWork(()->{
// We are on the client now, enqueue the sound!
SoundEvent ev = SoundEvent.createFixedRangeEvent(sound, 2.0f);
// Play sound for player!
Minecraft.getInstance().player.playSound(ev, 1, BinUtil.getARandomInstance().nextFloat(0, 1));
});
return true;
}
@Override
public NetworkDirection getDirection() {
return NetworkDirection.PLAY_TO_CLIENT;
}
@Override
public void register(SimpleChannel chan) {
ServerUtilities.registerPacket(chan, S2CPlaySoundPacket.class, this, S2CPlaySoundPacket::new);
}
}

View file

@ -0,0 +1,43 @@
package dev.zontreck.libzontreck.networking.packets;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.networking.ModMessages;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
public class S2CServerAvailable
{
public S2CServerAvailable(FriendlyByteBuf buf)
{
// nothing!
}
public S2CServerAvailable()
{
}
public void toBytes(FriendlyByteBuf buf)
{
}
public void handle(Supplier<NetworkEvent.Context> supplier)
{
NetworkEvent.Context context = supplier.get();
context.enqueueWork(()->{
// We are now on the client
LibZontreck.LIBZONTRECK_SERVER_AVAILABLE = true;
});
}
public void send(ServerPlayer player)
{
ModMessages.sendToPlayer(this, player);
}
}

View file

@ -0,0 +1,70 @@
package dev.zontreck.libzontreck.networking.packets;
import dev.zontreck.libzontreck.currency.Account;
import dev.zontreck.libzontreck.currency.Bank;
import dev.zontreck.libzontreck.currency.events.WalletSyncEvent;
import dev.zontreck.libzontreck.util.ServerUtilities;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.EventBus;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.simple.SimpleChannel;
import java.util.UUID;
import java.util.function.Supplier;
public class S2CWalletInitialSyncPacket implements IPacket
{
public Account act;
public S2CWalletInitialSyncPacket(FriendlyByteBuf buf)
{
act = new Account(buf.readNbt());
}
public S2CWalletInitialSyncPacket(Account act)
{
this.act=act;
}
public S2CWalletInitialSyncPacket(UUID ID)
{
this.act= Bank.getAccount(ID);
}
public S2CWalletInitialSyncPacket(){}
@Override
public void deserialize(CompoundTag data) {
}
@Override
public void serialize(CompoundTag data) {
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeNbt(act.save());
}
@Override
public boolean handle(Supplier<NetworkEvent.Context> supplier) {
return ServerUtilities.handlePacket(supplier, new Runnable() {
@Override
public void run() {
MinecraftForge.EVENT_BUS.post(new WalletSyncEvent(act));
}
});
}
@Override
public NetworkDirection getDirection() {
return NetworkDirection.PLAY_TO_CLIENT;
}
@Override
public void register(SimpleChannel chan) {
ServerUtilities.registerPacket(chan, S2CWalletInitialSyncPacket.class, this, S2CWalletInitialSyncPacket::new);
}
}

View file

@ -0,0 +1,81 @@
package dev.zontreck.libzontreck.networking.packets;
import dev.zontreck.eventsbus.Bus;
import dev.zontreck.libzontreck.currency.Transaction;
import dev.zontreck.libzontreck.currency.events.WalletUpdatedEvent;
import dev.zontreck.libzontreck.util.ServerUtilities;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.simple.SimpleChannel;
import java.lang.reflect.InvocationTargetException;
import java.util.UUID;
import java.util.function.Supplier;
public class S2CWalletUpdatedPacket implements IPacket
{
public UUID ID;
public Transaction tx;
public int balance;
public int oldBal;
public S2CWalletUpdatedPacket(FriendlyByteBuf buf)
{
ID = buf.readUUID();
tx = new Transaction(buf.readNbt());
balance = buf.readInt();
oldBal = buf.readInt();
}
public S2CWalletUpdatedPacket(UUID ID, Transaction tx, int bal, int old)
{
this.ID= ID;
this.tx=tx;
this.balance=bal;
oldBal=old;
}
public S2CWalletUpdatedPacket(){}
@Override
public void deserialize(CompoundTag data) {
}
@Override
public void serialize(CompoundTag data) {
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeUUID(ID);
buf.writeNbt(tx.save());
buf.writeInt(balance);
buf.writeInt(oldBal);
}
@Override
public boolean handle(Supplier<NetworkEvent.Context> supplier) {
return ServerUtilities.handlePacket(supplier, new Runnable() {
@Override
public void run() {
Bus.Post(new WalletUpdatedEvent(ID, oldBal, balance, tx));
}
});
}
@Override
public NetworkDirection getDirection() {
return NetworkDirection.PLAY_TO_CLIENT;
}
@Override
public void register(SimpleChannel chan) {
ServerUtilities.registerPacket(chan, S2CWalletUpdatedPacket.class, this, S2CWalletUpdatedPacket::new);
}
}

View file

@ -0,0 +1,39 @@
package dev.zontreck.libzontreck.networking.structures;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
public class OpenGUIRequest {
public ResourceLocation ID;
public UUID playerID;
public OpenGUIRequest(CompoundTag tag)
{
CompoundTag tags = tag.getCompound("id");
ID = new ResourceLocation(tags.getString("mod"), tags.getString("id"));
playerID = tag.getUUID("player");
}
public CompoundTag serialize()
{
CompoundTag tag = new CompoundTag();
tag.putUUID("player", playerID);
CompoundTag tags = new CompoundTag();
tags.putString("mod", ID.getNamespace());
tags.putString("id", ID.getPath());
tag.put("id", tags);
return tag;
}
public OpenGUIRequest(){}
}

View file

@ -0,0 +1,230 @@
package dev.zontreck.libzontreck.profiles;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.chat.ChatColor;
import dev.zontreck.libzontreck.events.ProfileCreatedEvent;
import dev.zontreck.libzontreck.events.ProfileSavingEvent;
import dev.zontreck.libzontreck.events.ProfileUnloadedEvent;
import dev.zontreck.libzontreck.events.ProfileUnloadingEvent;
import dev.zontreck.libzontreck.util.ServerUtilities;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.MinecraftForge;
/**
* A libZontreck user profile
*<p></p>
* This is used to contain common player data, as well as be capable of serializing the player's data and sending to/from the client.
*/
public class Profile {
public String username;
public String user_id;
public String prefix;
public String nickname;
public String name_color; // ChatColor.X
public String prefix_color;
public String chat_color;
public Boolean flying;
public int available_vaults;
public int deaths;
public ServerPlayer player;
private File accessor;
private CompoundTag miscData;
public CompoundTag NBT;
public static final Path BASE;
public static final Profile SYSTEM;
static{
BASE = LibZontreck.BASE_CONFIG.resolve("profiles");
if(!BASE.toFile().exists())
{
try {
Files.createDirectory(BASE);
LibZontreck.LOGGER.info("Created profiles base directory");
} catch (IOException e) {
e.printStackTrace();
LibZontreck.LOGGER.error("Failed to create profiles base directory");
}
}
SYSTEM = new Profile("SYSTEM", "", "SYSTEM", ChatColor.DARK_RED, LibZontreck.NULL_ID.toString(), "", "", false, 0, null, 0, null, null, new CompoundTag());
}
public Profile(String username, String prefix, String nickname, String name_color, String ID, String prefix_color, String chat_color, Boolean isFlying, int vaults, File vaultFile, int deathCount, ServerPlayer player, CompoundTag misc, CompoundTag NBT) {
this.username = username;
this.prefix = prefix;
this.nickname = nickname;
this.name_color = name_color;
this.user_id = ID;
this.prefix_color = prefix_color;
this.chat_color = chat_color;
this.flying=isFlying;
this.available_vaults=vaults;
this.deaths=deathCount;
this.player=player;
miscData = misc;
this.NBT = NBT;
this.accessor = vaultFile;
}
public boolean runSanityChecks()
{
if(player == null) return false;
return true;
}
/**
* Gets, or loads from persistent data, the user's LibZ profile
* @param UUID Player ID
* @return Profile
* @throws UserProfileNotYetExistsException When the profile has not yet been created
*/
public static Profile get_profile_of(String UUID) throws UserProfileNotYetExistsException
{
if(LibZontreck.PROFILES.containsKey(UUID)){
Profile prof = LibZontreck.PROFILES.get(UUID);
if(!prof.runSanityChecks())
{
prof.player = ServerUtilities.getPlayerByID(UUID);
}
return prof;
}else {
// Create or load profile
Path userProfile = BASE.resolve(UUID);
if(userProfile.toFile().exists())
{
// Load profile data
File ace = userProfile.resolve("profile.nbt").toFile();
try {
Profile actual = load(NbtIo.read(ace), ace, ServerUtilities.getPlayerByID(UUID));
LibZontreck.PROFILES.put(UUID, actual);
return actual;
} catch (IOException e) {
throw new UserProfileNotYetExistsException(UUID);
} catch (NullPointerException e)
{
throw new UserProfileNotYetExistsException(UUID);
}
}else {
// Create directory, then throw a exception so a new profile gets created
try {
Files.createDirectories(userProfile);
} catch (IOException e) {
e.printStackTrace();
}
throw new UserProfileNotYetExistsException(UUID);
}
}
}
private static Profile load(CompoundTag tag, File accessor, ServerPlayer player)
{
return new Profile(tag.getString("user"), tag.getString("prefix"), tag.getString("nick"), tag.getString("nickc"), tag.getString("id"), tag.getString("prefixc"), tag.getString("chatc"), tag.getBoolean("flying"), tag.getInt("vaults"), accessor, tag.getInt("deaths"), player, tag.getCompound("misc"), tag.getCompound("data"));
}
/**
* Generate a new user profile.
*
* @param player The player to generate the profile for
*/
private static void generateNewProfile(ServerPlayer player)
{
Path userProfile = BASE.resolve(player.getStringUUID());
if(userProfile.toFile().exists())
{
// Load profile data
File ace = userProfile.resolve("profile.nbt").toFile();
Profile template = new Profile(player.getName().getString(), "Member", player.getDisplayName().getString(), ChatColor.GREEN, player.getStringUUID(), ChatColor.AQUA, ChatColor.WHITE, false, 0, ace, 0, player, new CompoundTag(), new CompoundTag());
template.commit();
LibZontreck.PROFILES.put(player.getStringUUID(), template);
MinecraftForge.EVENT_BUS.post(new ProfileCreatedEvent(template));
return;
}else {
try {
Files.createDirectories(userProfile);
} catch (IOException e) {
e.printStackTrace();
}
generateNewProfile(player);
}
}
@Override
public void finalize()
{
if(MinecraftForge.EVENT_BUS.post(new ProfileUnloadingEvent(this, player)))
{
commit();
}
LibZontreck.LOGGER.info("Profile is unloaded for "+username);
MinecraftForge.EVENT_BUS.post(new ProfileUnloadedEvent(user_id));
}
public static void unload(Profile prof)
{
LibZontreck.PROFILES.remove(prof.user_id);
prof=null;
}
/**
* Creates a profile if it does not yet exist
* @param play Player
* @return The existing, or new, profile instance.
*/
public static Profile factory(ServerPlayer play)
{
try {
return get_profile_of(play.getStringUUID());
} catch (UserProfileNotYetExistsException e) {
generateNewProfile(play);
return factory(play);
}
}
/**
* Save the profile to disk
*/
public void commit()
{
// Save data to FileTree
CompoundTag serial = new CompoundTag();
serial.putString("user", username);
serial.putString("prefix", prefix);
serial.putString("nick", nickname);
serial.putString("id", user_id);
serial.putString("nickc", name_color);
serial.putString("prefixc", prefix_color);
serial.putString("chatc", chat_color);
serial.putBoolean("flying", flying);
serial.putInt("vaults", available_vaults);
serial.putInt("deaths", deaths);
ProfileSavingEvent event = new ProfileSavingEvent(this, miscData);
MinecraftForge.EVENT_BUS.post(event);
serial.put("misc", event.tag);
serial.put("data", NBT);
try {
NbtIo.write(serial, accessor);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,9 @@
package dev.zontreck.libzontreck.profiles;
public class UserProfileNotYetExistsException extends Exception{
String playerID;
public UserProfileNotYetExistsException(String id){
super("A user profile does not yet exist");
playerID=id;
}
}

View file

@ -0,0 +1,29 @@
package dev.zontreck.libzontreck.types;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.menus.ChestGUIMenu;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraftforge.common.extensions.IForgeMenuType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.network.IContainerFactory;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class ModMenuTypes
{
public static DeferredRegister<MenuType<?>> REGISTRY = DeferredRegister.create(ForgeRegistries.MENU_TYPES, LibZontreck.MOD_ID);
public static RegistryObject<MenuType<ChestGUIMenu>> CHEST_GUI_MENU = registerMenuType(ChestGUIMenu::new, "chestgui");
private static <T extends AbstractContainerMenu> RegistryObject<MenuType<T>> registerMenuType(IContainerFactory<T> factory, String name)
{
return REGISTRY.register(name, ()-> IForgeMenuType.create(factory));
}
public static void register(IEventBus bus)
{
REGISTRY.register(bus);
}
}

View file

@ -0,0 +1,59 @@
package dev.zontreck.libzontreck.util;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class BinUtil {
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
/**
* Converts a byte array to hexadecimal
* @param bytes
* @return
*/
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
public static byte[] hexToBytes(String hexStr)
{
List<Byte> bList = new ArrayList<>();
for(int i=0;i<hexStr.length();i+=2)
{
bList.add((byte)(
(Character.digit(hexStr.charAt(i), 16)<<4) +
(Character.digit(hexStr.charAt(i+1), 16))
));
}
return byteArray(bList);
}
public static byte[] byteArray(List<Byte> b)
{
byte[] ret = new byte[b.size()];
int i=0;
for(byte bx : b)
{
ret[i] = bx;
i++;
}
return ret;
}
/**
* @return A random instance backed by the time including milliseconds as the seed.
*/
public static Random getARandomInstance()
{
return new Random(Instant.now().toEpochMilli());
}
}

View file

@ -0,0 +1,29 @@
package dev.zontreck.libzontreck.util;
import dev.zontreck.libzontreck.vectors.Vector3;
import net.minecraft.server.level.ServerLevel;
import java.util.ArrayList;
import java.util.List;
/**
* Contains helper functions for block position calculations
*/
public class BlocksUtil
{
/**
* Gathers a list of positions for like-blocks in a vein. This can accept a limit of -1, but has a hard cap at 512 blocks
* @param level The level to find the vein in
* @param start Starting position for vein
* @param limit The applicable limit for vein detection
* @return List of positions for the vein
*/
public static List<Vector3> VeinOf(ServerLevel level, Vector3 start, int limit)
{
List<Vector3> ret = new ArrayList<>();
return ret;
}
}

View file

@ -0,0 +1,155 @@
package dev.zontreck.libzontreck.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.chat.ChatColor;
import net.minecraft.network.chat.*;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
public class ChatHelpers {
public static void broadcastActionBar(Component message, MinecraftServer server)
{
server.execute(new Runnable(){
@Override
public void run()
{
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
player.displayClientMessage(message, true);
}
LibZontreck.LOGGER.info("[ALL] "+message.getContents());
}
});
}
public static void broadcast(Component message, MinecraftServer server)
{
server.execute(new Runnable(){
@Override
public void run()
{
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
player.displayClientMessage(message, false);
}
LibZontreck.LOGGER.info("[ALL] "+message.getContents());
}
});
}
public static void broadcastTo(UUID ID, Component message, MinecraftServer server, boolean actionBar)
{
server.execute(new Runnable(){
@Override
public void run()
{
ServerPlayer play = server.getPlayerList().getPlayer(ID);
if(play==null)return;
play.displayClientMessage(message, actionBar);
LibZontreck.LOGGER.info("[SERVER] -> ["+play.getName().getContents()+"] "+message.getContents());
}
});
}
public static void broadcastTo(UUID ID, Component message, MinecraftServer server)
{
broadcastTo(ID, message, server, false);
}
public static void broadcastToAbove(UUID ID, Component message, MinecraftServer server)
{
broadcastTo(ID, message, server, true);
}
public static void broadcastTo(Player ID, Component message, MinecraftServer server)
{
broadcastTo(ID.getUUID(), message, server, false);
}
public static void broadcastToAbove(Player ID, Component message, MinecraftServer server)
{
broadcastTo(ID.getUUID(), message, server, true);
}
public static String hashOfMd5(String input) throws NoSuchAlgorithmException {
MessageDigest md5 = MessageDigest.getInstance("md5");
md5.update(input.getBytes());
return asHex(md5.digest());
}
public static String hashOfSha256(String input) throws NoSuchAlgorithmException {
MessageDigest md5 = MessageDigest.getInstance("sha-256");
md5.update(input.getBytes());
return asHex(md5.digest());
}
public static String hashOfMd5(byte[] input) throws NoSuchAlgorithmException {
MessageDigest md5 = MessageDigest.getInstance("md5");
md5.update(input);
return asHex(md5.digest());
}
public static String hashOfSha256(byte[] input) throws NoSuchAlgorithmException {
MessageDigest md5 = MessageDigest.getInstance("sha-256");
md5.update(input);
return asHex(md5.digest());
}
public static String asHex(byte[] input)
{
return BinUtil.bytesToHex(input);
}
/**
* Returns the output with colors applied, and chat entries replaced using [number] as the format
* @param input
* @param inputs Entries to replace with in input
* @return
*/
public static MutableComponent macro(String input, String... inputs)
{
return Component.literal(macroize(input,inputs));
}
/**
* Returns the output with colors applied, and chat entries replaced using [number] as the format
* @param input
* @param inputs Entries to replace with in input
* @return
*/
public static String macroize(String input, String... inputs)
{
String output = input;
for (int i = 0; i < inputs.length; i++) {
String inp = inputs[i];
output = output.replaceAll("\\["+String.valueOf(i)+"]", inp);
}
return ChatColor.doColors(output);
}
/**
* Merges the styles
* @param comp The original component
* @param ce Click event to add to the component
* @return Component + Merged Event
*/
public static MutableComponent applyClickEvent(MutableComponent comp, ClickEvent ce)
{
return comp.setStyle(comp.getStyle().withClickEvent(ce));
}
/**
* Merges the styles
* @param comp The original component
* @param ce Hover event to add to the component
* @return Component + Merged Event
*/
public static MutableComponent applyHoverEvent(MutableComponent comp, HoverEvent ce)
{
return comp.setStyle(comp.getStyle().withHoverEvent(ce));
}
}

View file

@ -0,0 +1,49 @@
package dev.zontreck.libzontreck.util;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import net.minecraftforge.fml.loading.FMLPaths;
public class FileTreeDatastore {
private static final Path BASE;
static{
Path X = FMLPaths.CONFIGDIR.get().resolve("arias_mods");
BASE=X;
if(!BASE.toFile().exists())
{
try {
Files.createDirectory(BASE);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static String get()
{
return BASE.toString();
}
public static Path of(String nick)
{
return BASE.resolve(nick);
}
public static List<File> getListOfFiles(Path files)
{
List<File> fileList = new ArrayList<>();
File[] entries = files.toFile().listFiles();
for (File file : entries) {
fileList.add(file);
}
return fileList;
}
}

View file

@ -0,0 +1,22 @@
package dev.zontreck.libzontreck.util;
import java.net.URL;
import java.util.Scanner;
public class HttpHelper {
public static String getFrom(URL url)
{
String data = "";
try (Scanner s = new Scanner(url.openStream()))
{
s.useDelimiter("\\A");
data = s.hasNext() ? s.next() : "";
}catch(Exception e)
{
}
return data;
}
}

View file

@ -0,0 +1,58 @@
package dev.zontreck.libzontreck.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraftforge.registries.ForgeRegistries;
public class ItemUtils {
public static Map<Enchantment, Integer> getEnchantments(ItemStack stack)
{
//ListTag enchants = stack.getEnchantmentTags();
Map<Enchantment, Integer> enchantments = EnchantmentHelper.getEnchantments(stack);
return enchantments;
/*Map<Enchantment, Integer> enchantments = new HashMap<>();
Iterator<Tag> enchantsIterator = enchants.iterator();
while(enchantsIterator.hasNext())
{
CompoundTag theTag = (CompoundTag)enchantsIterator.next();
Enchantment enchant = EnchantmentHelper.
Enchantment ench = .getOptional(EnchantmentHelper.getEnchantmentId(theTag)).get();
Integer level = EnchantmentHelper.getEnchantmentLevel(theTag);
enchantments.put(ench, level);
}
return enchantments;*/
}
public static Integer getEnchantmentLevel(Enchantment ench, ItemStack stack)
{
Integer ret = 0;
try{
Map<Enchantment, Integer> enchants = getEnchantments(stack);
ret=enchants.get(ench);
}catch(Exception e)
{
ret =0;
}finally{
if(ret == null)ret =0;
}
return ret;
}
}

View file

@ -0,0 +1,45 @@
package dev.zontreck.libzontreck.util;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import dev.zontreck.ariaslib.util.FileIO;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import java.io.File;
import java.nio.file.Path;
/**
* Provides helpers for reading and writing snbt to file
*/
public class SNbtIo
{
/**
* Read the file at the path, and deserialize from snbt
* @param path The file to load
* @return The deserialized compound tag, or a blank tag
*/
public static CompoundTag loadSnbt(Path path)
{
if(!path.toFile().exists())
return new CompoundTag();
else {
File fi = path.toFile();
try {
return NbtUtils.snbtToStructure(FileIO.readFile(fi.getAbsolutePath()));
} catch (CommandSyntaxException e) {
return new CompoundTag();
}
}
}
/**
* Writes the tag to the file specified
* @param path The file to write
* @param tag The tag to serialize
*/
public static void writeSnbt(Path path, CompoundTag tag)
{
String snbt = NbtUtils.structureToSnbt(tag);
FileIO.writeFile(path.toFile().getAbsolutePath(), snbt);
}
}

View file

@ -0,0 +1,99 @@
package dev.zontreck.libzontreck.util;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.Supplier;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.exceptions.InvalidSideException;
import dev.zontreck.libzontreck.networking.ModMessages;
import dev.zontreck.libzontreck.networking.packets.IPacket;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.simple.SimpleChannel;
public class ServerUtilities
{
/**
* This function only exists on the server
* @param id Player ID
* @return The server player associated with the ID
*/
public static ServerPlayer getPlayerByID(String id)
{
return LibZontreck.THE_SERVER.getPlayerList().getPlayer(UUID.fromString(id));
}
/**
* Handles the registration of packets
* @param <X>
* @param channel
* @param type
* @param inst
* @param decoder
*/
public static <X extends IPacket> void registerPacket(SimpleChannel channel, Class<X> type, X inst, Function<FriendlyByteBuf, X> decoder)
{
IPacket packet = (IPacket) inst;
channel.messageBuilder(type, ModMessages.id(), packet.getDirection())
.decoder(decoder)
.encoder(X::toBytes)
.consumerMainThread(X::handle)
.add();
}
/**
* Handles the tedious and repetitive actions in the handle packet segment of code
* @param context
* @param run
* @return
*/
public static boolean handlePacket(Supplier<NetworkEvent.Context> context, Runnable run)
{
NetworkEvent.Context ctx = context.get();
ctx.enqueueWork(run);
return true;
}
/**
* Checks if the mod is running on the server
* @return True if the mod is on the server
*/
public static boolean isServer()
{
return (LibZontreck.CURRENT_SIDE == LogicalSide.SERVER);
}
/**
* Checks if the mod is running on the client
* @return True if the mod is on the client
*/
public static boolean isClient()
{
return !isServer();
}
public static boolean playerIsOffline(UUID ID) throws InvalidSideException {
if(isClient())throw new InvalidSideException("This can only be called on the server");
if(LibZontreck.THE_SERVER.getPlayerList().getPlayer(ID) == null) return true;
else return false;
}
/**
* Checks if the user has operator permissions on the server
* @param ID The player ID
* @return True if the player is op
*/
public static boolean playerIsOp(UUID ID)
{
ServerPlayer player = getPlayerByID(ID.toString());
if(player.hasPermissions(player.getServer().getOperatorUserPermissionLevel()))
{
return true;
}else return false;
}
}

View file

@ -0,0 +1,59 @@
package dev.zontreck.libzontreck.util.heads;
import dev.zontreck.libzontreck.chat.ChatColor;
import dev.zontreck.libzontreck.lore.ExtraLore;
import dev.zontreck.libzontreck.lore.LoreContainer;
import dev.zontreck.libzontreck.lore.LoreEntry;
import dev.zontreck.libzontreck.util.ChatHelpers;
import dev.zontreck.libzontreck.util.heads.HeadCache.HeadCacheItem;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
public class CreditsEntry {
public HeadCacheItem player;
public String name;
public String role;
public String description;
public CreditsEntry(HeadCacheItem item, String name, String role, String descript){
player=item;
this.name=name;
this.role=role;
this.description=descript;
}
/**
* Compiles all the information into the head item, then applies the Lore Entry with the role the person has played, and a description
* @return
*/
public ItemStack compile()
{
ItemStack stack = player.getAsItem("");
stack.setHoverName(ChatHelpers.macro(name));
LoreContainer contain = new LoreContainer(stack);
contain.clear();
LoreEntry.Builder builder = new LoreEntry.Builder();
builder = builder.text(ChatColor.doColors("!Dark_Purple!Role: "+role + "\n"))
.bold(true)
.italic(true);
contain.miscData.loreData.add(builder.build());
builder = new LoreEntry.Builder().italic(true)
.text(ChatColor.doColors("!White!About: !Dark_Green!"+description + "\n"));
contain.miscData.loreData.add(builder.build());
contain.commitLore();
return stack;
}
/**
* Generates a written book that can serve as an about-page about the person being creditted.
* @return
*/
public ItemStack compileInfosBook()
{
// Will return a patchouli book
return null;
}
}

View file

@ -0,0 +1,215 @@
package dev.zontreck.libzontreck.util.heads;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.util.ChatHelpers;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.PlayerHeadItem;
public class HeadCache
{
public static final Path CACHE_FILE;
public static final HeadCache CACHE = new HeadCache();
public List<HeadCacheItem> items = new ArrayList<>();
public class HeadCacheItem
{
public UUID owner;
public String texture;
public String name;
public CompoundTag serialize()
{
CompoundTag tag = new CompoundTag();
tag.putUUID("id", owner);
tag.putString("texture", texture);
tag.putString("name", name);
return tag;
}
public HeadCacheItem(CompoundTag tag)
{
owner = tag.getUUID("id");
texture = tag.getString("texture");
name = tag.getString("name");
}
private HeadCacheItem()
{}
public ItemStack getAsItem(String itemName)
{
ItemStack head = new ItemStack(Items.PLAYER_HEAD, 1);
CompoundTag skullOwner = new CompoundTag();
skullOwner.putUUID("Id", owner);
CompoundTag properties = new CompoundTag();
ListTag textures = new ListTag();
CompoundTag item = new CompoundTag();
item.putString("Value", texture);
textures.add(item);
properties.put("textures", textures);
skullOwner.put("Properties", properties);
head.addTagElement(PlayerHeadItem.TAG_SKULL_OWNER, skullOwner);
if(itemName == "")
{
Component headname = ChatHelpers.macro("[0]'s Head", name);
head.setHoverName(headname);
}else {
head.setHoverName(ChatHelpers.macro(itemName));
}
return head;
}
public static UUID toNewID(final String input) {
return UUID.fromString(input.replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5"));
}
public String getOldID()
{
return owner.toString().replaceAll("-", "");
}
}
static{
CACHE_FILE = LibZontreck.BASE_CONFIG.resolve("head_cache.nbt");
if(CACHE_FILE.toFile().exists())
{
// Deserialize heads
try {
CompoundTag tag = NbtIo.read(CACHE_FILE.toFile());
CACHE.initFromCache(tag);
} catch (IOException e) {
e.printStackTrace();
}
}else {
CACHE.resetCache();
}
List<CreditsEntry> creds = new ArrayList<>();
creds.add(
new CreditsEntry(HeadUtilities.cachedLookup("zontreck"), "Aria (zontreck)", "Developer, Designer, Artist", "Aria is the primary developer and project maintainer"));
creds.add(
new CreditsEntry(HeadUtilities.cachedLookup("PossumTheWarrior"), "PossumTheWarrior", "Tester, Adviser, Designer, Artist", "Poss has helped to test the mods from very early on. Poss has also contributed the artwork and mob model for the Possum"));
creds.add(
new CreditsEntry(HeadUtilities.cachedLookup("GemMD"), "GemMD", "Tester, Adviser, Designer", "GemMD has provided advice on marketing and development decisions for various mods"));
CREDITS = creds;
CACHE.compile();
}
private void initFromCache(CompoundTag tag)
{
ListTag heads = tag.getList("heads", Tag.TAG_COMPOUND);
for (Tag tag2 : heads) {
CompoundTag tag3 = (CompoundTag)tag2;
items.add(new HeadCacheItem(tag3));
}
}
public void saveCache()
{
try {
NbtIo.write(serialize(), CACHE_FILE.toFile());
} catch (IOException e) {
e.printStackTrace();
}
}
public CompoundTag serialize()
{
ListTag heads = new ListTag();
for (HeadCacheItem item : items) {
heads.add(item.serialize());
}
CompoundTag tag = new CompoundTag();
tag.put("heads", heads);
return tag;
}
/**
* Adds a new head to the cache
* @param owner
* @param texture
* @param name
* @return The item added to the cache
* @return Null if not added!
*/
public HeadCacheItem addToCache(UUID owner, String texture, String name)
{
HeadCacheItem item = new HeadCacheItem();
item.name=name;
item.texture=texture;
item.owner=owner;
if(!hasHead(name))
{
items.add(item);
saveCache();
return item;
}
return null;
}
/**
* Initializes the cache fresh using the default heads for the developer(s), contributors/testers, and patreon supporters
*/
public void resetCache()
{
HeadUtilities.get("zontreck", "");
HeadUtilities.get("PossumTheWarrior", "");
HeadUtilities.get("GemMD", "");
}
public List<ItemStack> compiled = new ArrayList<>();
public static final List<CreditsEntry> CREDITS;
public void compile()
{
compiled.clear();
for (CreditsEntry entry : CREDITS) {
compiled.add(entry.compile());
}
}
public boolean hasHead(String playerName)
{
for (HeadCacheItem item : items) {
if(item.name.equals(playerName)) return true;
}
return false;
}
public HeadCacheItem getHead(String playerName)
{
for (HeadCacheItem item : items) {
if(item.name.equals(playerName)) return item;
}
return null;
}
}

View file

@ -0,0 +1,67 @@
package dev.zontreck.libzontreck.util.heads;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;
import com.google.gson.Gson;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.util.HttpHelper;
import dev.zontreck.libzontreck.util.heads.HeadCache.HeadCacheItem;
import net.minecraft.world.item.ItemStack;
/**
* Added to showcase Patreon supporters and those who have helped test or provide feedback and suggestions!
*/
public class HeadUtilities {
protected static HeadCacheItem cachedLookup(String playerName)
{
if(HeadCache.CACHE.hasHead(playerName))
{
HeadCacheItem item = HeadCache.CACHE.getHead(playerName);
return item;
}else {
// Look up head then add to cache
return externalHeadRequest(playerName);
}
}
public static ItemStack get(String playerName, String itemName)
{
return cachedLookup(playerName).getAsItem(itemName);
}
private static HeadCacheItem externalHeadRequest(String playerName)
{
String data="";
try {
data = HttpHelper.getFrom(new URL(LibZontreck.PLAYER_INFO_URL + playerName));
} catch (MalformedURLException e) {
e.printStackTrace();
}
if(data.equals("")){
return null;
}
UUID PlayerID = null;
String playerTexture="";
try{
Gson gson = new Gson();
PlayerInfo info = gson.fromJson(data, PlayerInfo.class);
String data2 = HttpHelper.getFrom(new URL(LibZontreck.PLAYER_SKIN_URL + info.id));
PlayerProfileInfo info2 = gson.fromJson(data2, PlayerProfileInfo.class);
playerTexture = info2.properties.get(0).value;
PlayerID = HeadCache.HeadCacheItem.toNewID(info.id);
return HeadCache.CACHE.addToCache(PlayerID, playerTexture, playerName);
}catch(Exception e)
{
return null;
}
}
}

View file

@ -0,0 +1,6 @@
package dev.zontreck.libzontreck.util.heads;
public class PlayerInfo {
public String name;
public String id;
}

View file

@ -0,0 +1,9 @@
package dev.zontreck.libzontreck.util.heads;
import java.util.List;
public class PlayerProfileInfo {
public String id;
public String name;
public List<PlayerTextureContainer> properties;
}

View file

@ -0,0 +1,6 @@
package dev.zontreck.libzontreck.util.heads;
public class PlayerTextureContainer {
public String name;
public String value;
}

View file

@ -0,0 +1,42 @@
package dev.zontreck.libzontreck.vectors;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
public class ChunkPos {
public Points points;
public Vector2 centerPoints;
public String dim;
public ChunkPos(Vector3 point1, Vector3 point2, ServerLevel lvl)
{
points = new Points(point1, point2, lvl);
dim = WorldPosition.getDim(lvl);
}
public ChunkPos(CompoundTag tag)
{
points = new Points(tag.getCompound("points"));
centerPoints = new Vector2(tag.getCompound("center"));
}
public boolean isWithin(Vector3 point)
{
return point.inside(points.Min, points.Max);
}
public static ChunkPos getChunkPos(WorldPosition pos)
{
return pos.getChunkPos();
}
public CompoundTag serialize()
{
CompoundTag tag = new CompoundTag();
tag.put("points", points.serialize());
tag.put("center", centerPoints.serialize());
tag.putString("dim", dim);
return tag;
}
}

View file

@ -0,0 +1,63 @@
package dev.zontreck.libzontreck.vectors;
import net.minecraft.nbt.CompoundTag;
/*
* This is a non-serializable instanced Vector that is meant to slam positions down as a integer
*/
public class NonAbsVector3
{
public long x;
public long y;
public long z;
public NonAbsVector3(Vector3 origin)
{
x = Math.round(origin.x);
y = Math.round(origin.y);
z = Math.round(origin.z);
}
public CompoundTag serialize()
{
CompoundTag tag = new CompoundTag();
tag.putLong("x", x);
tag.putLong("y", y);
tag.putLong("z", z);
return tag;
}
public NonAbsVector3(CompoundTag tag) {
this.deserialize(tag);
}
public void deserialize(CompoundTag tag)
{
x=tag.getLong("x");
y=tag.getLong("y");
z=tag.getLong("z");
}
public boolean same(NonAbsVector3 other)
{
if(x == other.x && y==other.y && z==other.z)return true;
else return false;
}
public boolean inside(NonAbsVector3 point1, NonAbsVector3 point2)
{
if(point1.x <= x && point2.x >= x){
if(point1.y <= y && point2.y >= y)
{
if(point1.z <= z && point2.z >= z)
{
return true;
}
}
}
return false;
}
}

View file

@ -0,0 +1,55 @@
package dev.zontreck.libzontreck.vectors;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
/**
* Two points within the same dimension
*/
public class Points {
public Vector3 Min = Vector3.ZERO;
public Vector3 Max = Vector3.ZERO;
public String dimension = "";
/**
* Creates a new set of points
* @param min
* @param max
* @param lvl
*/
public Points(Vector3 min, Vector3 max, ServerLevel lvl)
{
dimension = WorldPosition.getDimSafe(lvl);
if(min.less(max))
{
Min=min;
Max=max;
}else{
Min=max;
Max=min;
}
}
/**
* Deserializes a points compound tag
* @param tag
*/
public Points(CompoundTag tag){
deserialize(tag);
}
public CompoundTag serialize(){
CompoundTag tag = new CompoundTag();
tag.put("min", Min.serialize());
tag.put("max", Max.serialize());
tag.putString("dim", dimension);
return tag;
}
public void deserialize(CompoundTag tag)
{
Min = new Vector3(tag.getCompound("min"));
Max = new Vector3(tag.getCompound("max"));
dimension = tag.getString("dim");
}
}

View file

@ -0,0 +1,120 @@
package dev.zontreck.libzontreck.vectors;
import dev.zontreck.libzontreck.exceptions.InvalidDeserialization;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.phys.Vec2;
public class Vector2
{
public static final Vector2 ZERO = new Vector2(0, 0);
public float x;
public float y;
public Vec2 asMinecraftVector(){
return new Vec2(x, y);
}
public Vector2()
{
}
public Vector2(float x, float y)
{
this.x=x;
this.y=y;
}
public Vector2(Vec2 pos)
{
x=pos.x;
y=pos.y;
}
public Vector2(String pos) throws InvalidDeserialization
{
// This will be serialized most likely from the ToString method
// Parse
if(pos.startsWith("<"))
{
pos=pos.substring(1, pos.length()-1); // Rip off the ending bracket too
String[] positions = pos.split(", ");
if(positions.length!=2)
{
positions = pos.split(",");
}
if(positions.length!=2)
{
throw new InvalidDeserialization("Positions must be in the same format provided by ToString() (ex. <1,1> or <1, 1>");
}
this.x = Float.parseFloat(positions[0]);
this.y = Float.parseFloat(positions[1]);
// We are done now
}
}
public Vector2 Clone()
{
Vector2 n = new Vector2(x, y);
return n;
}
@Override
public String toString()
{
return "<"+String.valueOf(x)+", "+String.valueOf(y) + ">";
}
public CompoundTag serialize()
{
CompoundTag tag = new CompoundTag();
tag.putFloat("x", x);
tag.putFloat("y", y);
return tag;
}
public Vector2(CompoundTag tag) {
this.deserialize(tag);
}
public void deserialize(CompoundTag tag)
{
x=tag.getFloat("x");
y=tag.getFloat("y");
}
public boolean same(Vector2 other)
{
if(x == other.x && y==other.y)return true;
else return false;
}
public boolean inside(Vector2 point1, Vector2 point2)
{
if(point1.x <= x && point2.x >= x){
if(point1.y <= y && point2.y >= y)
{
return true;
}
}
return false;
}
public boolean greater(Vector2 other)
{
return ((x>other.x) && (y>other.y));
}
public boolean less(Vector2 other)
{
return ((x>other.x) && (y>other.y));
}
public boolean equal(Vector2 other)
{
return same(other);
}
}

View file

@ -0,0 +1,120 @@
package dev.zontreck.libzontreck.vectors;
import dev.zontreck.libzontreck.exceptions.InvalidDeserialization;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.phys.Vec2;
public class Vector2i
{
public static final Vector2i ZERO = new Vector2i(0, 0);
public int x;
public int y;
public Vec2 asMinecraftVector(){
return new Vec2(x, y);
}
public Vector2i()
{
}
public Vector2i(int x, int y)
{
this.x=x;
this.y=y;
}
public Vector2i(Vec2 pos)
{
x= (int) Math.floor(pos.x);
y=(int)Math.floor(pos.y);
}
public Vector2i(String pos) throws InvalidDeserialization
{
// This will be serialized most likely from the ToString method
// Parse
if(pos.startsWith("<"))
{
pos=pos.substring(1, pos.length()-1); // Rip off the ending bracket too
String[] positions = pos.split(", ");
if(positions.length!=2)
{
positions = pos.split(",");
}
if(positions.length!=2)
{
throw new InvalidDeserialization("Positions must be in the same format provided by ToString() (ex. <1,1> or <1, 1>");
}
this.x = Integer.parseInt(positions[0]);
this.y = Integer.parseInt(positions[1]);
// We are done now
}
}
public Vector2i Clone()
{
Vector2i n = new Vector2i(x, y);
return n;
}
@Override
public String toString()
{
return "<"+String.valueOf(x)+", "+String.valueOf(y) + ">";
}
public CompoundTag serialize()
{
CompoundTag tag = new CompoundTag();
tag.putFloat("x", x);
tag.putFloat("y", y);
return tag;
}
public Vector2i(CompoundTag tag) {
this.deserialize(tag);
}
public void deserialize(CompoundTag tag)
{
x=tag.getInt("x");
y=tag.getInt("y");
}
public boolean same(Vector2i other)
{
if(x == other.x && y==other.y)return true;
else return false;
}
public boolean inside(Vector2i point1, Vector2i point2)
{
if(point1.x <= x && point2.x >= x){
if(point1.y <= y && point2.y >= y)
{
return true;
}
}
return false;
}
public boolean greater(Vector2i other)
{
return ((x>other.x) && (y>other.y));
}
public boolean less(Vector2i other)
{
return ((x>other.x) && (y>other.y));
}
public boolean equal(Vector2i other)
{
return same(other);
}
}

View file

@ -0,0 +1,285 @@
package dev.zontreck.libzontreck.vectors;
import java.util.ArrayList;
import java.util.List;
import dev.zontreck.libzontreck.exceptions.InvalidDeserialization;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.phys.Vec3;
public class Vector3
{
public static final Vector3 ZERO = new Vector3(0, 0, 0);
public double x;
public double y;
public double z;
public Vec3 asMinecraftVector(){
return new Vec3(x, y, z);
}
public Vec3i asMinecraftVec3i()
{
return new Vec3i((int) Math.round(x), (int) Math.round(y), (int) Math.round(z));
}
public BlockPos asBlockPos()
{
return new BlockPos(asMinecraftVec3i());
}
public Vector3()
{
}
public Vector3(double x, double y, double z)
{
this.x=x;
this.y=y;
this.z=z;
}
public Vector3(Vec3 pos)
{
x=pos.x;
y=pos.y;
z=pos.z;
}
public Vector3(BlockPos pos)
{
x=pos.getX();
y=pos.getY();
z=pos.getZ();
}
public Vector3(String pos) throws InvalidDeserialization
{
// This will be serialized most likely from the ToString method
// Parse
if(pos.startsWith("<"))
{
pos=pos.substring(1, pos.length()-1); // Rip off the ending bracket too
String[] positions = pos.split(", ");
if(positions.length!=3)
{
positions = pos.split(",");
}
if(positions.length!=3)
{
throw new InvalidDeserialization("Positions must be in the same format provided by ToString() (ex. <1,1,1> or <1, 1, 1>");
}
this.x = Double.parseDouble(positions[0]);
this.y = Double.parseDouble(positions[1]);
this.z = Double.parseDouble(positions[2]);
// We are done now
}
}
public List<Vector3> makeCube(Vector3 other)
{
List<Vector3> vecs = new ArrayList<>();
Vector3 work = new Vector3();
double xx = x;
double yy = y;
double zz = z;
int yState = 0;
int zState = 0;
int xState = 0;
for(xx = Math.round(x); (xx != Math.round(other.x) && xState != 2);)
{
for(zz = Math.round(z); (zz != Math.round(other.z) && zState != 2);)
{
for(yy = Math.round(y); (yy != Math.round(other.y) && yState != 2);)
{
work = new Vector3(xx, yy, zz);
if(!vecs.contains(work)) vecs.add(work);
if(yy > other.y)
{
yy -= 1.0;
if(yy == Math.round(other.y) && yState == 0)
{
yState++;
}else{
if(yState == 1)
{
yState ++;
}
}
} else if(yy < other.y)
{
yy += 1.0;
if(yy == Math.round(other.y) && yState == 0){
yState ++;
}else {
if(yState == 1)yState++;
}
}
}
yState=0;
work = new Vector3(xx,yy,zz);
if(!vecs.contains(work)) vecs.add(work);
if(zz > other.z)
{
zz -= 1.0;
if(zz == Math.round(other.z) && zState == 0)zState++;
else{
if(zState == 1)zState++;
}
}else if(zz < other.z)
{
zz += 1.0;
if(zz == Math.round(other.z) && zState == 0)zState++;
else {
if(zState==1)zState++;
}
}
}
zState=0;
work = new Vector3(xx,yy,zz);
if(!vecs.contains(work)) vecs.add(work);
if(xx > other.x)
{
xx -= 1.0;
if(xx == Math.round(other.x) && xState == 0) xState++;
else{
if(xState == 1)xState++;
}
}else if(xx < other.x)
{
xx += 1.0;
if(xx == Math.round(other.x) && xState==0)xState++;
else{
if(xState==1)xState++;
}
}
}
return vecs;
}
public Vector3 subtract(Vector3 other)
{
return new Vector3(x-other.x, y-other.y, z-other.z);
}
public Vector3 add(Vector3 other)
{
return new Vector3(x+other.x, y+other.y, z +other.z);
}
public double distance(Vector3 other)
{
Vector3 sub = subtract(other);
return Math.sqrt((sub.x * sub.x + sub.y * sub.y + sub.z * sub.z));
}
public Vector3 moveUp()
{
Vector3 up = Clone();
up.y+=1;
return up;
}
public Vector3 moveDown()
{
Vector3 up = Clone();
up.y-=1;
return up;
}
public Vector3 Clone()
{
Vector3 n = new Vector3(x, y, z);
return n;
}
@Override
public String toString()
{
return "<"+String.valueOf(x)+", "+String.valueOf(y)+", "+String.valueOf(z)+">";
}
public NonAbsVector3 rounded()
{
NonAbsVector3 cl = new NonAbsVector3(this);
return cl;
}
public CompoundTag serialize()
{
CompoundTag tag = new CompoundTag();
tag.putDouble("x", x);
tag.putDouble("y", y);
tag.putDouble("z", z);
return tag;
}
public Vector3(CompoundTag tag) {
this.deserialize(tag);
}
public void deserialize(CompoundTag tag)
{
x=tag.getDouble("x");
y=tag.getDouble("y");
z=tag.getDouble("z");
}
public boolean same(Vector3 other)
{
if(x == other.x && y==other.y && z==other.z)return true;
else return false;
}
public boolean inside(Vector3 point1, Vector3 point2)
{
if(point1.x <= x && point2.x >= x){
if(point1.y <= y && point2.y >= y)
{
if(point1.z <= z && point2.z >= z)
{
return true;
}
}
}
return false;
}
public boolean greater(Vector3 other)
{
return ((x>other.x) && (y>other.y) && (z>other.z));
}
public boolean less(Vector3 other)
{
return ((x<other.x) && (y<other.y) && (z<other.z));
}
public boolean equal(Vector3 other)
{
return same(other);
}
}

View file

@ -0,0 +1,127 @@
package dev.zontreck.libzontreck.vectors;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.exceptions.InvalidDeserialization;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
public class WorldPosition {
public Vector3 Position;
public String Dimension;
public String DimSafe;
public WorldPosition(CompoundTag tag, boolean pretty) throws InvalidDeserialization {
if (pretty) {
Position = new Vector3(tag.getString("Position"));
Dimension = tag.getString("Dimension");
} else {
Position = new Vector3(tag.getCompound("pos"));
Dimension = tag.getString("Dimension");
}
calcDimSafe();
}
public WorldPosition(Vector3 pos, String dim) {
Position = pos;
Dimension = dim;
calcDimSafe();
}
public WorldPosition(ServerPlayer player) {
this(new Vector3(player.position()), player.serverLevel());
}
public WorldPosition(Vector3 pos, ServerLevel lvl) {
Position = pos;
Dimension = lvl.dimension().location().getNamespace() + ":" + lvl.dimension().location().getPath();
calcDimSafe();
}
public void calcDimSafe() {
ServerLevel lvl = getActualDimension();
DimSafe = lvl.dimension().location().getNamespace() + "-" + lvl.dimension().location().getPath();
}
public static String getDimSafe(ServerLevel lvl) {
return lvl.dimension().location().getNamespace() + "-" + lvl.dimension().location().getPath();
}
/**
* Gives you the dimension string modid:dimension
*
* @param lvl
* @return dimension string
*/
public static String getDim(ServerLevel lvl) {
return lvl.dimension().location().getNamespace() + ":" + lvl.dimension().location().getPath();
}
@Override
public String toString() {
return NbtUtils.structureToSnbt(serialize());
}
public CompoundTag serializePretty() {
CompoundTag tag = new CompoundTag();
tag.putString("Position", Position.toString());
tag.putString("Dimension", Dimension);
return tag;
}
public CompoundTag serialize() {
CompoundTag tag = new CompoundTag();
tag.put("pos", Position.serialize());
tag.putString("Dimension", Dimension);
return tag;
}
public ServerLevel getActualDimension() {
String dim = Dimension;
String[] dims = dim.split(":");
ResourceLocation rl = new ResourceLocation(dims[0], dims[1]);
ServerLevel dimL = null;
for (ServerLevel lServerLevel : LibZontreck.THE_SERVER.getAllLevels()) {
ResourceLocation XL = lServerLevel.dimension().location();
if (XL.getNamespace().equals(rl.getNamespace())) {
if (XL.getPath().equals(rl.getPath())) {
dimL = lServerLevel;
}
}
}
if (dimL == null) {
LibZontreck.LOGGER.error("DIMENSION COULD NOT BE FOUND : " + Dimension);
return null;
}
return dimL;
}
public boolean same(WorldPosition other) {
return Position.same(other.Position) && Dimension == other.Dimension;
}
public ChunkPos getChunkPos() {
net.minecraft.world.level.ChunkPos mcChunk = getActualDimension().getChunkAt(Position.asBlockPos()).getPos();
ChunkPos pos = new ChunkPos(new Vector3(mcChunk.getMinBlockX(), -70, mcChunk.getMinBlockZ()), new Vector3(mcChunk.getMaxBlockX(), 400, mcChunk.getMaxBlockZ()), getActualDimension());
pos.centerPoints = new Vector2(mcChunk.getMiddleBlockX(), mcChunk.getMiddleBlockZ());
return pos;
}
}

View file

@ -6,32 +6,30 @@
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
modLoader="javafml" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
loaderVersion="[43,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
loaderVersion="${loader_version_range}" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
license="All rights reserved"
license="${mod_license}"
# A URL to refer people to when problems occur with this mod
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
issueTrackerURL="https://github.com/zontreck/LibZontreckMod/issues" #optional
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
modId="libzontreck" #mandatory
# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
# see the associated build.gradle script for how to populate this completely automatically during a build
version="1.0.0.1" #mandatory
# A display name for the mod
displayName="LibZontreck" #mandatory
# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
modId="${mod_id}" #mandatory
# The version number of the mod
version="${mod_version}" #mandatory
# A display name for the mod
displayName="${mod_name}" #mandatory
# A URL to query for updates for this mod. See the JSON update specification https://docs.minecraftforge.net/en/latest/misc/updatechecker/
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
# A URL for the "homepage" for this mod, displayed in the mod UI
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
# A file name (in the root of the mod JAR) containing a logo for display
logoFile="library.png" #optional
#logoFile="examplemod.png" #optional
# A text field displayed in the mod UI
credits="Zontreck" #optional
#credits="" #optional
# A text field displayed in the mod UI
authors="Zontreck" #optional
authors="${mod_authors}" #optional
# Display Test controls the display for your mod in the server connection screen
# MATCH_VERSION means that your mod will cause a red X if the versions on client and server differ. This is the default behaviour and should be what you choose if you have server and client elements to your mod.
# IGNORE_SERVER_VERSION means that your mod will not cause a red X if it's present on the server but not on the client. This is what you should use if you're a server only mod.
@ -41,26 +39,32 @@ authors="Zontreck" #optional
#displayTest="MATCH_VERSION" # MATCH_VERSION is the default if nothing is specified (#optional)
# The description text for the mod (multi line!) (#mandatory)
description='''
This mod provides common code to all of zontreck's mods. It by itself does absolutely nothing
'''
description='''${mod_description}'''
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
[[dependencies.libzontreck]] #optional
[[dependencies.${mod_id}]] #optional
# the modid of the dependency
modId="forge" #mandatory
# Does this dependency have to exist - if not, ordering below must be specified
mandatory=true #mandatory
# The version range of the dependency
versionRange="[43,)" #mandatory
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
versionRange="${forge_version_range}" #mandatory
# An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory
# BEFORE - This mod is loaded BEFORE the dependency
# AFTER - This mod is loaded AFTER the dependency
ordering="NONE"
# Side this dependency is applied on - BOTH, CLIENT or SERVER
# Side this dependency is applied on - BOTH, CLIENT, or SERVER
side="BOTH"
# Here's another dependency
[[dependencies.libzontreck]]
[[dependencies.${mod_id}]]
modId="minecraft"
mandatory=true
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange="[1.19.2,1.20)"
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange="${minecraft_version_range}"
ordering="NONE"
side="BOTH"
# Features are specific properties of the game environment, that you may want to declare you require. This example declares
# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't
# stop your mod loading on the server for example.
#[features.${mod_id}]
#openGLVersion="[3.2,)"

View file

@ -0,0 +1,9 @@
{
"itemGroup.tabs.libzontreck": "Aria's Library",
"item.libzontreck.chestgui_add": "Add",
"item.libzontreck.chestgui_remove": "Remove",
"item.libzontreck.chestgui_back": "Previous Page",
"item.libzontreck.chestgui_forward": "Next Page",
"item.libzontreck.chestgui_reset": "Reset"
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "libzontreck:item/chestgui_add"
}
}

Some files were not shown because too many files have changed in this diff Show more