Compare commits

...
This repository has been archived on 2024-10-31. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.

20 commits
main ... 1.19.2

Author SHA1 Message Date
5c8db873c6 Revert back to normal forge's build chain 2024-10-09 22:51:45 -07:00
bddc380f8f Bump version 2024-10-09 22:22:00 -07:00
307b3427e8 Don't jarjar anymore. 2024-10-09 22:21:30 -07:00
44eb9d1d9c Convert project to architectury 2024-10-09 21:59:58 -07:00
19b122990c Update build system fixes 2024-09-14 19:44:43 -07:00
a005e2d0ef Fix API Version number 2024-09-14 13:50:28 -07:00
472b117f70 Add a instrucion for environment var 2024-09-12 22:15:13 -07:00
a9dfaa546c Fix build! 2024-09-12 21:33:40 -07:00
93899a86d1 Bump mod version number 2024-09-12 18:02:46 -07:00
d86f5b87f1 Fix compilation errors 2024-09-12 18:00:40 -07:00
21a40835b5 Adjust maven publish path 2024-09-12 16:06:19 -07:00
792898135d Add a jenkinsfile 2024-09-12 16:05:01 -07:00
15bca9670b Backport 1.20 changes and improvements 2024-09-12 15:54:37 -07:00
e4b59167f6 Update build files 2024-09-12 15:40:26 -07:00
1c27c3da01 Increment libac and eventbus versions 2024-02-13 22:00:37 -07:00
2715c3fbb5 Increment LibZ version number 2024-02-06 22:26:57 -07:00
8319cd850a Update the LibAC package with the new one built by CI/CD 2024-02-06 22:18:35 -07:00
dabc717bd4 Update to 1.19.2 2024-01-31 17:57:01 -07:00
275288447f Add some new APIs for file and snbt 2024-01-21 17:10:26 -07:00
55acbd4868 Finish backporting libzontreck to 1.18.2 2024-01-16 17:25:12 -07:00
156 changed files with 9938 additions and 1188 deletions

51
Jenkinsfile vendored Normal file
View file

@ -0,0 +1,51 @@
pipeline {
agent any
options {
buildDiscarder(
logRotator(
numToKeepStr: '5'
)
)
}
stages {
stage("Build on Linux") {
agent {
label 'linux'
}
tools {
jdk "jdk17"
}
steps {
script {
sh '''
#!/bin/bash
git clean -xfd
git reset --hard
git fetch
export JAVA_OPTS=-Dfile.encoding=UTF-8
java -version
chmod +x gradlew
./gradlew -Dorg.gradle.java.home="$JAVA_HOME" build publish
'''
}
}
post {
always {
archiveArtifacts artifacts: "build/libs/*.jar"
deleteDir()
}
}
}
}
}

View file

@ -12,4 +12,4 @@ If the mod becomes widely used, I will begin using deprecation notices.
Compatibility
=====
1) Lightman's Currency
1) Lightman's Currency (possible future compatibility)

View file

@ -2,7 +2,6 @@ plugins {
id 'eclipse'
id 'idea'
id 'maven-publish'
id 'java-library'
id 'net.minecraftforge.gradle' version '[6.0,6.2)'
id 'org.parchmentmc.librarian.forgegradle' version '1.+'
}
@ -20,11 +19,6 @@ java {
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)
@ -39,16 +33,17 @@ 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://parchmentmc.org/docs/getting-started
// Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/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: mapping_channel, version: mapping_version
//mappings channel: mapping_channel, version: "${parchment_version}-${minecraft_version}"
mappings channel: mapping_channel, version: "${minecraft_version}"
// 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
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.
@ -58,7 +53,7 @@ minecraft {
// 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
generateRunFolders = true
// This property enables access transformers for use in development.
// They will be applied to the Minecraft artifact.
@ -66,7 +61,7 @@ minecraft {
// 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')
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
@ -87,6 +82,9 @@ 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', mod_id
mods {
"${mod_id}" {
source sourceSets.main
@ -125,11 +123,7 @@ minecraft {
sourceSets.main.resources { srcDir 'src/generated/resources' }
repositories {
//mavenCentral()
maven {
name = "Aria's Creations Caches"
url = "https://maven.zontreck.com/repository/internal"
}
mavenCentral()
// Put repositories for dependencies here
// ForgeGradle automatically adds the Forge maven and Maven Central for you
@ -145,7 +139,7 @@ repositories {
maven {
name = "zontreck Maven"
url = "https://maven.zontreck.com/repository/zontreck"
url = "https://git.zontreck.com/api/packages/AriasCreations/maven"
}
}
@ -158,15 +152,6 @@ dependencies {
// 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}"
provided "dev.zontreck:LibAC:${libac}"
implementation "dev.zontreck:LibAC:${libac}"
minecraftLibrary "dev.zontreck:LibAC:${libac}"
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}")
@ -204,11 +189,6 @@ tasks.named('processResources', ProcessResources).configure {
// Example for how to get properties into the manifest for reading at runtime.
tasks.named('jar', Jar).configure {
from {
configurations.provided.asFileTree.collect{zipTree(it)}
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes([
'Specification-Title' : mod_id,
@ -231,10 +211,12 @@ tasks.named('jar', Jar).configure {
// }
def MAVEN_PASSWORD_PROPERTY = "AriasCreationsMavenPassword"
def MAVEN_PASSWORD = "AriasCreationsMavenPassword"
def MAVEN_USER = "AriasCreationsMavenUser"
publishing {
publications {
mavenJava(MavenPublication) {
register('mavenJava', MavenPublication) {
artifact jar
artifact sourcesJar
artifact javadocJar
@ -242,13 +224,12 @@ publishing {
}
repositories {
maven {
url = "https://maven.zontreck.com/repository/zontreck"
url = "https://git.zontreck.com/api/packages/MinecraftMods/maven"
name = "ariascreations"
if (project.findProperty(MAVEN_PASSWORD_PROPERTY) != null) {
credentials {
username = "admin"
password = project.findProperty(MAVEN_PASSWORD_PROPERTY)
}
credentials {
username = project.findProperty(MAVEN_USER)
password = project.findProperty(MAVEN_PASSWORD)
}
}
}

View file

@ -1,460 +0,0 @@
1.19.x Changelog
43.1
====
- 43.1.1 Add ability to Auto register capabilities via annotation (#8972)
- 43.1.0 1.19.2 RB
43.0
====
- 43.0.22 Added ItemDecorator API (#8794)
- 43.0.21 [1.19.x] Custom usage animations for items (#8932)
- 43.0.20 Allow registering custom `ColorResolver`s (#8880)
- 43.0.19 [1.19] Allow custom outline rendering on EntityRenderers and BlockEntityRenderers (#8938)
- 43.0.18 Redirect checks for entity selector use to a permission (#8947)
This allows greater flexibility for configuring servers with
operator-like permissions to user groups through the permissions API and
their permissions handler of choice without needing to grant the
vanilla operator permission to any player.
The new permission is "forge:use_entity_selectors", which is granted by
default to players with permission level 2 (GAMEMASTERS) and above.
The hook falls back to checking the permission level if the source of
the command is not a ServerPlayer, such as for command blocks and
functions.
- 43.0.17 Allow FakePlayer to report its position (#8963)
- 43.0.16 Add alternate version of renderEntityInInventory to allow for directly specifying the angles (#8961)
- 43.0.15 Add cancellable ToastAddEvent (#8952)
- 43.0.14 Modify ScreenEvent.RenderInventoryMobEffects to allow moving the effect stack left or right (#8951)
- 43.0.13 Fix Enchantment#doPostHurt and Enchantment#doPostAttack being called twice for players. Fixes MC-248272 (#8948)
- 43.0.12 Remove reflective implementation of ICustomPacket. (#8973)
Make vanilla custom packets able to be sent multiple times. Closes #8969
- 43.0.11 Filter name spaces to directories only. Closes #8413
- 43.0.10 Fix a corner case where the UMLB can not extract a version from a library. (#8967)
- 43.0.9 Fix worlds with removed dimension types unable to load. (#8959) Closes #8800
- 43.0.8 Fix issue where unknown chunk generators would cause DFU to fail. (#8957)
- 43.0.7 Fix comments and documentation that were missed during the review of #8712 (#8945)
- 43.0.6 Make AnvilUpdateEvent fire even if the second input is empty, which means it fires even if only changing the item name. (#8905)
- 43.0.5 Fix `LivingEntity#isBlocking` to use `ToolActions#SHIELD_BLOCK` instead of `UseAnim#BLOCK` (#8933)
- 43.0.4 Add Custom HolderSet Types allowing for logical combining of sets. (#8928)
- 43.0.3 Add values to VersionSupportMatrix to support loading mods that restrict versions to 1.19.1 on 1.19.2 (#8946)
- 43.0.2 Fix certain particles not updating their bounding box when their position changes (#8925)
- 43.0.1 Update EventBus to address concurrency issue in ModLauncher Factory. Closes #8924
- 43.0.0 1.19.2
42.0
====
- 42.0.9 Remove calls to getStepHeight in Player#maybeBackOffFromEdge (#8927)
- 42.0.8 Add forge tags for tools and armors, these DO NOT replace ToolActions, and are designed just for Recipes. (#8914)
- 42.0.7 Add Biomes.BEACH to Tags (#8892)
- 42.0.6 Let NetworkInstance.isRemotePresent check minecraft:register for channel IDs. (#8921)
- 42.0.5 Add an event for when the chunk ticket level is updated (#8909)
- 42.0.4 Re-add PotentialSpawns event (#8712)
- 42.0.3 Fix misplaced patch in ItemEntityRenderer breaking ItemEntityRenderer#shouldBob() (#8919)
- 42.0.2 [1.19] [HotFix] Fix the dedicated server not having access to the JiJ filesystems. (#8931)
- 42.0.1 Match Mojang's action bar fix for MC-72687 (#8917)
- 42.0.0 Forge 1.19.1
Load natives from classpath
Make command argument types a forge registry
Add `EntityMobGriefingEvent` to `Allay#wantsToPickUp`
Overhaul `ServerChatEvent` to use `ChatDecorator` system
Remove `ClientChatEvent#setMessage` for now
Gradle 7.5
41.1
====
- 41.1.0 Mark 1.19 RB
41.0
====
- 41.0.113 Allow faces of an "elements" model to be made emissive (#8890)
- 41.0.112 Fix invalid channel names sent from the server causing the network thread to error. (#8902)
- 41.0.111 Fix PlayerEvent.BreakSpeed using magic block position to signify invalid position. Closes #8906
- 41.0.110 Fix cases where URIs would not work properly with JarInJar (#8900)
- 41.0.109 Add new hook to allow modification of lightmap via Dimension special effects (#8863)
- 41.0.108 Fix Forge's packet handling on play messages. (#8875)
- 41.0.107 Add API for tab list header/footer (#8803)
- 41.0.106 Allow modded blocks overriding canStickTo prevent sticking to vanilla blocks/other modded blocks (#8837)
- 41.0.105 Multiple tweaks and fixes to the recent changes in the client refactor PR: Part 3 (#8864)
Fix weighted baked models not respecting children render types
Allow fluid container model to use base texture as particle
Fix inverted behavior in composite model building. Fixes #8871
- 41.0.104 Fix crossbows not firing ArrowLooseEvent (#8887)
- 41.0.103 Add User-Agent header to requests made by the update checker (#8881)
Format: Java-http-client/<Java version> MinecraftForge/<ForgeVer> <ModId>/<ModVersion>
- 41.0.102 Output the full path in a crash report so it is easier to find the outer mod when a crash in Jar-In-Jar occurs. (#8856)
- 41.0.101 Clean up the pick item ("middle mouse click") patches (#8870)
- 41.0.100 [1.19.x] Hotfix for test mods while the refactor is ongoing
- 41.0.99 add event to SugarCaneBlock (#8877)
- 41.0.98 Fix Global Loot Modifiers not using Dispatch Codec (#8859)
- 41.0.97 Allow block render types to be set in datagen (#8852)
- 41.0.96 Fix renderBreakingTexture not using the target's model data (#8849)
- 41.0.95 Multiple tweaks and fixes to the recent changes in the client refactor PR: Part 2 (#8854)
* Add getter for the component names in an unbaked geometry
* Fix render type hint not being copied in BlockGeometryBakingContext
* Ensure BlockRenderDispatches's renderSingleBlock uses the correct buffer
- 41.0.94 [1.19.x] Apply general renames, A SRG is provided for modders. (#8840)
See https://gist.github.com/SizableShrimp/882a671ff74256d150776da08c89ef72
- 41.0.93 Fix mob block breaking AI not working correctly when chunk 0,0 is unloaded. Closes #8853
- 41.0.92 Fix crash when breaking blocks with multipart models and remove caching. Closes #8850
- 41.0.91 Fixed `CompositeModel.Baked.Builder.build()` passing arguments in the wrong order (#8846)
- 41.0.90 Make cutout mipmaps explicitly opt-in for item/entity rendering (#8845)
* Make cutout mipmaps explicitly opt-in for item/entity rendering
* Default render type domain to "minecraft" in model datagens
- 41.0.89 Fixed multipart block models not using the new model driven render type system. (#8844)
- 41.0.88 Update to the latest JarJar to fix a collision issue where multiple jars could provide an exact match. (#8847)
- 41.0.87 Add FML config to disable DFU optimizations client-side. (#8842)
* Add client-side command line argument to disable DFU optimizations.
* Switch to using FMLConfig value instead.
- 41.0.86 [1.19] Fixed broken BufferBuilder.putBulkData(ByteBuffer) added by Forge (#8819)
* Fixes BufferBuilder.putBulkData(ByteBuffer)
* use nextElementByte
* Fixed merge conflict
- 41.0.85 [1.19.x] Fix shulker boxes allowing input of items, that return false for Item#canFitInsideContainerItems, through hoppers. (#8823)
* Make ShulkerBoxBlockEntity#canPlaceItemThroughFace delegate to Item#canFitInsideContainerItems.
* Switch to using Or and add comment.
* Switch Or to And.
- 41.0.84 [1.19.x] Added RenderLevelStageEvent to replace RenderLevelLastEvent (#8820)
* Ported RenderLevelStageEvent from 1.18.2
* Updated to fix merge conflicts
- 41.0.83 [1.19.x] Fix door datagenerator (#8821)
* Fix door datagenerator
Fix datagenerator for door blocks. Successor to #8687, addresses comments made there about statement complexity.
* Fix extra space around parameter
Fix extra space before comma around a parameter.
- 41.0.82 Create PieceBeardifierModifier to re-enable piecewise beardifier definitions (#8798)
- 41.0.81 Allow blocks to provide a dynamic MaterialColor for display on maps (#8812)
- 41.0.80 [1.19.x] BiomeTags Fixes/Improvements (#8711)
* dimension specific tag fix
* remove forge:is_beach cause vanilla has it already
* remove forge tags for new 1.19 vanilla tags (savanna, beach, overworld, end)
Co-authored-by: Flemmli97 <Flemmli97@users.noreply.github.com>
- 41.0.79 1.19 - Remove GlobalLootModifierSerializer and move to Codecs (#8721)
* convert GLM serializer class to codec
* cleanup
* GLM list needs to be sorted
* datagen
* simplify serialization
* fix test mods (oops)
* properly use suppliers for codec as they are registry obj
- 41.0.78 Implement item hooks for potions and enchantments (#8718)
* Implement item hooks for potions and enchantments
* code style fixes
- 41.0.77 Re-apply missing patch to ServerLevel.EntityCallbacks#onTrackingEnd() (#8828)
- 41.0.76 Double Bar Rendering fixed (#8806) (#8807)
* Double Bar Rendering fixed (#8806)
* Added requested changes by sciwhiz12
- 41.0.75 Multiple tweaks and fixes to the recent changes in the client refactor PR (#8836)
* Add an easy way to get the NamedGuiOverlay from a vanilla overlay
* Fix static member ordering crash in UnitTextureAtlasSprite
* Allow boss bar rendering to be cancelled
* Make fluid container datagen use the new name
- 41.0.74 Add FogMode to ViewportEvent.RenderFog (#8825)
- 41.0.73 Provide additional context to the getFieldOfView event (#8830)
- 41.0.72 Pass renderType to IForgeBakedModel.useAmbientOcclusion (#8834)
- 41.0.71 Load custom ITransformationServices from the classpath in dev (#8818)
* Add a classpath transformer discoverer to load custom transformation services from the classpath
* Update ClasspathTransformerDiscoverer to 1.18
* Update license year
* Update license header
* Fix the other license headers
* Update ClasspathTransformerDiscoverer to 1.19
- 41.0.70 Handle modded packets on the network thread (#8703)
* Handle modded packets on the network thread
- On the server we simply need to remove the call to
ensureRunningOnSameThread.
- On the client side, we now handle the packet at the very start of the
call. We make sure we're running from a network thread to prevent
calling the handling code twice.
While this does mean we no longer call .release(), in practice this
doesn't cause any leaks as ClientboundCustomPayloadPacket releases
for us.
* Clarify behaviour a little in the documentation
* Javadoc formatting
* Add a helper method for handling packets on the main thread
Also rename the network thread one. Should make it clearer the expected
behaviour of the two, and make it clearer there's a potentially breaking
change.
* Add back consumer() methods
Also document EventNetworkChannel, to clarify the thread behaviour
there.
* Add since = "1.19" to deprecated annotations
- 41.0.69 Cache resource listing calls in resource packs (#8829)
* Make the resource lookups cached.
* Include configurability and handle patch cleanup.
* Document and comment the cache manager.
* Make thread selection configurable.
* Implement a configurable loading mechanic that falls back to default behaviour when the config is not bound yet.
* Use boolean supplier and fix wildcard import.
* Clean up the VPR since this is more elegant.
* Clean up the VPR since this is more elegant.
* Address review comments.
* Address more review comments.
* Fix formatting on `getSource`
* Address comments by ichtt
* Adapt to pups requests.
* Stupid idea.
* Attempt this again with a copy on write list.
* Fix a concurrency and loading issue.
* Fix #8813
Checks if the paths are valid resource paths.
* Move the new methods on vanilla Patch.
- 41.0.68 Update SJH and JIJ
- 41.0.67 Fix #8833 (#8835)
- 41.0.66 Fix backwards fabulous check in SimpleBakedModel (#8832)
Yet another blunder we missed during the review of #8786.
- 41.0.65 Make texture atlas in StandaloneGeometryBakingContext configurable (#8831)
- 41.0.64 [1.19.X] Client code cleanup, updates, and other refactors (#8786)
* Revert "Allow safely registering RenderType predicates at any time (#8685)"
This reverts commit be7275443fd939db9c58bcad47079c3767789ac1.
* Renderable API refactors
- Rename "render values" to "context"
- Rename SimpleRenderable to CompositeRenderable to better reflect its use
- Remove IMultipartRenderValues since it doesn't have any real use
- Add extensive customization options to BakedModelRenderable
* ClientRegistry and MinecraftForgeClient refactors
- Add sprite loader manager and registration event
- Add spectator shader manager and registration event
- Add client tooltip factory manager and registration event
- Add recipe book manager and registration event
- Add key mapping registration event
- Remove ClientRegistry, as everything has been moved out of it
- Remove registration methods from MinecraftForgeClient, as they have dedicated events now
* Dimension special effects refactors
- Fold handlers into an extension class and remove public mutable fields
- Add dimension special effects manager and registration event
* HUD overlay refactors
- Rename to IGuiOverlay match vanilla (instead of Ingame)
- Add overlay manager and registration event
- Move vanilla overlays to a standalone enum
* Model loader refactors
- Rename IModelLoader to IGeometryLoader
- Add loader manager and registration event
- Fold all model events into one
- Move registration of additionally loaded models to an event
- Remove ForgeModelBakery and related classes as they served no purpose anymore
* Render properties refactors
- Rename all render properties to client extensions and relocate accordingly
- Move lookups to the respective interfaces
* Model data refactors
- Convert model data to a final class backed by an immutable map and document mutability requirements. This addresses several thread-safety issues in the current implementation which could result in race conditions
- Transfer ownership of the data manager to the client level. This addresses several issues that arise when multiple levels are used at once
* GUI and widget refactors
- Move all widgets to the correct package
- Rename GuiUtils and children to match vanilla naming
* New vertex pipeline API
- Move to vanilla's VertexConsumer
- Roll back recent PR making VertexConsumer format-aware. This is the opposite of what vanilla does, and should not be relevant with the updated lighting pipeline
* Lighting pipeline refactors
- Move to dedicated lighting package
- Separate flat and smooth lighters
- Convert from a vertex pipeline transformer to a pure vertex source (input is baked quads)
* Model geometry API refactors
- Rename IModelGeometry to IUnbakedGeometry
- Rename IModelConfiguration to IGeometryBakingContext
- Rename other elements to match vanilla naming
- Remove current changes to ModelState, as they do not belong there. Transforms should be specified through vanilla's system. ModelState is intended to transfer state from the blockstate JSON
- Remove multipart geometries and geometry parts. After some discussion, these should not be exposed. Instead, geometries should be baked with only the necessary parts enabled
* Make render types a first-class citizen in baked models
- Add named render types (block + entity + fabulous entity)
- Add named render type manager + registration event
- Make BakedModel aware of render types and transfer control over which ones are used to it instead of ItemBlockRenderTypes (fallback)
- (additional) Add concatenated list view. A wrapper for multiple lists that iterates through them in order without the cost of merging them. Useful for merging lists of baked quads
* General event refactors
- Several renames to either match vanilla or improve clarity
- Relocate client chat event dispatching out of common code
* Forge model type refactors
- Rename SeparatePerspectiveModel to SeparateTransformsModel
- Rename ItemModelMesherForge to ForgeItemModelShaper
- Rename DynamicBucketModel to DynamicFluidContainerModel
- Prefix all OBJ-related classes with "Obj" and decouple parsing from construction
- Extract ElementsModel from model loader registry
- Add EmptyModel (baked, unbaked and loader)
- Refactor CompositeModel to take over ItemMultiLayerBakedModel
- Remove FluidModel as it's not used and isn't compatible with the new fluid rendering in modern versions
- Move model loader registration to a proper event handler
- Update names of several JSON fields (backwards-compatible)
- Update datagens to match
* Miscellaneous changes and overlapping patches
- Dispatch all new registration events
- Convert ExtendedServerListData to a record
- Add/remove hooks from ForgeHooksClient as necessary
* Update test mods
* Fix VertexConsumerWrapper returning parent instead of itself
* Additional event cleanup pass
As discussed on Discord:
- Remove "@hidden" and "@see <callsite>" javadoc annotations from all client events and replace them with @ApiStatus.Internal annotation
- Make all events that shouldn't be fired directly into abstract classes with protected constructors
- Another styling pass, just in case (caught some missed classes)
* Add proper deprecation javadocs and de-dupe some vertex consumer code
* Replace sets of chunk render types with a faster BitSet-backed collection
This largely addresses potential performance concerns that using a plain HashSet might involve by making lookups and iteration as linear as they can likely be (aside from using a plain byte/int/long for bit storage). Further performance concerns related to the implementation may be addressed separately, as all the implementation details are hidden from the end user
* Requested changes
- Remove MinecraftForgeClient and move members to Minecraft, IForgeMinecraft and StencilManager
- Allow non-default elements to be passed into VertexConsumer and add support to derived classes
- Move array instantiation out of quad processing in lighting pipeline
- Fix flipped fluid container model
- Set default UV1 to the correct values in the remapping pipeline
- Minor documentation changes
* Add/update EXC entries and fix AT comment
* Add test mod as per Orion's request
* Additional requested changes
* Allow custom model types to request the particle texture to be loaded
* Even more requested changes
* Improve generics in ConcatenatedListView and add missing fallbacks
* Fix fluid render types being bound to the fluid and not its holder
* Remove non-contractual nullability in ChunkRenderTypeSet and add isEmpty
Additionally, introduce chunk render type checks in ItemBlockRenderTypes
Co-authored-by: Dennis C <xfacthd@gmx.de>
- 41.0.63 Implement full support for IPv6 (#8742)
- 41.0.62 Fix certain user-configured options being overwritten incorrectly due to validators. (#8780)
- 41.0.61 Allow safely registering RenderType predicates at any time (#8685)
- 41.0.60 Fix crash after loading error due to fluid texture gathering and config lookup (#8802)
- 41.0.59 Remove the configuration option for handling empty tags in ingredients. (#8799)
Now empty tags are considered broken in all states.
- 41.0.58 Fix MC-105317 Structure blocks do not rotate entities correctly when loading (#8792)
- 41.0.57 Fire ChunkWatchEvents after sending packets (#8747)
- 41.0.56 Add item handler capability to chest boats (#8787)
- 41.0.55 Add getter for correct BiomeSpecialEffectsBuilder to BiomeInfo$Builder (#8781)
- 41.0.54 Fix BlockToolModificationEvent missing cancelable annotation (#8778)
- 41.0.53 Fix ticking chunk tickets from forge's chunk manager not causing chunks to fully tick (#8775)
- 41.0.52 Fix default audio device config loading string comparison issue (#8767)
- 41.0.51 Fix missed vanilla method overrides in ForgeRegistry (#8766)
- 41.0.50 Add MinecraftServer reference to ServerTickEvent (#8765)
- 41.0.49 Fix TagsProviders for datapack registries not recognizing existing files (#8761)
- 41.0.48 Add callback after a BlockState was changed and the neighbors were updated (#8686)
- 41.0.47 Add biome tag entries for 1.19 biomes (#8684)
- 41.0.46 Make fishing rods use tool actions for relevant logic (#8681)
- 41.0.45 Update BootstrapLauncher to 1.1.1 and remove the forced
merge of text2speech since new BSL does it.
- 41.0.44 Merge text2speech libs together so the natives are part of the jar
- 41.0.43 Make Forge ConfigValues implement Supplier. (#8776)
- 41.0.42 Fix merge derp in AbstractModProvider and logic derp in ModDiscoverer
- 41.0.41 Add "send to mods in order" method to ModList and use it (#8759)
* Add "send to mods in order" method to ModList and use it in RegistryEvents and DataGen..
* Also preserve order in runAll
* Do better comparator thanks @pupnewfster
* postEvent as well.
- 41.0.40 Update SJH to 2.0.2.. (#8774)
* Update SJH to 2.0.3..
- 41.0.39 Sanity check the version specified in the mod file (#8749)
* Sanity check the version specified in the mod file to
make sure it's compatible with JPMS standards for
version strings.
Closes #8748
Requires SPI 6
- 41.0.38 Fix SP-Devtime world loading crash due to missing server configs (#8757)
- 41.0.37 Remove ForgeWorldPreset and related code (#8756)
Vanilla has a working replacement.
- 41.0.36 Change ConfigValue#get() to throw if called before config loaded (#8236)
This prevents silent issues where a mod gets the value of the setting
before configs are loaded, which means the default value is always
returned.
As there may be situations where the getting the config setting before
configs are loaded is needed, and it is not preferable to hardcode the
default value, the original behavior is made available through #getRaw.
Implements and closes #7716
* Remove getRaw() method
This is effectively replaced with the expression `spec.isLoaded() ?
configValue.get() : configValue.getDefault()`.
* Remove forceSystemNanoTime config setting
As implemented, it never had any effect as any place where the config
value would be queried happens before the configs are loaded.
- 41.0.35 Fix EnumArgument to use enum names for suggestions (#8728)
Previously, the suggestions used the string representation of the enum
through Enum#toString, which can differ from the name of the enum as
required by Enum#valueOf, causing invalid suggestions (both in gui and
through the error message).
- 41.0.34 Jar-In-Jar (#8715)
- 41.0.33 [1.19] Fix data-gen output path of custom data-pack registries (#8724)
- 41.0.32 Fix player dive and surface animations in custom fluids (#8738)
- 41.0.31 [1.19.x] Affect ItemEntity Motion in Custom Fluids (#8737)
- 41.0.30 [1.19] Add support for items to add enchantments without setting them in NBT (#8719)
- 41.0.29 [1.19.x] Add stock biome modifier types for adding features and spawns (#8697)
- 41.0.28 [1.19.x] Fluid API Overhaul (#8695)
- 41.0.27 Replace StructureSpawnListGatherEvent with StructureModifiers (#8717)
- 41.0.26 Use stack sensitive translation key by default for FluidAttributes. (#8707)
- 41.0.25 Delete LootItemRandomChanceCondition which added looting bonus enchantment incorrectly. (#8733)
- 41.0.24 Update EventBus to 6.0, ModLauncher to 10.0.1 and BootstrapLauncher to 1.1 (#8725)
- 41.0.23 Replace support bot with support action (#8700)
- 41.0.22 Fix Reach Distance / Attack Range being clamped at 6.0 (#8699)
- 41.0.21 [1.19.x] Fix mods' worldgen data not being loaded when creating new singleplayer worlds (#8693)
- 41.0.20 [1.19.x] Fix experimental confirmation screen (#8727)
- 41.0.19 Move is_mountain to forge's tag instead of vanilla's (#8726)
- 41.0.18 [1.19.x] Add CommandBuildContext to Register Command Events (#8716)
- 41.0.17 Only rewrite datagen cache when needed (#8709)
- 41.0.16 Implement a simple feature system for Forge (#8670)
* Implement a simple feature system for Forge. Allows mods to demand certain features are available in the loading system. An example for java_version is provided, but not expected to be used widely. This is more targeted to properties of the display, such as GL version and glsl profile.
Requires https://github.com/MinecraftForge/ForgeSPI/pull/13 to be merged first in ForgeSPI, and the SPI to be updated appropriately in build.gradle files.
* rebase onto 1.19 and add in SPI update
- 41.0.15 displayTest option in mods.toml (#8656)
* displayTest option in mods.toml
* "MATCH_VERSION" (or none) is existing match version string behaviour
* "IGNORE_SERVER_VERSION" accepts anything and sends special SERVERONLY string
* "IGNORE_ALL_VERSION" accepts anything and sends an empty string
* "NONE" allows the mod to supply their own displaytest using the IExtensionPoint mechanism.
* Update display test with feedback and added the mods.toml discussion in mdk.
- 41.0.14 Update forgeSPI to v5 (#8696)
- 41.0.13 Make IVertexConsumers such as the lighting pipeline, be aware of which format they are dealing with. (#8692)
Also fix Lighting pipeline ignoring the overlay coords from the block renderer.
- 41.0.12 Fixed misaligned patch to invalidateCaps in Entity (#8705)
- 41.0.11 Fix readAdditionalLevelSaveData (#8704)
- 41.0.10 Fixes setPos to syncPacketPositionCodec (#8702)
- 41.0.9 Fix wrong param passed to PlayLevelSoundEvent.AtEntity (#8688)
- 41.0.8 Override initialize in SlotItemHandler, so it uses the itemhandler instead of container (#8679)
- 41.0.7 Update MDK for 1.19 changes (#8675)
- 41.0.6 Add helper to RecipeType, and fix eclipse compiler error in test class.
- 41.0.5 Update modlauncher to latest (#8691)
- 41.0.4 Fix getting entity data serializer id crashing due to improper port to new registry system (#8678)
- 41.0.3 Fire registry events in the order vanilla registers to registries (#8677)
Custom registries are still fired in alphabetical order, after all vanilla registries.
Move forge's data_serializers registry to forge namespace.
- 41.0.2 Add method with pre/post wrap to allow setting/clearing mod context. (#8682)
Fixes ActiveContainer in ModContext not being present in registry events. Closes #8680
- 41.0.1 Fix the Curlie oopsie
- 41.0.0 Forge 1.19
* Bump pack.mcmeta formats
* 1.19 biome modifiers
* Mark ClientPlayerNetworkEvent.LoggedOutEvent's getters as nullable
* Add docs and package-info to client extension interfaces package
* Move RenderBlockOverlayEvent hooks to ForgeHooksClient
* Add package-infos to client events package
* Rename SoundLoadEvent to SoundEngineLoadEvent
This reduces confusion from consumers which may think the
name SoundLoadEvent refers to an individual sound being loaded rather
than the sound engine.
* Document and change SoundLoadEvent to fire on mod bus
Previously, it fired on both the mod bus and the Forge bus, which is
confusing for consumers.
* Delete SoundSetupEvent
Looking at its original implementation shows that there isn't an
appropriate place in the new sound code to reinsert the event, and the
place of 'sound engine/manager initialization event' is taken already by SoundLoadEvent.
* Perform some cleanup on client events
- Removed nullable annotations from ClientPlayerNetworkEvent
- Renamed #getPartialTicks methods to #getPartialTick, to be consistent
with vanilla's naming of the partial tick
- Cleanup documentation to remove line breaks, use the
spelling 'cancelled' over
'canceled', and improve docs on existing and
new methods.
* Remove EntityEvent.CanUpdate
Closes MinecraftForge/MinecraftForge#6394
* Switch to Jetbrains nullability annotations
* New PlayLevelSoundEvent; replaces old PlaySoundAtEntityEvent
* Remove ForgeWorldPresetScreens
* Remove IForgeRegistryEntry
* Remove use of List<Throwable> in FML's CompletableFutures
* Add docs to mod loading stages, stages, and phases
* Gradle 7.4.2
* Use SLF4J in FMLLoader and other subprojects
* Switch dynamic versions in subprojects to pinned ones
* Switch ForgeRoot and MDK to FG plugin markers
* Configure Forge javadoc task
The task now uses a custom stylesheet with MCForge elements, and
configured to combine the generation from the four FML subprojects
(fmlloader, fmlcore, javafmllanguage, mclanguage) and the Forge project
into the javadoc output.
* Update docs/md files, for 1.19 update and the move away from IRC to Discord.
* Make "Potentially dangerous alternative prefix" a debug warning, not info.
Co-authored-by: Curle <curle@gemwire.uk>
Co-authored-by: sciwhiz12 <arnoldnunag12@gmail.com>

View file

@ -1,28 +1,20 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
# This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx3G
org.gradle.jvmargs=-Xmx3G -Dfile.encoding=utf-8
org.gradle.daemon=false
parchment_version=2023.09.03
# luckperms_api_version=5.4
libac=1.4.18
eventsbus=1.0.31
## Environment Properties
# The Minecraft version must agree with the Forge version to get a valid artifact
minecraft_version=1.20.1
minecraft_version=1.19.2
# 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)
minecraft_version_range=[1.19.2,1.20)
# The Forge version must agree with the Minecraft version to get a valid artifact
forge_version=47.2.0
forge_version=43.4.2
# The Forge version range can use any version of Forge as bounds or match the loader version range
forge_version_range=[47,)
forge_version_range=[43,)
# The loader version range can only use the major version of Forge/FML as bounds
loader_version_range=[47,)
loader_version_range=[43,)
# 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.
@ -37,14 +29,15 @@ loader_version_range=[47,)
#
# 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
mapping_channel=official
# 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
parchment_version=2022.11.27
# luckperms_api_version=5.4
libac=1.5.33
eventsbus=1.0.48
## Environment Properties
## 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
@ -53,7 +46,7 @@ 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.011524.0045
mod_version=1192.13.100924.2250
# 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

Binary file not shown.

View file

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

12
gradlew vendored
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/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/master/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,11 +80,11 @@ do
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# 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,16 +143,12 @@ 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,7 +26,6 @@ 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%

View file

@ -1,10 +1,14 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven { url = "https://maven.zontreck.com/repository/internal" }
maven {
name = 'MinecraftForge'
url = 'https://maven.minecraftforge.net/'
}
maven { url = 'https://maven.parchmentmc.org' } // Add this line
}
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
}

View file

@ -0,0 +1,106 @@
package dev.zontreck.ariaslib.args;
import dev.zontreck.ariaslib.exceptions.WrongArgumentTypeException;
public abstract class Argument<T> implements Cloneable
{
public boolean hasValue = false;
public String name;
/**
* Initializes a boolean only command line toggle
*
* @param name The option name
*/
public Argument(String name) {
this.name = name;
}
/**
* Retrieves the current argument's type
*
* @return The argument type!
*/
public abstract ArgumentType getType();
/**
* Retrieves the value.
*
* @return The value
* @throws IllegalArgumentException When there is no value
*/
public T getValue() throws IllegalArgumentException {
throw new IllegalArgumentException("No value");
}
/**
* Directly cast to the Argument type Long
* @return
* @throws WrongArgumentTypeException Throws when type does not match
*/
public LongArgument getAsLong() throws WrongArgumentTypeException {
if(this instanceof LongArgument)
{
return (LongArgument) this;
}
throw new WrongArgumentTypeException();
}
/**
* Directly cast to the Argument type String
* @return
* @throws WrongArgumentTypeException Throws when type does not match
*/
public StringArgument getAsString() throws WrongArgumentTypeException {
if(this instanceof StringArgument)
{
return (StringArgument) this;
}
throw new WrongArgumentTypeException();
}
/**
* Directly cast to the Argument type Integer
* @return
* @throws WrongArgumentTypeException Throws when type does not match
*/
public IntegerArgument getAsInteger() throws WrongArgumentTypeException
{
if(this instanceof IntegerArgument)
{
return (IntegerArgument) this;
}
throw new WrongArgumentTypeException();
}
@Override
public Argument<T> clone() {
Argument<T> arg = null;
try{
if(getType() == ArgumentType.LONG)
{
arg = (Argument<T>) new LongArgument(name, getAsLong().getValue());
} else if(getType() == ArgumentType.STRING)
{
arg = (Argument<T>) new StringArgument(name, getAsString().getValue());
} else if(getType() == ArgumentType.BOOLEAN) {
arg = (Argument<T>) new BooleanArgument(name);
} else if(getType() == ArgumentType.INTEGER){
arg = (Argument<T>) new IntegerArgument(name, getAsInteger().getValue());
}
}catch (WrongArgumentTypeException ex)
{
ex.printStackTrace();
}
return arg;
}
}

View file

@ -0,0 +1,25 @@
package dev.zontreck.ariaslib.args;
public enum ArgumentType {
/**
* This indicates a string. It may possibly have a default value
*/
STRING,
/**
* This indicates a boolean
* <p>
* This may have a default value, which initiates a BooleanArgument
*/
BOOLEAN,
/**
* This indicates a data type of integer
* The type of integer arg is determined by the length of the integer.
*/
INTEGER,
/**
* This is a long value, which can hold larger values than a integer. The type of integer arg is determined by the length of the integer.
*/
LONG
}

View file

@ -0,0 +1,63 @@
package dev.zontreck.ariaslib.args;
import java.util.HashMap;
import java.util.Map;
public class Arguments implements Cloneable
{
private Map<String, Argument<?>> args = new HashMap<>();
/**
* Set the argument in the args list
* @param arg
*/
public void setArg(Argument arg) {
args.put(arg.name, arg);
}
/**
* Checks for and returns the argument
*
* @param argName The argument's name
* @return The argument instance, or null if not found
*/
public Argument getArg(String argName) {
if (hasArg(argName))
return args.get(argName);
else return null;
}
/**
* Checks if the argument is set.
*
* @param argName The argument's name to check for
* @return True if the argument is present. This does not indicate if the argument has a value
*/
public boolean hasArg(String argName) {
return args.containsKey(argName);
}
/**
* Checks the argument (if it exists), for whether a value is set
*
* @param argName This is the argument name
* @return True if a value is set
* @throws IllegalArgumentException If there is no such argument
*/
public boolean argHasValue(String argName) throws IllegalArgumentException {
if (hasArg(argName)) {
return getArg(argName).hasValue;
} else throw new IllegalArgumentException(("No such argument"));
}
@Override
public Arguments clone() {
Arguments arg = new Arguments();
for(Map.Entry<String, Argument<?>> entry : args.entrySet())
{
arg.setArg(entry.getValue().clone());
}
return arg;
}
}

View file

@ -0,0 +1,20 @@
package dev.zontreck.ariaslib.args;
public class ArgumentsBuilder {
private Arguments args = new Arguments();
public static ArgumentsBuilder builder() {
return new ArgumentsBuilder();
}
public ArgumentsBuilder withArgument(Argument arg) {
args.setArg(arg);
return this;
}
public Arguments build()
{
return args;
}
}

View file

@ -0,0 +1,99 @@
package dev.zontreck.ariaslib.args;
public class ArgumentsParser {
/**
* Parses and returns the arguments list with keeping defaults in mind
* @param args
* @param defaults
* @return Arguments with defaults set
*/
public static Arguments parseArguments(String[] args, Arguments defaults) {
Arguments arguments = defaults.clone();
for (int i = 0; i < args.length; i++) {
Argument arg = parseArgument(args[i]);
if (arg != null) {
Argument defaultArg = null;
if (defaults.hasArg(arg.name)) {
defaultArg = defaults.getArg(arg.name);
}
if (!arg.hasValue) {
if (defaultArg != null) {
arg = defaultArg;
}
}
arguments.setArg(arg);
}
}
return arguments;
}
/**
* Parses and returns an argument with a type set
* @param arg The argument to parse with double tack
* @return Typed Argument
* @throws IllegalArgumentException when no type matches and the input is malformed in some way
*/
public static Argument parseArgument(String arg) {
if (arg.startsWith("--")) {
String[] parts = arg.split("=");
String name = getNamePart(parts[0]);
if (parts.length == 1) {
return new BooleanArgument(name);
} else if (parts.length == 2) {
String value = getValuePart(parts[1]);
ArgumentType typeOfArg = getArgumentType(value);
switch(typeOfArg)
{
case INTEGER:
{
return new IntegerArgument(name, Integer.parseInt(value));
}
case LONG:
{
return new LongArgument(name, Long.parseLong(value));
}
case BOOLEAN:
{
return new BooleanArgument(name);
}
default:
{
return new StringArgument(name, value);
}
}
} else throw new IllegalArgumentException("The argument is malformed. Remember to use --arg=val, or --toggle");
} else {
throw new IllegalArgumentException("Not a valid argument format");
}
}
protected static String getNamePart(String entry) {
return entry.substring(2);
}
protected static String getValuePart(String entry) {
return entry;
}
protected static ArgumentType getArgumentType(String input) {
try {
Integer.parseInt(input);
return ArgumentType.INTEGER;
}catch(Exception e){}
try{
Long.parseLong(input);
return ArgumentType.LONG;
}catch(Exception E){
}
if(input.isEmpty())
return ArgumentType.BOOLEAN;
else return ArgumentType.STRING;
}
}

View file

@ -0,0 +1,35 @@
package dev.zontreck.ariaslib.args;
public class BooleanArgument extends Argument<Boolean> {
private boolean value;
/**
* Initializes a boolean only command line toggle
*
* @param name The option name
*/
public BooleanArgument(String name) {
super(name);
this.hasValue = true;
this.value = true;
}
@Override
public Boolean getValue() {
return value;
}
@Override
public ArgumentType getType() {
return ArgumentType.BOOLEAN;
}
@Override
public String toString() {
return "BooleanArgument{" +
name + "=true" +
'}';
}
}

View file

@ -0,0 +1,30 @@
package dev.zontreck.ariaslib.args;
public class IntegerArgument extends Argument<Integer> {
private int value;
public IntegerArgument(String name, int value) {
super(name);
this.hasValue = true;
this.value = value;
}
@Override
public ArgumentType getType() {
return ArgumentType.INTEGER;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String toString() {
return "IntegerArgument{" +
name + "=" +
value +
'}';
}
}

View file

@ -0,0 +1,30 @@
package dev.zontreck.ariaslib.args;
public class LongArgument extends Argument<Long> {
private long value;
public LongArgument(String name, long value) {
super(name);
this.hasValue = true;
this.value = value;
}
@Override
public ArgumentType getType() {
return ArgumentType.LONG;
}
@Override
public Long getValue() {
return value;
}
@Override
public String toString() {
return "LongArgument{" +
name + "=" +
value +
'}';
}
}

View file

@ -0,0 +1,30 @@
package dev.zontreck.ariaslib.args;
public class StringArgument extends Argument<String> {
private String value;
public StringArgument(String name, String value) {
super(name);
this.value = value;
this.hasValue = true;
}
@Override
public String getValue() {
return value;
}
@Override
public ArgumentType getType() {
return ArgumentType.STRING;
}
@Override
public String toString() {
return "StringArgument{" +
name + "=" +
value +
'}';
}
}

View file

@ -0,0 +1,7 @@
package dev.zontreck.ariaslib.exceptions;
public class EventRegistrationException extends Exception{
public EventRegistrationException(String message){
super(message);
}
}

View file

@ -0,0 +1,7 @@
package dev.zontreck.ariaslib.exceptions;
public class WrongArgumentTypeException extends Exception
{
}

View file

@ -0,0 +1,34 @@
package dev.zontreck.ariaslib.file;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
public class AriaIO {
public static void write(Path fileName, Entry folder) {
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(fileName.toFile()));
folder.write(dos);
dos.close();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Entry read(Path fileName) {
try {
DataInputStream dis = new DataInputStream(new FileInputStream(fileName.toFile()));
return Entry.read(dis);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Path resolveDataFile(String main) {
return Paths.get(main + ".aria");
}
}

View file

@ -0,0 +1,281 @@
package dev.zontreck.ariaslib.file;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* An entry in the serialized file
*/
public class Entry<K> {
public static final byte YES = 1;
public static final byte NO = 0;
public EntryType type;
public String name;
public K value;
public Entry(K v, String name) {
value = v;
this.name = name;
if (v instanceof String) {
type = EntryType.STRING;
} else if (v instanceof Integer) {
type = EntryType.INT;
} else if (v instanceof List<?>) {
type = EntryType.FOLDER;
} else if (v instanceof Boolean) {
type = EntryType.BOOL;
} else if (v instanceof Long) {
type = EntryType.LONG;
} else if (v instanceof Short) {
type = EntryType.SHORT;
} else if (v instanceof Byte) {
type = EntryType.BYTE;
} else if (v instanceof Double) {
type = EntryType.DOUBLE;
} else if (v instanceof Float) {
type = EntryType.FLOAT;
} else if (v instanceof int[]) {
type = EntryType.INT_ARRAY;
} else if (v instanceof String[]) {
type = EntryType.STRING_ARRAY;
} else if (v instanceof byte[]) {
type = EntryType.BYTE_ARRAY;
} else if (v instanceof long[]) {
type = EntryType.LONG_ARRAY;
} else {
type = EntryType.INVALID;
}
}
private Entry() {
}
public static Entry read(DataInputStream dis) throws IOException {
EntryType et = EntryType.of(dis.readByte());
int nameLen = dis.readInt();
byte[] nm = new byte[nameLen];
for (int i = 0; i < nameLen; i++) {
nm[i] = dis.readByte();
}
Entry work = new Entry<>();
work.type = et;
work.name = new String(nm);
//System.out.println("Read start: " + work.name + " [ " + work.type.toString() + " ]");
switch (et) {
case FOLDER: {
Entry<List<Entry>> entries = (Entry<List<Entry>>) work;
entries.value = new ArrayList<>();
int numEntries = dis.readInt();
for (int i = 0; i < numEntries; i++) {
entries.value.add(Entry.read(dis));
}
break;
}
case STRING: {
Entry<String> w = (Entry<String>) work;
int vLen = dis.readInt();
byte[] x = new byte[vLen];
for (int i = 0; i < vLen; i++) {
x[i] = dis.readByte();
}
w.value = new String(x);
break;
}
case INT: {
Entry<Integer> w = (Entry<Integer>) work;
w.value = dis.readInt();
break;
}
case BOOL: {
Entry<Boolean> w = (Entry<Boolean>) work;
byte b = dis.readByte();
if (b == YES) w.value = true;
else w.value = false;
break;
}
case LONG: {
Entry<Long> w = (Entry<Long>) work;
w.value = dis.readLong();
break;
}
case SHORT: {
Entry<Short> w = (Entry<Short>) work;
w.value = dis.readShort();
break;
}
case BYTE: {
Entry<Byte> w = (Entry<Byte>) work;
w.value = dis.readByte();
break;
}
case DOUBLE: {
Entry<Double> w = (Entry<Double>) work;
w.value = dis.readDouble();
break;
}
case FLOAT: {
Entry<Float> w = (Entry<Float>) work;
w.value = dis.readFloat();
break;
}
case INT_ARRAY: {
Entry<int[]> w = (Entry<int[]>) work;
int num = dis.readInt();
w.value = new int[num];
for (int i = 0; i < num; i++) {
w.value[i] = dis.readInt();
}
break;
}
case STRING_ARRAY: {
Entry<String[]> w = (Entry<String[]>) work;
int num = dis.readInt();
w.value = new String[num];
for (int i = 0; i < num; i++) {
int len = dis.readInt();
byte[] bStr = new byte[len];
for (int j = 0; j < len; j++) {
bStr[j] = dis.readByte();
}
w.value[i] = new String(bStr);
}
break;
}
case BYTE_ARRAY: {
Entry<byte[]> w = (Entry<byte[]>) work;
int num = dis.readInt();
w.value = new byte[num];
for (int i = 0; i < num; i++) {
w.value[i] = dis.readByte();
}
break;
}
case LONG_ARRAY: {
Entry<long[]> w = (Entry<long[]>) work;
int num = dis.readInt();
w.value = new long[num];
for (int i = 0; i < num; i++) {
w.value[i] = dis.readLong();
}
break;
}
}
//System.out.println("Read finished: " + work.name + " [ " + work.type.toString() + " ]");
return work;
}
public void write(DataOutputStream dos) throws IOException {
dos.writeByte((int) type.value);
byte[] nameBytes = name.getBytes();
dos.writeInt(nameBytes.length);
dos.write(nameBytes);
switch (type) {
case FOLDER: {
List<Entry<?>> entries = (List<Entry<?>>) value;
dos.writeInt(entries.size());
for (Entry<?> x :
entries) {
x.write(dos);
}
break;
}
case STRING: {
String s = (String) value;
byte[] bS = s.getBytes();
dos.writeInt(bS.length);
dos.write(bS);
break;
}
case INT: {
dos.writeInt((Integer) value);
break;
}
case BOOL: {
boolean x = (Boolean) value;
if (x) dos.writeByte(YES);
else dos.writeByte(NO);
break;
}
case LONG: {
dos.writeLong((Long) value);
break;
}
case SHORT: {
dos.writeShort((Short) value);
break;
}
case BYTE: {
dos.write((Byte) value);
break;
}
case DOUBLE: {
dos.writeDouble((Double) value);
break;
}
case FLOAT: {
dos.writeFloat((Float) value);
break;
}
case INT_ARRAY: {
int[] arr = (int[]) value;
dos.writeInt(arr.length);
for (int x : arr
) {
dos.writeInt(x);
}
break;
}
case STRING_ARRAY: {
String[] arr = (String[]) value;
dos.writeInt(arr.length);
for (String s : arr) {
byte[] bArr = s.getBytes();
dos.writeInt(bArr.length);
dos.write(bArr);
}
break;
}
case BYTE_ARRAY: {
byte[] arr = (byte[]) value;
dos.writeInt(arr.length);
for (byte b : arr) {
dos.write(b);
}
break;
}
case LONG_ARRAY: {
long[] arr = (long[]) value;
dos.writeInt(arr.length);
for (long L : arr) {
dos.writeLong(L);
}
break;
}
}
}
}

View file

@ -0,0 +1,36 @@
package dev.zontreck.ariaslib.file;
import java.util.Arrays;
import java.util.stream.Collectors;
public enum EntryType {
FOLDER(0),
STRING(1),
INT(2),
BOOL(3),
LONG(4),
SHORT(5),
BYTE(6),
DOUBLE(7),
FLOAT(8),
INT_ARRAY(9),
STRING_ARRAY(10),
BYTE_ARRAY(11),
LONG_ARRAY(12),
INVALID(255);
public byte value;
EntryType(int v)
{
value = (byte)v;
}
public static EntryType of(byte b)
{
return Arrays.stream(values())
.filter(c->c.value == b)
.collect(Collectors.toList())
.get(0);
}
}

View file

@ -0,0 +1,118 @@
package dev.zontreck.ariaslib.file;
import java.util.UUID;
public class EntryUtils {
public static Entry mkStr(String name, String value)
{
return new Entry<String>(value, name);
}
public static String getStr(Entry e)
{
Entry<String> eS = (Entry<String>) e;
return eS.value;
}
public static Entry mkInt(String name, int value)
{
return new Entry<Integer>(value, name);
}
public static int getInt(Entry e)
{
Entry<Integer> eS = (Entry<Integer>) e;
return eS.value;
}
public static Entry mkBool(String name, boolean value)
{
return new Entry<Boolean>(value, name);
}
public static boolean getBool(Entry e)
{
Entry<Boolean> eS = (Entry<Boolean>) e;
return eS.value;
}
public static Entry mkLong(String name, long value)
{
return new Entry<Long>(value, name);
}
public static long getLong(Entry e)
{
Entry<Long> eS = (Entry<Long>) e;
return eS.value;
}
public static Entry mkShort(String name, short value)
{
return new Entry<Short>(value, name);
}
public static short getShort(Entry e)
{
Entry<Short> eS = (Entry<Short>) e;
return eS.value;
}
public static Entry mkByte(String name, byte value)
{
return new Entry<Byte>(value, name);
}
public static byte getByte(Entry e)
{
Entry<Byte> eS = (Entry<Byte>) e;
return eS.value;
}
public static Entry mkDouble(String name, double value)
{
return new Entry<Double>(value, name);
}
public static double getDouble(Entry e)
{
Entry<Double> eS = (Entry<Double>) e;
return eS.value;
}
public static Entry mkFloat(String name, float value)
{
return new Entry<Float>(value, name);
}
public static float getFloat(Entry e)
{
Entry<Float> eS = (Entry<Float>) e;
return eS.value;
}
public static Entry mkIntArray(String name, int[] value)
{
return new Entry<int[]>(value, name);
}
public static int[] getIntArray(Entry e)
{
Entry<int[]> eS = (Entry<int[]>) e;
return eS.value;
}
public static Entry mkStringArray(String name, String[] value)
{
return new Entry<String[]>(value, name);
}
public static String[] getStringArray(Entry e)
{
Entry<String[]> eS = (Entry<String[]>) e;
return eS.value;
}
public static Entry mkByteArray(String name, byte[] value)
{
return new Entry<byte[]>(value, name);
}
public static byte[] getByteArray(Entry e)
{
Entry<byte[]> eS = (Entry<byte[]>) e;
return eS.value;
}
public static Entry mkUUID(String name, UUID ID)
{
long[] uid = new long[2];
uid[0] = ID.getLeastSignificantBits();
uid[1] = ID.getMostSignificantBits();
return new Entry<long[]>(uid, name);
}
public static UUID getUUID(Entry e)
{
Entry<long[]> uid = (Entry<long[]>) e;
return new UUID(uid.value[1], uid.value[0]);
}
}

View file

@ -0,0 +1,42 @@
package dev.zontreck.ariaslib.file;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Folder
{
public static void add(Entry e, Entry item)
{
((Entry<List<Entry>>)e).value.add(item);
}
public static void remove(Entry e, Entry item)
{
((Entry<List<Entry>>)e).value.remove(item);
}
public static Entry getEntry(Entry item, String name)
{
List<Entry> ret = ((Entry<List<Entry>>)item).value;
if(ret.size()>0)
{
for (Entry ent :
ret) {
if(ent.name.equals(name))return ent;
}
}
return null;
}
public static int size(Entry e)
{
return ((Entry<List<Entry>>)e).value.size();
}
public static Entry<List<Entry>> getNew(String name)
{
return new Entry<>(new ArrayList<Entry>(), name);
}
}

View file

@ -0,0 +1,283 @@
package dev.zontreck.ariaslib.html;
import dev.zontreck.ariaslib.html.bootstrap.Color;
import dev.zontreck.ariaslib.html.bootstrap.Icons;
import dev.zontreck.ariaslib.html.bootstrap.Size;
import dev.zontreck.ariaslib.util.Percent;
public class Bootstrap {
public static class Border {
public Side side;
public int width = 1;
public boolean usesSides = false;
public Colors colors;
public boolean invert;
public static Border make() {
return new Border();
}
public Border withColor(Colors color) {
this.colors = color.withPrefix("border");
return this;
}
public Border widthSide(Side side) {
this.side = side;
usesSides = true;
return this;
}
public Border withWidth(int width) {
this.width = width;
return this;
}
/**
* Removes borders instead of adding
*/
public Border setInverted() {
invert = true;
return this;
}
public void apply(HTMLElementBuilder elem) {
elem.addClass("border");
colors.apply(elem);
if (usesSides) {
elem.addClass("border-" + side.name().toLowerCase() + (invert ? "-0" : ""));
} else {
if (invert) elem.addClass("border-0");
}
}
public enum Side {
Start,
End,
Top,
Bottom
}
}
public static class Opacity {
public Percent value;
public String prefix;
public static Opacity make() {
return new Opacity();
}
public Opacity withPercent(Percent val) {
value = val;
return this;
}
public Opacity withPrefix(String pref) {
this.prefix = pref;
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass((prefix != "" ? prefix + "-" : "") + "opacity-" + value.get());
}
}
public static class Colors {
public Color color;
public boolean emphasis;
public boolean subtle;
public String prefix;
public static Colors make() {
return new Colors();
}
public Colors withColor(Color color) {
this.color = color;
return this;
}
public Colors setEmphasis() {
emphasis = true;
return this;
}
public Colors setSubtle() {
subtle = true;
return this;
}
public Colors withPrefix(String prefix) {
this.prefix = prefix;
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass(((prefix != "") ? prefix + "-" : "") + color.name().toLowerCase() + (emphasis ? "-emphasis" : "") + (subtle ? "-subtle" : ""));
}
}
public static class Background {
public Colors color;
public Opacity opacity;
public boolean gradient;
public static Background make() {
return new Background();
}
public Background withColor(Colors color) {
this.color = color.withPrefix("bg");
return this;
}
public Background withOpacity(Opacity op) {
this.opacity = op.withPrefix("bg");
return this;
}
public Background setGradient() {
gradient = true;
return this;
}
public void apply(HTMLElementBuilder builder) {
color.apply(builder);
opacity.apply(builder);
if (gradient)
builder.addClass(".bg-gradient");
}
}
public static class Shadow {
public Size size;
public static Shadow make() {
return new Shadow();
}
public Shadow withSize(Size size) {
this.size = size;
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass("shadow" + size.sizeText());
}
}
public static class FocusRing {
public Colors color;
public static FocusRing make() {
return new FocusRing();
}
public FocusRing withColor(Colors color) {
this.color = color.withPrefix("focus-ring");
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass("focus-ring");
color.apply(builder);
}
}
public static class Link {
public Colors color;
public static Link make() {
return new Link();
}
public Link withColor(Colors color) {
this.color = color.withPrefix("link");
return this;
}
public void apply(HTMLElementBuilder builder) {
color.apply(builder);
}
}
public static class Toast {
public Icons icon;
public HTMLElementBuilder toastHeader;
public HTMLElementBuilder toastBody;
public Toast() {
toastHeader = new HTMLElementBuilder("div").addClass("toast-header");
toastHeader.addChild("svg").addClass("bi").addClass(icon.getClassName()).addClass("rounded");
toastHeader.addChild("strong").addClass("me-auto");
toastHeader.addChild("small").withText("Text?");
toastHeader.addChild("button").withAttribute("type", "button").addClass("btn-close").withAttribute("data-bs-dismiss", "toast").withAttribute("aria-label", "Close");
toastBody = new HTMLElementBuilder("div").addClass("toast-body");
}
public static Toast make() {
return new Toast();
}
public Toast withIcon(Icons icon) {
this.icon = icon;
return this;
}
public void apply(HTMLElementBuilder builder) {
HTMLElementBuilder toast = builder.addChild("div").addClass("toast").withAttribute("role", "alert").withAttribute("aria-live", "assertive").withAttribute("aria-atomic", "true");
toast.addChild(toastHeader);
toast.addChild(toastBody);
}
}
public static class Button {
public Colors color;
public boolean outline;
public Size size;
public static Button make() {
return new Button();
}
public Button withColor(Colors color) {
this.color = color;
return this;
}
public Button setOutline() {
outline = true;
return this;
}
public Button withSize(Size size) {
this.size = size;
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass("btn");
if (outline) {
color.withPrefix("btn-outline");
} else color.withPrefix("btn");
color.apply(builder);
if (size != Size.Regular)
builder.addClass("btn" + size.sizeText());
}
}
public static class Disabled {
public static void setDisabled(HTMLElementBuilder builder) {
builder.withAttribute("disabled");
}
}
}

View file

@ -0,0 +1,8 @@
package dev.zontreck.ariaslib.html;
// Class attribute class for HTML element classes
class ClassAttribute extends HTMLAttribute {
public ClassAttribute(String value) {
super("class", value);
}
}

View file

@ -0,0 +1,55 @@
package dev.zontreck.ariaslib.html;
public class DOM {
public static HTMLElementBuilder beginBootstrapDOM(String pageTitle) {
HTMLElementBuilder builder = new HTMLElementBuilder("!doctype").withText("html");
HTMLElementBuilder html = builder.getOrCreate("html");
HTMLElementBuilder head = html.getOrCreate("head");
head.addChild("meta").withAttribute("charset", "utf-8");
head.addChild("meta").withAttribute("name", "viewport").withAttribute("content", "width=device-width, initial-scale=1");
head.getOrCreate("link").withAttribute("href", "https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css").withAttribute("integrity", "sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM").withAttribute("crossorigin", "anonymous").withAttribute("rel", "stylesheet");
head.addClass("link").withAttribute("rel", "stylesheet").withAttribute("href", "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css");
head.getOrCreate("title").withText(pageTitle);
HTMLElementBuilder body = html.getOrCreate("body");
body.addChild("script").withAttribute("src", "https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js").withAttribute("integrity", "sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz").withAttribute("crossorigin", "anonymous").withText(" ");
body.addChild("script").withAttribute("src", "https://code.jquery.com/jquery-3.7.0.min.js").withAttribute("crossorigin", "anonymous").withText(" ");
body.addChild("style").withText("\n" +
" .command-popover{\n" +
" --bs-popover-header-bg: var(--bs-info);\n" +
" --bs-popover-header-color: var(--bs-dark);\n" +
" --bs-popover-bg: var(--bs-dark);\n" +
" --bs-popover-body-color: var(--bs-light);\n" +
" }\n");
return builder;
}
public static void addPopOverScan(HTMLElementBuilder builder) {
builder.getChildByTagName("html").getChildByTagName("body").addChild("script").withText("" +
"function scanPopOver()" +
"{" +
"var popoverTriggerList = document.querySelectorAll('[data-bs-toggle=\"popover\"]');\n" +
"var popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl));" +
"" +
"}");
}
public static String closeHTML() {
return "</body></html>";
}
}

View file

@ -0,0 +1,24 @@
package dev.zontreck.ariaslib.html;
// Attribute class for HTML element attributes
class HTMLAttribute {
private String name;
private String value;
public HTMLAttribute(String name, String value) {
this.name = name;
this.value = value;
}
public HTMLAttribute(String name) {
this(name, null);
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
}

View file

@ -0,0 +1,72 @@
package dev.zontreck.ariaslib.html;
import java.util.List;
// HTML element class supporting tag attributes
public class HTMLElement {
private String tagName;
private String text;
private List<HTMLAttribute> attributes;
private List<HTMLElement> children;
private boolean isEmptyElement;
public HTMLElement ( String tagName , String text , List<HTMLAttribute> attributes , List<HTMLElement> children , boolean isEmptyElement ) {
this.tagName = tagName;
this.text = text;
this.attributes = attributes;
this.children = children;
this.isEmptyElement = isEmptyElement;
}
public String getTagName ( ) {
return tagName;
}
public String generateHTML ( ) {
StringBuilder builder = new StringBuilder ( );
if ( "!doctype".equalsIgnoreCase ( tagName ) ) {
builder.append ( "<" ).append ( tagName ).append ( " " ).append ( text ).append ( ">\n" );
for ( HTMLElement child : children ) {
builder.append ( child.generateHTML ( ) );
}
return builder.toString ( );
}
builder.append ( "<" ).append ( tagName );
for ( HTMLAttribute attribute : attributes ) {
builder.append ( " " )
.append ( attribute.getName ( ) );
String value = attribute.getValue ( );
if ( value != null ) {
builder.append ( "=\"" ).append ( value ).append ( "\"" );
}
}
/*
if ( isEmptyElement ) {
builder.append ( " />\n" );
return builder.toString ( );
}*/
builder.append ( ">" );
if ( text != null ) {
builder.append ( text );
}
if ( ! isEmptyElement ) {
for ( HTMLElement child : children ) {
builder.append ( child.generateHTML ( ) );
}
}
builder.append ( "</" ).append ( tagName ).append ( ">\n" );
return builder.toString ( );
}
}

View file

@ -0,0 +1,118 @@
package dev.zontreck.ariaslib.html;
import java.util.ArrayList;
import java.util.List;
// Builder class for building HTML elements
public class HTMLElementBuilder {
private String tagName;
private String text;
private List<HTMLAttribute> attributes;
private List<HTMLElementBuilder> childElementBuilders;
public HTMLElementBuilder ( String tagName ) {
this.tagName = tagName;
this.attributes = new ArrayList<> ( );
this.childElementBuilders = new ArrayList<> ( );
}
public HTMLElementBuilder withText ( String text ) {
this.text = text;
return this;
}
public HTMLElementBuilder withAttribute ( String name , String value ) {
HTMLAttribute attribute = new HTMLAttribute ( name , value );
this.attributes.add ( attribute );
return this;
}
public HTMLElementBuilder withAttribute ( String name ) {
HTMLAttribute attribute = new HTMLAttribute ( name );
this.attributes.add ( attribute );
return this;
}
public HTMLElementBuilder addClass ( String className ) {
ClassAttribute classAttribute = getClassAttribute ( );
if ( classAttribute == null ) {
classAttribute = new ClassAttribute ( className );
this.attributes.add ( classAttribute );
}
else {
String existingValue = classAttribute.getValue ( );
classAttribute = new ClassAttribute ( existingValue + " " + className );
this.attributes.removeIf ( attr -> attr.getName ( ).equalsIgnoreCase ( "class" ) );
this.attributes.add ( classAttribute );
}
return this;
}
private ClassAttribute getClassAttribute ( ) {
for ( HTMLAttribute attribute : attributes ) {
if ( attribute instanceof ClassAttribute ) {
return ( ClassAttribute ) attribute;
}
}
return null;
}
public HTMLElementBuilder addChild ( HTMLElementBuilder childBuilder ) {
childElementBuilders.add ( childBuilder );
return this;
}
public HTMLElementBuilder addChild ( String tagName ) {
HTMLElementBuilder childBuilder = new HTMLElementBuilder ( tagName );
childElementBuilders.add ( childBuilder );
return childBuilder;
}
public HTMLElementBuilder getOrCreate ( String tagName ) {
HTMLElementBuilder childBuilder = getChildByTagName ( tagName );
if ( childBuilder == null ) {
childBuilder = addChild ( tagName );
}
return childBuilder;
}
public HTMLElementBuilder getChildByTagName ( String tagName ) {
return getChildByTagName ( tagName , 0 );
}
public HTMLElementBuilder getChildByTagName ( String tagName , int index ) {
List<HTMLElementBuilder> matchingChildBuilders = new ArrayList<> ( );
for ( HTMLElementBuilder builder : childElementBuilders ) {
if ( builder.tagName.equalsIgnoreCase ( tagName ) ) {
matchingChildBuilders.add ( builder );
}
}
if ( matchingChildBuilders.size ( ) > index ) {
return matchingChildBuilders.get ( index );
}
return null;
}
private boolean hasTextOrChildren ( ) {
return text != null || ! childElementBuilders.isEmpty ( );
}
public HTMLElement build ( ) {
List<HTMLElement> children = buildChildren ( );
boolean isEmptyElement = ! hasTextOrChildren ( );
return new HTMLElement ( tagName , text , attributes , children , isEmptyElement );
}
private List<HTMLElement> buildChildren ( ) {
List<HTMLElement> children = new ArrayList<> ( );
for ( HTMLElementBuilder builder : childElementBuilders ) {
children.add ( builder.build ( ) );
}
return children;
}
}

View file

@ -0,0 +1,46 @@
package dev.zontreck.ariaslib.html.bootstrap;
public enum Color
{
/**
* Dark Blue
*/
Primary,
/**
* Dark Gray
*/
Secondary,
/**
* Dark Green
*/
Success,
/**
* Dark Red
*/
Danger,
/**
* Yellow
*/
Warning,
/**
* Light Blue
*/
Info,
/**
* Black
*/
Dark,
/**
* Semi-gray
*/
Light,
Black,
White
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
package dev.zontreck.ariaslib.html.bootstrap;
public enum Size {
Small,
Regular,
Large,
None;
public String sizeText() {
switch (this) {
case Small:
return "-sm";
case None:
return "-none";
case Large:
return "-lg";
default:
return "";
}
}
}

View file

@ -0,0 +1,9 @@
package dev.zontreck.ariaslib.http;
public enum HTTPMethod
{
GET,
POST,
PUT,
DELETE
}

View file

@ -0,0 +1,15 @@
package dev.zontreck.ariaslib.http;
public class HTTPRequest
{
public String url;
public String method;
public String body;
public String contentType;
protected HTTPRequest(){
}
}

View file

@ -0,0 +1,134 @@
package dev.zontreck.ariaslib.http;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class HTTPRequestBuilder
{
private HttpURLConnection connection;
private URL url;
private HTTPRequest request = new HTTPRequest();
public static HTTPRequestBuilder builder()
{
return new HTTPRequestBuilder();
}
protected HTTPRequestBuilder()
{
}
/**
* Sets the url in this request to the one supplied
* @param url The url to connect to
* @return Builder instance
* @throws MalformedURLException If the URL supplied was invalid
*/
public HTTPRequestBuilder withURL( String url) throws MalformedURLException {
request.url = url;
this.url = new URL(url);
return this;
}
/**
* Sets the HTTP Request method
* @param method The method you want to use
* @see HTTPMethod
* @return Builder instance
*/
public HTTPRequestBuilder withMethod(HTTPMethod method)
{
switch(method)
{
case GET:
{
request.method = "GET";
break;
}
case POST: {
request.method = "POST";
if(request.contentType.isEmpty()) request.contentType = "application/x-www-form-urlencoded";
break;
}
case DELETE:{
request.method = "DELETE";
break;
}
case PUT:{
request.method = "PUT";
if(request.contentType.isEmpty()) request.contentType = "application/x-www-form-urlencoded";
break;
}
}
return this;
}
/**
* Sets the request body. This may only be processed by the server when using POST or PUT, depending on the server's setup
* @param body The body to upload
* @return Builder Instance
*/
public HTTPRequestBuilder withBody(String body)
{
request.body = body;
return this;
}
/**
* Sets the content type header
* Default: application/x-www-form-urlencoded for POST/PUT, and null/not present for GET
* @param type
* @return
*/
public HTTPRequestBuilder withContentType(String type)
{
request.contentType = type;
return this;
}
public HTTPResponse build()
{
try {
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(request.method);
byte[] array = request.body.getBytes("UTF-8");
connection.setRequestProperty("Content-Length" , "" + array.length);
connection.setRequestProperty("Content-Type", request.contentType);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setDoOutput(true);
DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
dos.write(array);
dos.flush();
dos.close();
// Get the response body
InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
inputStream.close();
String responseBody = response.toString();
return new HTTPResponse(connection.getContentType(), connection.getResponseCode(), responseBody, request);
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
connection.disconnect();
}
}
}

View file

@ -0,0 +1,33 @@
package dev.zontreck.ariaslib.http;
public class HTTPResponse
{
private String ContentType;
private int ResponseCode;
private String ResponseBody;
private HTTPRequest OriginalRequest;
protected HTTPResponse(String contentType, int code, String body, HTTPRequest request){
this.ContentType = contentType;
this.ResponseCode = code;
this.ResponseBody = body;
this.OriginalRequest = request;
}
public String getContentType() {
return ContentType;
}
public int getResponseCode() {
return ResponseCode;
}
public String getResponseBody() {
return ResponseBody;
}
public HTTPRequest getOriginalRequest() {
return OriginalRequest;
}
}

View file

@ -0,0 +1,15 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Serialization or Deserialization has completed.
*
* The method takes 1 argument.
*
* Boolean: True for deserialization.
*/
@Retention ( RetentionPolicy.RUNTIME )
public @interface Completed {
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Used on a class to indicate that it is serializable by the dynamic serializer.
*/
@Retention ( RetentionPolicy.RUNTIME )
public @interface DynSerial {
}

View file

@ -0,0 +1,119 @@
package dev.zontreck.ariaslib.json;
import java.io.ByteArrayInputStream;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Deserializes objects!
* <p>
* YOU MUST HAVE A NO-PARAMETER CONSTRUCTOR
*/
public class DynamicDeserializer {
/**
* Constructs and deserializes an object from serialized data
*/
public static <T> T doDeserialize ( Class<T> clazz , byte[] data ) throws Exception {
ByteArrayInputStream BAIS = new ByteArrayInputStream ( data );
return deserialize ( ( Map<String, Object> ) JsonObject.parseJSON ( BAIS ).getMap ( ) , clazz );
}
private static <T> T deserialize ( Map<String, Object> map , Class<T> clazz ) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
if ( ! clazz.isAnnotationPresent ( DynSerial.class ) )
return null;
T object = clazz.getDeclaredConstructor ( ).newInstance ( );
Field[] fields = clazz.getDeclaredFields ( );
for ( Field field : fields ) {
field.setAccessible ( true );
if ( field.isAnnotationPresent ( IgnoreSerialization.class ) )
continue;
try {
if ( List.class.isAssignableFrom ( field.getType ( ) ) ) {
Class<?> listType = getListType ( field );
List<Object> list = new ArrayList<> ( );
List<?> serializedList = ( List<?> ) map.get ( field.getName ( ) );
if ( serializedList != null ) {
for ( Object listItem : serializedList ) {
if ( listType.isAnnotationPresent ( DynSerial.class ) ) {
Object deserializedItem = deserialize ( ( Map<String, Object> ) listItem , listType );
list.add ( deserializedItem );
}
else {
list.add ( listItem );
}
}
}
field.set ( object , list );
}
else if ( Map.class.isAssignableFrom ( field.getType ( ) ) ) {
Class<?> valueType = getMapValueType ( field );
Map<String, Object> serializedMap = ( Map<String, Object> ) map.get ( field.getName ( ) );
if ( serializedMap != null ) {
Map<String, Object> mapValue = new HashMap<> ( );
for ( Map.Entry<String, Object> entry : serializedMap.entrySet ( ) ) {
Object deserializedValue;
if ( valueType.isAnnotationPresent ( DynSerial.class ) ) {
deserializedValue = deserialize ( ( Map<String, Object> ) entry.getValue ( ) , valueType );
}
else {
deserializedValue = entry.getValue ( );
}
mapValue.put ( entry.getKey ( ) , deserializedValue );
}
field.set ( object , mapValue );
}
}
else if ( ! field.getType ( ).isAnnotationPresent ( DynSerial.class ) ) {
field.set ( object , map.get ( field.getName ( ) ) );
}
else {
Object tmp = deserialize ( ( Map<String, Object> ) map.get ( field.getName ( ) ) , field.getType ( ) );
field.set ( object , tmp );
}
} catch ( Exception e ) {
// Handle any exceptions during deserialization
}
}
Method[] methods = clazz.getDeclaredMethods ( );
for ( Method method : methods ) {
if ( method.isAnnotationPresent ( Completed.class ) ) {
method.invoke ( object , true );
}
}
return object;
}
private static Class<?> getListType ( Field field ) {
Type genericType = field.getGenericType ( );
if ( genericType instanceof ParameterizedType ) {
ParameterizedType paramType = ( ParameterizedType ) genericType;
Type[] actualTypeArgs = paramType.getActualTypeArguments ( );
if ( actualTypeArgs.length > 0 ) {
return ( Class<?> ) actualTypeArgs[ 0 ];
}
}
return Object.class;
}
private static Class<?> getMapValueType ( Field field ) {
Type genericType = field.getGenericType ( );
if ( genericType instanceof ParameterizedType ) {
ParameterizedType paramType = ( ParameterizedType ) genericType;
Type[] actualTypeArgs = paramType.getActualTypeArguments ( );
if ( actualTypeArgs.length > 1 ) {
return ( Class<?> ) actualTypeArgs[ 1 ];
}
}
return Object.class;
}
}

View file

@ -0,0 +1,115 @@
package dev.zontreck.ariaslib.json;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DynamicSerializer {
/**
* Serializes the object instance
*
* @param inst The class object to serialize
* @return A byte array of serialized data
*/
public static byte[] doSerialize(Object inst) throws InvocationTargetException, IllegalAccessException {
Map<String, Object> ret = serialize(inst);
JsonObject js = new JsonObject(ret);
return js.toJSONString().getBytes();
}
private static Map<String, Object> serialize(Object inst) throws InvocationTargetException, IllegalAccessException {
Class<?> clazz = inst.getClass();
if (!clazz.isAnnotationPresent(DynSerial.class))
return null;
Method[] mth = clazz.getDeclaredMethods();
Method onComplete = null;
for (
Method mt :
mth
) {
if (mt.isAnnotationPresent(PreSerialize.class)) {
mt.invoke(inst);
}
if (mt.isAnnotationPresent(Completed.class))
onComplete = mt;
}
Field[] fields = clazz.getDeclaredFields();
Map<String, Object> ret = new HashMap<>();
for (
Field field :
fields
) {
field.setAccessible(true);
if (field.isAnnotationPresent(IgnoreSerialization.class))
continue;
Object fieldVal = field.get(inst);
if (fieldVal == null) continue;
String fieldName = field.getName();
if (field.isAnnotationPresent(ListOrMap.class)) {
// Special handling for List and Map types
ret.put(fieldName, serializeCollectionOrMap(fieldVal));
continue;
}
if (!(fieldVal.getClass().isAnnotationPresent(DynSerial.class))) {
// Special handler for List and Map is needed right here.
if (fieldVal instanceof List || fieldVal instanceof Map) continue;
ret.put(fieldName, fieldVal);
} else {
Map<String, Object> TMP = serialize(fieldVal);
ret.put(fieldName, TMP);
}
}
if (onComplete != null)
onComplete.invoke(inst, false);
return ret;
}
@SuppressWarnings("unchecked")
private static Object serializeCollectionOrMap(Object collectionOrMap) throws InvocationTargetException, IllegalAccessException {
if (collectionOrMap instanceof List<?>) {
List<?> list = (List<?>) collectionOrMap;
List<Object> serializedList = new ArrayList<>();
for (Object item : list) {
if (item.getClass().isAnnotationPresent(DynSerial.class)) {
serializedList.add(serialize(item));
} else {
serializedList.add(item);
}
}
return serializedList;
} else if (collectionOrMap instanceof Map<?, ?>) {
Map<?, ?> mp = (Map<?, ?>) collectionOrMap;
Map<String, Object> map = (Map<String, Object>) mp;
Map<String, Object> serializedMap = new HashMap<>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value.getClass().isAnnotationPresent(DynSerial.class)) {
value = serialize(value);
}
serializedMap.put(key, value);
}
return serializedMap;
}
return collectionOrMap;
}
}

View file

@ -0,0 +1,12 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Marks an element to be ignored completely by the serializer or deserializer.
*/
@Retention ( RetentionPolicy.RUNTIME )
public @interface IgnoreSerialization
{
}

View file

@ -0,0 +1,183 @@
package dev.zontreck.ariaslib.json;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JsonObject {
private Map<String, Object> data;
public JsonObject() {
data = new HashMap<>();
}
public JsonObject(Map<String, Object> dat) {
data = new HashMap<>(dat);
}
public static JsonObject parseJSON(InputStream inputStream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder jsonString = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
jsonString.append(line);
}
return parseJsonObject(jsonString.toString());
}
private static JsonObject parseJsonObject(String jsonString) {
JsonObject jsonObject = new JsonObject();
jsonString = jsonString.trim();
if (jsonString.startsWith("{") && jsonString.endsWith("}")) {
jsonString = jsonString.substring(1, jsonString.length() - 1);
String[] keyValuePairs = jsonString.split(",");
for (String pair : keyValuePairs) {
String[] keyValue = pair.split(":");
if (keyValue.length == 2) {
String key = keyValue[0].trim().replace("\"", "");
String value = keyValue[1].trim();
jsonObject.put(key, parseValue(value));
}
}
}
return jsonObject;
}
private static Object parseValue(String value) {
if (value.startsWith("{") && value.endsWith("}")) {
return parseJsonObject(value);
} else if (value.startsWith("[") && value.endsWith("]")) {
return parseJSONArray(value);
} else if (value.startsWith("\"") && value.endsWith("\"")) {
return value.substring(1, value.length() - 1);
} else if (value.equalsIgnoreCase("true")) {
return true;
} else if (value.equalsIgnoreCase("false")) {
return false;
} else if (value.equalsIgnoreCase("null")) {
return null;
} else {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
try {
return Double.parseDouble(value);
} catch (NumberFormatException ex) {
return value;
}
}
}
}
private static List<Object> parseJSONArray(String jsonArray) {
List<Object> list = new ArrayList<>();
jsonArray = jsonArray.trim();
if (jsonArray.startsWith("[") && jsonArray.endsWith("]")) {
jsonArray = jsonArray.substring(1, jsonArray.length() - 1);
String[] elements = jsonArray.split(",");
for (String element : elements) {
list.add(parseValue(element.trim()));
}
}
return list;
}
public void put(String key, Object value) {
data.put(key, value);
}
public Object get(String key) {
return data.get(key);
}
public void merge(Map<String, Object> ret) {
data.putAll(ret);
}
public Map<String, Object> getMap() {
return new HashMap<>(data);
}
public void add(String key, Object value) {
if (data.containsKey(key)) {
Object existingValue = data.get(key);
if (existingValue instanceof List) {
((List<Object>) existingValue).add(value);
} else {
List<Object> list = new ArrayList<>();
list.add(existingValue);
list.add(value);
data.put(key, list);
}
} else {
data.put(key, value);
}
}
public String toJSONString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
boolean first = true;
for (Map.Entry<String, Object> entry : data.entrySet()) {
if (!first) {
sb.append(",");
}
first = false;
sb.append("\"");
sb.append(escape(entry.getKey()));
sb.append("\":");
sb.append(toJSONValue(entry.getValue()));
}
sb.append("}");
return sb.toString();
}
private String escape(String str) {
if (str == null) return "";
// Add necessary escape characters (e.g., double quotes, backslashes)
// You can implement this method based on your specific requirements.
// This is a simplified version for demonstration purposes.
return str.replace("\"", "\\\"");
}
private String toJSONValue(Object value) {
if (value instanceof String) {
return "\"" + escape(value.toString()) + "\"";
} else if (value instanceof JsonObject) {
return ((JsonObject) value).toJSONString();
} else if (value instanceof List) {
return toJSONList((List<Object>) value);
} else if (value instanceof Map<?, ?>) {
return new JsonObject((Map<String, Object>) ((Map<?, ?>) value)).toJSONString();
} else {
return value.toString();
}
}
private String toJSONList(List<Object> list) {
StringBuilder sb = new StringBuilder();
sb.append("[");
boolean first = true;
for (Object item : list) {
if (!first) {
sb.append(",");
}
first = false;
sb.append(toJSONValue(item));
}
sb.append("]");
return sb.toString();
}
}

View file

@ -0,0 +1,8 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention ( RetentionPolicy.RUNTIME )
public @interface ListOrMap {
}

View file

@ -0,0 +1,13 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* To be set on a method, and will invoke that method prior to serialization beginning.
*
* Preparations should be made here
*/
@Retention ( RetentionPolicy.RUNTIME )
public @interface PreSerialize {
}

View file

@ -0,0 +1,47 @@
package dev.zontreck.ariaslib.terminal;
import java.util.ArrayList;
import java.util.List;
public class Banners
{
public static String generateBanner(String text) {
int maxLength = calculateMaxLength(text);
List<String> bannerLines = new ArrayList<>();
StringBuilder border = new StringBuilder();
for (int i = 0; i < maxLength + 4; i++) {
border.append("*");
}
bannerLines.add(border.toString());
bannerLines.add("* " + centerText(text, maxLength) + " *");
bannerLines.add(border.toString());
return String.join("\n", bannerLines);
}
private static String centerText(String text, int maxLength) {
StringBuilder centeredText = new StringBuilder();
int spacesToAdd = (maxLength - text.length()) / 2;
for (int i = 0; i < spacesToAdd; i++) {
centeredText.append(" ");
}
centeredText.append(text);
for (int i = 0; i < spacesToAdd; i++) {
centeredText.append(" ");
}
if (centeredText.length() < maxLength) {
centeredText.append(" ");
}
return centeredText.toString();
}
private static int calculateMaxLength(String text) {
int maxLength = 0;
for (String line : text.split("\n")) {
if (line.length() > maxLength) {
maxLength = line.length();
}
}
return maxLength;
}
}

View file

@ -0,0 +1,88 @@
package dev.zontreck.ariaslib.terminal;
import dev.zontreck.ariaslib.util.DelayedExecutorService;
import dev.zontreck.ariaslib.util.EnvironmentUtils;
import dev.zontreck.ariaslib.util.Progress;
import java.util.TimerTask;
public abstract class Task extends TimerTask implements Runnable {
public final String TASK_NAME;
private TaskCompletionToken token = new TaskCompletionToken ( );
public static final String CHECK = "P";
public static final String FAIL = "F";
// Else use the progress spinner from the Progress class
private boolean isSilent = false;
public Task ( String name ) {
TASK_NAME = name;
}
/**
* This constructor is meant to be used to create silent tasks that do not output to the console. (Example usage: DelayedExecutionService)
*
* @param name Task name
* @param silent Whether to print to the terminal
*/
public Task ( String name , boolean silent ) {
this ( name );
isSilent = silent;
}
public boolean isComplete ( ) {
return token.get ( );
}
public void startTask ( ) {
Thread tx = new Thread(this);
tx.start();
if(! isSilent && !EnvironmentUtils.isRunningInsideDocker())
{
Thread tx2 = new Thread(new SpinnerTask(token, this));
tx2.start();
}
}
public void stopTask ( ) {
if ( token.get ( ) && ! isSilent ) {
System.out.printf ( "\r" + TASK_NAME + "\t\t[" + token.status + "]\n" );
}
}
public void setSuccess ( ) {
token.completed ( CHECK );
}
public void setFail ( ) {
token.completed ( FAIL );
}
public class SpinnerTask extends Task {
public final Task task;
public final TaskCompletionToken token;
private final Progress spinner = new Progress ( 100 );
public SpinnerTask ( TaskCompletionToken token , Task parent ) {
super ( "spinner" , true );
this.token = token;
this.task = parent;
}
@Override
public void run ( ) {
while ( ! task.isComplete ( ) ) {
try {
Thread.sleep ( 50L );
if ( ! task.isSilent && ! task.isComplete ( ) && ! EnvironmentUtils.isRunningInsideDocker ( ) )
System.out.printf ( "\r" + task.TASK_NAME + "\t\t" + spinner.getSpinnerTick ( ) + "\r" );
} catch ( Exception e ) {
e.printStackTrace ( );
}
}
}
}
}

View file

@ -0,0 +1,20 @@
package dev.zontreck.ariaslib.terminal;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Should not be re-used for multiple tasks!!!
*/
public class TaskCompletionToken
{
private AtomicBoolean complete = new AtomicBoolean(false);
public String status = "";
public void completed(String reason){
status=reason;
complete.set(true);
}
public boolean get(){
return complete.get();
}
}

View file

@ -0,0 +1,35 @@
package dev.zontreck.ariaslib.terminal;
import dev.zontreck.ariaslib.util.EnvironmentUtils;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class Terminal {
private static final AtomicInteger ID = new AtomicInteger ( 0 );
private static final AtomicBoolean running = new AtomicBoolean ( true );
public static String PREFIX = "";
/**
* This starts a terminal instance
*
* @return The terminal ID
*/
public static int startTerminal ( ) {
if ( EnvironmentUtils.isRunningInsideDocker ( ) )
return 0;
running.set ( true );
//DelayedExecutorService.getInstance ( ).schedule ( new ConsolePrompt ( ) , 1 );
return ID.getAndIncrement ( );
}
public static boolean isRunning ( ) {
return running.get ( );
}
public static void setRunning ( boolean running ) {
Terminal.running.set ( running );
}
}

View file

@ -0,0 +1,17 @@
package dev.zontreck.ariaslib.util;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import dev.zontreck.ariaslib.terminal.Task;
import dev.zontreck.ariaslib.terminal.Terminal;
@Deprecated
public class DelayedExecutorService {
}

View file

@ -0,0 +1,19 @@
package dev.zontreck.ariaslib.util;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class EnvironmentUtils {
public static boolean isRunningInsideDocker ( ) {
if ( Files.exists ( Paths.get ( "/.dockerenv" ) ) )
return true;
try {
Stream<String> str = Files.lines ( Paths.get ( "/proc/1/cgroup" ) );
return str.anyMatch ( ln -> ln.contains ( "/docker" ) );
} catch ( IOException e ) {
return false;
}
}
}

View file

@ -0,0 +1,51 @@
package dev.zontreck.ariaslib.util;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class FileIO
{
public static String readFile(String filePath) {
try {
byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
return new String(fileBytes);
} catch (IOException e) {
return "An error occurred: " + e.getMessage();
}
}
public static void writeFile(String filePath, String newContent) {
try {
Files.write(Paths.get(filePath), newContent.getBytes());
} catch (IOException e) {
}
}
/**
* Recursively delete a directory
* @param directory The folder to delete
*/
public static void deleteDirectory(File directory) {
if (directory.exists()) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
deleteDirectory(file);
} else {
file.delete();
}
}
}
// Now directory is empty, so delete it
directory.delete();
System.out.println("Directory deleted: " + directory.getAbsolutePath());
} else {
System.out.println("Directory does not exist: " + directory.getAbsolutePath());
}
}
}

View file

@ -0,0 +1,120 @@
package dev.zontreck.ariaslib.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Hashing
{
/**
* A md5 hashing function that is compatible with literally every other hashing function out there
* @param input The string to hash
* @return The hash
*/
public static String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(input.getBytes());
byte[] byteData = md.digest();
// Convert the byte array to a hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte aByteData : byteData) {
String hex = Integer.toHexString(0xff & aByteData);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
/**
* A md5 hashing function that is compatible with literally every other hashing function out there
* @param input The bytes to hash
* @return The hash
*/
public static String md5(byte[] input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(input);
byte[] byteData = md.digest();
// Convert the byte array to a hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte aByteData : byteData) {
String hex = Integer.toHexString(0xff & aByteData);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
/**
* A sha256 hashing function that is compatible with literally every other hashing function out there
* @param input The string to hash
* @return The hash
*/
public static String sha256(String input) {
try {
MessageDigest md = MessageDigest.getInstance("SHA256");
md.update(input.getBytes());
byte[] byteData = md.digest();
// Convert the byte array to a hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte aByteData : byteData) {
String hex = Integer.toHexString(0xff & aByteData);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
/**
* A sha256 hashing function that is compatible with literally every other hashing function out there
* @param input The bytes to hash
* @return The hash
*/
public static String sha256(byte[] input) {
try {
MessageDigest md = MessageDigest.getInstance("SHA256");
md.update(input);
byte[] byteData = md.digest();
// Convert the byte array to a hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte aByteData : byteData) {
String hex = Integer.toHexString(0xff & aByteData);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
}

View file

@ -0,0 +1,94 @@
package dev.zontreck.ariaslib.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Lists
{
/**
* Programatically constructs a list
* @param values The list of values
* @return The new list
* @param <T> An arbitrary type parameter
*/
public static <T> List<T> of(T... values)
{
List<T> arr = new ArrayList<>();
for(T value : values)
{
arr.add(value);
}
return arr;
}
/**
* Splits a string into a list
* @param input The string to split
* @param delimiters The list of delimiters
* @return A non-strided list
*/
public static List<String> split(String input, String... delimiters) {
List<String> result = new ArrayList<>();
StringBuilder regex = new StringBuilder("(");
// Constructing the regular expression pattern with provided delimiters
for (String delimiter : delimiters) {
regex.append(delimiter).append("|");
}
regex.deleteCharAt(regex.length() - 1); // Remove the extra '|' character
regex.append(")");
String[] tokens = input.split(regex.toString());
// Add non-empty tokens to the result list
for (String token : tokens) {
if (!token.isEmpty()) {
result.add(token);
}
}
return result;
}
/**
* Split a string, and keep the delimiters
* @param input The string to be parsed and split
* @param delimiters A list of delimiters
* @return A strided list containing the parsed options, and the delimiters
*/
public static List<String> splitWithDelim(String input, String... delimiters) {
List<String> result = new ArrayList<>();
StringBuilder regex = new StringBuilder("(");
// Constructing the regular expression pattern with provided delimiters
for (String delimiter : delimiters) {
regex.append(delimiter).append("|");
}
regex.deleteCharAt(regex.length() - 1); // Remove the extra '|' character
regex.append(")");
// Splitting the input string using the regex pattern
String[] tokens = input.split(regex.toString());
// Adding tokens and delimiters to the result list in a strided manner
for (int i = 0; i < tokens.length; i++) {
if (!tokens[i].isEmpty()) {
result.add(tokens[i]);
}
// Adding delimiter if it exists and it's not the last token
if (i < tokens.length - 1) {
result.add(input.substring(input.indexOf(tokens[i]) + tokens[i].length(), input.indexOf(tokens[i + 1])));
}
}
return result;
}
private Lists(){
}
}

View file

@ -0,0 +1,49 @@
package dev.zontreck.ariaslib.util;
import java.util.HashMap;
import java.util.Map;
/**
* Utility class to assist in creating a dictionary programmatically in one line of code.
*/
public class Maps
{
/**
* This takes a list of entries and returns a HashMap
* @param entries The entries you want in your hashmap
* @return The map itself
* @param <A> Any typed parameter
* @param <B> Any typed parameter
*/
public static <A,B> Map<A,B> of(Entry<A,B>... entries) {
Map<A,B> map = new HashMap<>();
for(Entry<A,B> E : entries)
{
map.put(E.key, E.value);
}
return map;
}
/**
* A virtual entry used only by the Maps#of function.
* @see Maps#of(Entry[])
* @param <A> Any typed parameter
* @param <B> Any typed parameter
*/
public static class Entry<A,B> {
public final A key;
public final B value;
/**
* Initializes the readonly entry
* @param a The dictionary key
* @param b The value
*/
public Entry(A a, B b)
{
this.key=a;
this.value=b;
}
}
}

View file

@ -0,0 +1,18 @@
package dev.zontreck.ariaslib.util;
/**
* This class will be used to house math helper functions
*/
public class MathUtil
{
/**
* A newer helper function to get the percentage with large number support
* @param current Min value
* @param max Maximum value for progress
* @return Percentage
*/
public static int getPercent(long current, long max)
{
return Math.round(current*100/max);
}
}

View file

@ -0,0 +1,23 @@
package dev.zontreck.ariaslib.util;
import java.io.PrintStream;
public class Percent
{
int current;
int maximum;
public Percent(int cur, int max)
{
current=cur;
maximum=max;
}
public int get()
{
return ((current * 100) / maximum);
}
}

View file

@ -0,0 +1,56 @@
package dev.zontreck.ariaslib.util;
import java.util.concurrent.atomic.AtomicInteger;
public class Progress
{
private int maximum;
private int current;
private AtomicInteger tickNum = new AtomicInteger(0);
private static final String TICKS="-\\|/";
public String getSpinnerTick()
{
if(tickNum.get()>=TICKS.length()) tickNum.set(0);
return "[" + TICKS.substring(tickNum.getAndIncrement(), tickNum.get()) + "]";
}
public Progress(int maximum)
{
current=0;
this.maximum=maximum;
}
public int getPercent(){
return (current*100/maximum);
}
public String getPercentStr()
{
return (getPercent()+"%");
}
public static int getPercentOf(int current, int max)
{
return (current*100/max);
}
public void increment(){
current++;
sanity();
}
private void sanity(){
if(current > maximum) current = maximum;
if(current < 0)current = 0;
}
public void decrement(){
current--;
sanity();
}
public void setCurrent(int cur)
{
current=cur;
}
}

View file

@ -0,0 +1,66 @@
package dev.zontreck.ariaslib.util;
import java.io.PrintStream;
/**
* Utility to create an ascii progress bar
*/
public class ProgressBar
{
private static final int DEFAULT_BAR_WIDTH = 50;
/**
* Reserved spaces for the brackets, and the carrot, and the percent value.
*/
private static final int PROGRESS_BAR_RESERVED=5;
/**
* Always will return 80
* @return 80
*/
private static int getConsoleWidth() {
return 80; // Default console width, can be adjusted for different consoles
}
/**
* Build a progress bar
* <br><br>
* your text here [========= ] 40% your text here
* @param percent The percentage
* @param beforeText
* @param afterText
* @return ProgressBar as a String
*/
public static String printProgressBar(int percent, String beforeText, String afterText) {
StringBuilder sb = new StringBuilder();
int consoleWidth = getConsoleWidth();
int barWidth = Math.min(consoleWidth - beforeText.length() - afterText.length() - PROGRESS_BAR_RESERVED, DEFAULT_BAR_WIDTH);
// Calculate progress
int progressBarLength = (int) ((double) percent / 100 * barWidth);
// Print before text
sb.append(beforeText);
// Print progress bar
sb.append("[");
for (int i = 0; i < barWidth; i++) {
if (i < progressBarLength) {
sb.append("=");
}else if(i==progressBarLength) sb.append(">");
else {
sb.append(" ");
}
}
sb.append("]");
// Print percentage
sb.append(" " + percent + "%");
// Print after text
sb.append(afterText);
return sb.toString();
}
}

View file

@ -0,0 +1,161 @@
package dev.zontreck.ariaslib.util;
import java.util.List;
/**
* Contains useful structures and functions for dealing with, and manipulation of, time.
*/
public class TimeNotation
{
public int Years;
public int Months;
public int Weeks;
public int Days;
public int Hours;
public int Minutes;
public int Seconds;
public TimeNotation(int years, int months, int weeks, int days, int hours, int minutes, int seconds)
{
Years=years;
Months=months;
Weeks=weeks;
Days=days;
Hours=hours;
Minutes=minutes;
Seconds = seconds;
}
private TimeNotation(){}
@Override
public String toString() {
String str =
someOrNone(Years,Pluralize(Years, "year") + ", ") +
someOrNone(Months, Pluralize(Months, "month") + ", ") +
someOrNone(Weeks, Pluralize(Weeks, "week") + ", ") +
someOrNone(Days, Pluralize(Days, "day") + ", ") +
someOrNone(Hours, Pluralize(Hours, "hour") + ", ") +
someOrNone(Minutes, Pluralize(Minutes, "minute") + ", ") +
someOrNone(Seconds, Pluralize(Seconds, "second"));
if(str == ""){
return "No Seconds";
} else return str;
}
/**
* Create a plural version for a number
* @param num The number to prefix
* @param str The singular form of the string
* @return Combined string, num + str in plural form if necessary
*/
private String Pluralize(int num, String str)
{
return num + " " + ((num > 1) ? str+"s" : str);
}
/**
* A simple function to test a number, return a string, or return nothing at all.
* @param num The number to check
* @param str The string to return if the number is greater than zero
* @return Str if num >1, or empty string
*/
private String someOrNone(int num, String str)
{
if(num > 0) return str;
else return "";
}
/**
* A simple function to test a number, return a string, or return something else.
* @param num The number to check
* @param str The string to return if the number is greater than zero
* @return Str if num >1, or other string
*/
private String someOrOther(int num, String str, String other)
{
if(num > 0) return str;
else return other;
}
/**
* Encodes time notation!
* @return A program readable string that can be decoded back to a time notation
*/
public String toNotation()
{
return Years + "Y" + Months + "M" + Weeks + "W" + Days + "d" + Hours + "h" + Minutes + "m" + Seconds + "s";
}
/**
* Parses a time notation string
* @param notation Serialized time notation
* @return The deserialized time notation object
*/
public static TimeNotation fromNotation(String notation)
{
TimeNotation notationX = new TimeNotation();
String[] delims = new String[]{"Y", "M", "W", "d", "h", "m", "s"};
List<String> opts = Lists.split(notation, delims);
int index = 0;
for(String dlim : delims)
{
if(notation.contains(dlim))
{
switch (dlim)
{
case "Y":
{
notationX.Years = Integer.parseInt(opts.get(index));
break;
}
case "M":
{
notationX.Months = Integer.parseInt(opts.get(index));
break;
}
case "W":
{
notationX.Weeks = Integer.parseInt(opts.get(index));
break;
}
case "d":
{
notationX.Days = Integer.parseInt(opts.get(index));
break;
}
case "h":
{
notationX.Hours = Integer.parseInt(opts.get(index));
break;
}
case "m":
{
notationX.Minutes = Integer.parseInt(opts.get(index));
break;
}
case "s":
{
notationX.Seconds = Integer.parseInt(opts.get(index));
break;
}
}
index++;
}
}
return notationX;
}
}

View file

@ -0,0 +1,96 @@
package dev.zontreck.ariaslib.util;
/**
* This class is a helper with some minecraft specific functions
*/
public class TimeUtil
{
/**
* Converts seconds to ticks. (seconds*ticks)
* @param seconds Number of seconds
* @param ticks Number of ticks in a single second
* @return Number of ticks
*/
public static int secondsToTicks(int seconds, int ticks)
{
return seconds*ticks;
}
/**
* Converts the number of ticks to seconds
* @param ticks The number of ticks to convert
* @param ticksInASecond The number of ticks in a single second
* @return Number of seconds
*/
public static int ticksToSeconds(int ticks, int ticksInASecond)
{
return ticks / ticksInASecond;
}
/**
* Encodes a LibAC Time Notation
* @param seconds Number of seconds to convert
* @return Time Notation
*/
public static TimeNotation secondsToTimeNotation(int seconds)
{
int years = seconds / YEAR;
if(years > 0) seconds -= YEAR * years;
int month = seconds / MONTH;
if(month > 0) seconds -= MONTH * month;
int week = seconds / WEEK;
if(week > 0) seconds -= WEEK * week;
int day = seconds / DAY;
if(day > 0) seconds -= DAY * day;
int hour = seconds / HOUR;
if(hour > 0) seconds -= HOUR * hour;
int minute = seconds / MINUTE;
if(minute > 0) seconds -= MINUTE * minute;
return new TimeNotation(years, month, week, day, hour, minute, seconds);
}
/**
* Convert a time notation to seconds
* @param notation Notation to convert
* @return Total seconds
*/
public static int notationToSeconds(TimeNotation notation)
{
int seconds = 0;
seconds += (notation.Years * YEAR);
seconds += (notation.Months * MONTH);
seconds += (notation.Weeks * WEEK);
seconds += (notation.Days * DAY);
seconds += (notation.Hours * HOUR);
seconds += (notation.Minutes * MINUTE);
seconds += (notation.Seconds);
return seconds;
}
public static final int SECOND;
public static final int MINUTE;
public static final int HOUR;
public static final int DAY;
public static final int WEEK;
public static final int MONTH;
public static final int YEAR;
static {
SECOND = 1;
MINUTE = SECOND * 60;
HOUR = MINUTE * 60;
DAY = HOUR*24;
WEEK = DAY*7;
MONTH = WEEK*4;
YEAR = DAY*365;
}
}

View file

@ -0,0 +1,32 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.util.Map;
public class MethodCall {
private String methodName;
private Object[] params;
public Map<String, Object> parameters;
public MethodCall ( String methodName , Object[] params , Map<String, Object> p ) {
this.methodName = methodName;
this.params = params;
this.parameters = p;
}
public String getMethodName ( ) {
return methodName;
}
public Object[] getParams ( ) {
return params;
}
public static MethodCall fromDeserializer ( XmlRpcDeserializer deserializer ) throws Exception {
String methodName = deserializer.readMethodName ( );
Object[] params = deserializer.readMethodParams ( );
Map<String, Object> parameters = ( Map<String, Object> ) params[ 0 ];
return new MethodCall ( methodName , params , parameters );
}
}

View file

@ -0,0 +1,26 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class MethodResponse {
public Map<String, Object> parameters = new HashMap<> ( );
public MethodResponse ( ) {
}
public String toXml ( ) {
ByteArrayOutputStream baos = new ByteArrayOutputStream ( );
XmlRpcStreamWriter streamWriter = new XmlRpcStreamWriter ( baos );
try {
streamWriter.writeMethodResponse ( parameters );
return new String ( baos.toByteArray ( ) );
} catch ( IOException e ) {
throw new RuntimeException ( e );
}
}
}

View file

@ -0,0 +1,7 @@
XMLRPC
======
-----------
This code is heavily auto-generated from ChatGPT, however, it contains a lot of modifications to make it actually work.

View file

@ -0,0 +1,44 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
public class XmlRpcDeserializer {
private XmlRpcStreamReader xmlStreamReader;
public XmlRpcDeserializer ( InputStream inputStream ) throws Exception {
xmlStreamReader = new XmlRpcStreamReader ( inputStream );
}
public String skipXmlHeader(String xml) {
int startIndex = xml.indexOf("<?xml");
if (startIndex >= 0) {
int endIndex = xml.indexOf("?>", startIndex);
if (endIndex >= 0) {
return xml.substring(endIndex + 2);
}
}
return xml;
}
public XmlRpcDeserializer ( String xml ) throws Exception {
byte[] xmlBytes = xml.getBytes ( );
ByteArrayInputStream inputStream = new ByteArrayInputStream ( xmlBytes );
xmlStreamReader = new XmlRpcStreamReader ( inputStream );
}
public String readMethodName ( ) throws Exception {
return xmlStreamReader.readMethodCallMethodName ( );
}
public Object[] readMethodParams ( ) throws Exception {
return xmlStreamReader.readMethodCallParams ( );
}
public Object readMethodResponse ( ) throws Exception {
return xmlStreamReader.readMethodResponseResult ( );
}
public void close ( ) throws Exception {
xmlStreamReader.close ( );
}
}

View file

@ -0,0 +1,24 @@
package dev.zontreck.ariaslib.xmlrpc;
public class XmlRpcException extends Exception {
public XmlRpcException ( int code , String message ) {
super ( message );
FaultCode = code;
FaultString = message;
}
public final String FaultString;
public final int FaultCode;
@Override
public String toString ( ) {
StringBuilder sb = new StringBuilder ( );
sb.append ( "Code: " +FaultCode);
sb.append ( "\nMessage: " +FaultString);
sb.append ( "\n\n" );
return sb.toString ();
}
}

View file

@ -0,0 +1,26 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
public class XmlRpcSerializer {
private XmlRpcStreamWriter writer;
public XmlRpcSerializer ( OutputStream outputStream ) {
this.writer = new XmlRpcStreamWriter ( outputStream );
}
public void serializeMethodCall ( String methodName , List<Object> params ) throws IOException {
writer.writeMethodCall ( methodName , params );
}
public void serializeMethodResponse ( Object value ) throws IOException {
writer.writeMethodResponse ( value );
}
public void close ( ) throws IOException {
writer.close ( );
}
}

View file

@ -0,0 +1,206 @@
package dev.zontreck.ariaslib.xmlrpc;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class XmlRpcStreamReader {
private XMLStreamReader xmlStreamReader;
public XmlRpcStreamReader ( InputStream inputStream ) throws XMLStreamException {
XMLInputFactory inputFactory = XMLInputFactory.newInstance ( );
xmlStreamReader = inputFactory.createXMLStreamReader ( inputStream );
}
private String CURRENT_TAG_NAME;
private int ELEM_TYPE;
public boolean nextTag ( ) throws XMLStreamException {
while ( xmlStreamReader.hasNext ( ) ) {
int eventType = xmlStreamReader.next ( );
if ( eventType == XMLStreamConstants.START_ELEMENT || eventType == XMLStreamConstants.END_ELEMENT ) {
CURRENT_TAG_NAME = getLocalName ( );
ELEM_TYPE = xmlStreamReader.getEventType ( );
return true;
}
}
return false;
}
public String getLocalName ( ) {
return xmlStreamReader.getLocalName ( );
}
public String getElementText ( ) throws XMLStreamException {
return xmlStreamReader.getElementText ( );
}
public void require ( int type , String namespaceURI , String localName ) throws XMLStreamException {
xmlStreamReader.require ( type , namespaceURI , localName );
}
public String readMethodCallMethodName ( ) throws XMLStreamException {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "methodCall" );
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "methodName" );
return getElementText ( );
}
public Object[] readMethodCallParams ( ) throws XMLStreamException {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "params" );
return deserializeParams ( );
}
private Object[] deserializeParams ( ) throws XMLStreamException {
List<Object> paramsList = new ArrayList<> ( );
while ( xmlStreamReader.hasNext ( ) ) {
int event = xmlStreamReader.next ( );
if ( event == XMLStreamConstants.START_ELEMENT ) {
String elementName = xmlStreamReader.getLocalName ( );
if ( elementName.equals ( "param" ) ) {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "value" );
Object value = deserializeValue ( );
paramsList.add ( value );
}
}
}
return paramsList.toArray ( );
}
public Object readMethodResponseResult ( ) throws XMLStreamException {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "methodResponse" );
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "params" );
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "param" );
return deserializeValue ( );
}
private Object deserializeValue ( ) throws XMLStreamException {
nextTag ( );
int eventType = xmlStreamReader.getEventType ( );
if ( eventType == XMLStreamConstants.CHARACTERS || eventType == XMLStreamConstants.CDATA ) {
return xmlStreamReader.getText ( );
}
else if ( eventType == XMLStreamConstants.START_ELEMENT ) {
String localName = xmlStreamReader.getLocalName ( );
switch ( localName ) {
case "string":
return deserializeString ( );
case "i4":
case "int":
return deserializeInt ( );
case "double":
return deserializeDouble ( );
case "boolean":
return deserializeBoolean ( );
case "array":
return deserializeArray ( );
case "struct":
return deserializeStruct ( );
case "nil":
return null;
case "i8":
return deserializeLong ( );
default:
throw new IllegalArgumentException ( "Unsupported element: " + localName );
}
}
else {
throw new IllegalArgumentException ( "Unexpected event type: " + eventType );
}
}
private String deserializeString ( ) throws XMLStreamException {
return getElementText ( );
}
private int deserializeInt ( ) throws XMLStreamException {
return Integer.parseInt ( getElementText ( ) );
}
private byte deserializeByte ( ) throws XMLStreamException {
return Byte.parseByte ( getElementText ( ) );
}
private long deserializeLong ( ) throws XMLStreamException {
return Long.parseLong ( getElementText ( ) );
}
private double deserializeDouble ( ) throws XMLStreamException {
return Double.parseDouble ( getElementText ( ) );
}
private boolean deserializeBoolean ( ) throws XMLStreamException {
return Boolean.parseBoolean ( getElementText ( ) );
}
private Object[] deserializeArray ( ) throws XMLStreamException {
List<Object> arr = new ArrayList<> ( );
while ( nextTag ( ) ) {
if ( CURRENT_TAG_NAME.equals ( "data" ) && ELEM_TYPE == XMLStreamConstants.END_ELEMENT ) {
break;
}
else if ( CURRENT_TAG_NAME.equals ( "value" ) && ELEM_TYPE == XMLStreamConstants.START_ELEMENT ) {
arr.add ( deserializeValue ( ) );
}
}
return arr.toArray ( );
}
private Map<String, Object> deserializeStruct ( ) throws XMLStreamException {
Map<String, Object> struct = new HashMap<> ( );
String name = null;
while ( nextTag ( ) ) {
if ( xmlStreamReader.getLocalName ( ).equals ( "member" ) ) {
name = null;
}
else if ( xmlStreamReader.getLocalName ( ).equals ( "name" ) ) {
name = getElementText ( );
}
else if ( xmlStreamReader.getLocalName ( ).equals ( "value" ) && xmlStreamReader.getEventType ( ) == XMLStreamConstants.START_ELEMENT ) {
if ( name != null ) {
Object value = deserializeValue ( );
struct.put ( name , value );
}
}
else if ( CURRENT_TAG_NAME.equals ( "struct" ) && xmlStreamReader.getEventType ( ) == XMLStreamConstants.END_ELEMENT ) {
break;
}
}
return struct;
}
public static String skipXmlHeader ( String xml ) {
int startIndex = xml.indexOf ( "<?xml" );
if ( startIndex >= 0 ) {
int endIndex = xml.indexOf ( "?>" , startIndex );
if ( endIndex >= 0 ) {
return xml.substring ( endIndex + 2 );
}
}
return xml;
}
public void close ( ) throws XMLStreamException {
xmlStreamReader.close ( );
}
}

View file

@ -0,0 +1,166 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import java.util.Map;
public class XmlRpcStreamWriter {
private static final String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
private static final String METHOD_CALL_START_TAG = "<methodCall>";
private static final String METHOD_CALL_END_TAG = "</methodCall>\n";
private static final String METHOD_NAME_START_TAG = "<methodName>";
private static final String METHOD_NAME_END_TAG = "</methodName>\n";
private static final String METHOD_RESPONSE_START_TAG = "<methodResponse>";
private static final String METHOD_RESPONSE_END_TAG = "</methodResponse>\n";
private static final String PARAMS_START_TAG = "<params>";
private static final String PARAMS_END_TAG = "</params>\n";
private static final String PARAM_START_TAG = "<param>";
private static final String PARAM_END_TAG = "</param>\n";
private static final String VALUE_START_TAG = "<value>";
private static final String VALUE_END_TAG = "</value>\n";
private static final String ARRAY_START_TAG = "<array>";
private static final String ARRAY_END_TAG = "</array>\n";
private static final String DATA_START_TAG = "<data>";
private static final String DATA_END_TAG = "</data>\n";
private static final String STRUCT_START_TAG = "<struct>";
private static final String STRUCT_END_TAG = "</struct>\n";
private static final String MEMBER_START_TAG = "<member>";
private static final String MEMBER_END_TAG = "</member>\n";
private static final String NAME_START_TAG = "<name>";
private static final String NAME_END_TAG = "</name>\n";
private Writer writer;
public XmlRpcStreamWriter ( OutputStream outputStream ) {
this.writer = new OutputStreamWriter ( outputStream );
}
public void writeMethodCall ( String methodName , List<Object> params ) throws IOException {
writer.write ( XML_VERSION );
writer.write ( METHOD_CALL_START_TAG );
writer.write ( METHOD_NAME_START_TAG );
writer.write ( methodName );
writer.write ( METHOD_NAME_END_TAG );
writer.write ( PARAMS_START_TAG );
if ( params != null ) {
for ( Object param : params ) {
writer.write ( PARAM_START_TAG );
writeValue ( param );
writer.write ( PARAM_END_TAG );
}
}
writer.write ( PARAMS_END_TAG );
writer.write ( METHOD_CALL_END_TAG );
writer.flush ( );
}
public void writeMethodResponse ( Object value ) throws IOException {
writer.write ( XML_VERSION );
writer.write ( METHOD_RESPONSE_START_TAG );
writer.write ( PARAMS_START_TAG );
writer.write ( PARAM_START_TAG );
writeValue ( value );
writer.write ( PARAM_END_TAG );
writer.write ( PARAMS_END_TAG );
writer.write ( METHOD_RESPONSE_END_TAG );
writer.flush ( );
}
private void writeValue ( Object value ) throws IOException {
if ( value == null ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<nil/>" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof String ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<string>" );
writer.write ( escapeXml ( ( String ) value ) );
writer.write ( "</string>\n" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Integer ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<i4>" );
writer.write ( value.toString ( ) );
writer.write ( "</i4>\n" );
writer.write ( VALUE_END_TAG );
} else if(value instanceof Long)
{
writer.write ( VALUE_START_TAG );
writer.write ( "<i8>" );
writer.write ( value.toString () ); // Save it as a int for now due to unclear handling
writer.write ( "</i8>\n" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Double ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<double>" );
writer.write ( value.toString ( ) );
writer.write ( "</double>\n" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Boolean ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<string>" );
writer.write ( value.toString ( ) );
writer.write ( "</string>\n" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof List ) {
writer.write ( VALUE_START_TAG );
writer.write ( ARRAY_START_TAG );
writer.write ( DATA_START_TAG );
List<?> list = ( List<?> ) value;
for ( Object item : list ) {
writeValue ( item );
}
writer.write ( DATA_END_TAG );
writer.write ( ARRAY_END_TAG );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Map ) {
writer.write ( VALUE_START_TAG );
writer.write ( STRUCT_START_TAG );
Map<?, ?> map = ( Map<?, ?> ) value;
for ( Map.Entry<?, ?> entry : map.entrySet ( ) ) {
writer.write ( MEMBER_START_TAG );
writer.write ( NAME_START_TAG );
writer.write ( escapeXml ( entry.getKey ( ).toString ( ) ) );
writer.write ( NAME_END_TAG );
writeValue ( entry.getValue ( ) );
writer.write ( MEMBER_END_TAG );
}
writer.write ( STRUCT_END_TAG );
writer.write ( VALUE_END_TAG );
}
else if(value instanceof Byte)
{
writer.write ( VALUE_START_TAG );
writer.write ( "<int>" );
writer.write ( value.toString () ); // Treat as a integer for now
writer.write ( "</int>\n" );
writer.write ( VALUE_END_TAG );
}
else {
throw new IllegalArgumentException ( "Unsupported data type: " + value.getClass ( ).getName ( ) );
}
}
private String escapeXml ( String value ) {
return value
.replace ( "&" , "&amp;" )
.replace ( "<" , "&lt;" )
.replace ( ">" , "&gt;" )
.replace ( "\"" , "&quot;" )
.replace ( "'" , "&apos;" );
}
public void close ( ) throws IOException {
writer.close ( );
}
}

View file

@ -0,0 +1,48 @@
package dev.zontreck.ariaslib.xmlrpc;
public class XmlRpcTokens
{
public final String ISO_DATETIME = "yyyyMMdd\\THH\\:mm\\:ss";
public final String BASE64 = "base64";
public final String STRING = "string";
public final String INT = "i4";
public final String ALT_INT = "int";
public final String DATETIME = "dateTime.iso8601";
public final String BOOLEAN = "boolean";
public final String VALUE = "value";
public final String NAME = "name";
public final String ARRAY = "array";
public final String DATA = "data";
public final String MEMBER = "member";
public final String STRUCT = "struct";
public final String DOUBLE = "double";
public final String PARAM = "param";
public final String PARAMS = "params";
public final String METHOD_CALL = "methodCall";
public final String METHOD_NAME = "methodName";
public final String METHOD_RESPONSE = "methodResponse";
public final String FAULT = "fault";
public final String FAULT_CODE = "faultCode";
public final String FAULT_STRING = "faultString";
}

View file

@ -0,0 +1,166 @@
package dev.zontreck.eventsbus;
import dev.zontreck.eventsbus.annotations.Priority;
import dev.zontreck.eventsbus.annotations.SingleshotEvent;
import dev.zontreck.eventsbus.annotations.Subscribe;
import dev.zontreck.eventsbus.events.EventBusReadyEvent;
import dev.zontreck.eventsbus.events.ResetEventBusEvent;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
/**
* To be removed
* <br/>
* Use {EventDispatcher} instead
*/
@Deprecated()
public class Bus {
/**
* The main event bus!
*/
private static Bus Main;
static {
if(Main == null)
{
Main = new Bus("Main Event Bus", false);
}
}
public static boolean debug = false;
public final String BusName;
public final boolean UsesInstances;
public Bus(String name, boolean useInstances) {
BusName = name;
UsesInstances = useInstances;
Post(new EventBusReadyEvent());
}
public Map<Class<?>, List<EventContainer>> static_events = new HashMap<Class<?>, List<EventContainer>>();
public Map<Class<?>, List<EventContainer>> instanced_events = new HashMap<Class<?>, List<EventContainer>>();
public static <T> void Register(Class<T> clazz, T instance) {
List<Method> nonStaticMethods = Arrays.stream(clazz.getMethods())
.filter(x -> x.isAnnotationPresent(Subscribe.class))
.filter(x -> (x.getModifiers() & Modifier.STATIC) != Modifier.STATIC)
.collect(Collectors.toList());
List<Method> staticMethods = Arrays.stream(clazz.getMethods())
.filter(x -> x.isAnnotationPresent(Subscribe.class))
.filter(x -> (x.getModifiers() & Modifier.STATIC) == Modifier.STATIC)
.collect(Collectors.toList());
// Register the non-static methods if applicable
if (instance != null) {
for (Method m :
nonStaticMethods) {
EventContainer container = new EventContainer();
container.instance = instance;
container.method = m;
container.clazz = clazz;
if (m.isAnnotationPresent(Priority.class))
container.Level = m.getAnnotation(Priority.class).Level();
else container.Level = PriorityLevel.LOWEST;
Class<?> clz = m.getParameters()[0].getType();
container.IsSingleshot = m.isAnnotationPresent(SingleshotEvent.class);
if (Main.instanced_events.containsKey(clz))
Main.instanced_events.get(clz).add(container);
else {
Main.instanced_events.put(clz, new ArrayList<>());
Main.instanced_events.get(clz).add(container);
}
}
}
for (Method m : staticMethods) {
EventContainer container = new EventContainer();
container.instance = null;
container.method = m;
container.clazz = clazz;
if (m.isAnnotationPresent((Priority.class)))
container.Level = m.getAnnotation(Priority.class).Level();
else container.Level = PriorityLevel.LOWEST;
Class<?> clz = m.getParameters()[0].getType();
container.IsSingleshot = m.isAnnotationPresent(SingleshotEvent.class);
if (Main.static_events.containsKey(clz))
Main.static_events.get(clz).add(container);
else {
Main.static_events.put(clz, new ArrayList<>());
Main.static_events.get(clz).add(container);
}
}
}
/**
* Posts an event to the bus.
*
* @param event The event you wish to post
* @return True if the event was cancelled.
*/
public static boolean Post(Event event) {
for (PriorityLevel level :
PriorityLevel.values()) {
// Call each priority level in order of declaration
// Static first, then instanced
// At the end, this method will return the cancellation result.
try {
if (Main.static_events.containsKey(event.getClass())) {
EventContainer[] tempArray = (EventContainer[]) Main.static_events.get(event.getClass()).toArray();
for (EventContainer container : tempArray) {
if (container.invoke(event, level)) {
Main.static_events.get(event.getClass()).remove(container);
}
}
}
if (Main.instanced_events.containsKey(event.getClass())) {
EventContainer[] tempArray = (EventContainer[]) Main.instanced_events.get(event.getClass()).toArray();
for (EventContainer container : tempArray) {
if (container.invoke(event, level)) {
Main.instanced_events.get(event.getClass()).remove(container);
}
}
}
} catch (Exception e) {
}
}
return event.isCancelled();
}
/**
* Attempts to reset the Event Bus
*
* @return True if the bus was successfully reset (If not interrupts!)
* @see dev.zontreck.eventsbus.events.ResetEventBusEvent
*/
public static boolean Reset() {
if (!Post(new ResetEventBusEvent())) {
Main.static_events = new HashMap<>();
Main.instanced_events = new HashMap<>();
Post(new EventBusReadyEvent());
return true;
}
return false;
}
}

View file

@ -0,0 +1,95 @@
package dev.zontreck.eventsbus;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@Deprecated
/**
* Used internally. Do not directly invoke
* <br/>
* Accessor is set Protected intentionally!!!!!!!!!
*/
class ClassScanner {
/**
* Start the process of scanning the classes and forcing them to load in
* <br/>
* This is used by the event dispatcher
*/
protected static void DoScan() {
// Scan all classes in the classpath
Set<Class<?>> scannedClasses = scanClasses();
// Force loading of all scanned classes
for (Class<?> clazz : scannedClasses) {
try {
// Load the class
Class.forName(clazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
private static Set<Class<?>> scanClasses() {
String classpath = System.getProperty("java.class.path");
String[] classpathEntries = classpath.split(File.pathSeparator);
Set<Class<?>> scannedClasses = new HashSet<>();
for (String classpathEntry : classpathEntries) {
File file = new File(classpathEntry);
if (file.isDirectory()) {
scanClassesInDirectory(file, "", scannedClasses);
} else if (file.isFile() && classpathEntry.endsWith(".jar")) {
scanClassesInJar(file, scannedClasses);
}
}
return scannedClasses;
}
private static void scanClassesInDirectory(File directory, String packageName, Set<Class<?>> scannedClasses) {
File[] files = directory.listFiles();
if (files == null) {
return;
}
for (File file : files) {
if (file.isDirectory()) {
scanClassesInDirectory(file, packageName + "." + file.getName(), scannedClasses);
} else if (file.getName().endsWith(".class")) {
String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
try {
Class<?> clazz = Class.forName(className);
scannedClasses.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
private static void scanClassesInJar(File jarFile, Set<Class<?>> scannedClasses) {
try (JarFile jf = new JarFile(jarFile)) {
for (JarEntry entry : Collections.list(jf.entries())) {
if (entry.getName().endsWith(".class")) {
String className = entry.getName().replace("/", ".").substring(0, entry.getName().length() - 6);
try {
Class<?> clazz = Class.forName(className);
scannedClasses.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,46 @@
package dev.zontreck.eventsbus;
import dev.zontreck.eventsbus.annotations.Cancellable;
import dev.zontreck.eventsbus.annotations.Priority;
public class Event {
private boolean cancelled = false;
/**
* Checks if the event can be cancelled.
*
* @return True if the cancellation annotation is present.
* @see Cancellable
*/
public boolean IsCancellable() {
Class<?> Current = this.getClass();
return Current.isAnnotationPresent(Cancellable.class);
}
/**
* Checks if the event is cancelled.
*
* @return False if the event cannot be cancelled; or
* The current cancellation status for the event
*/
public boolean isCancelled() {
if (!IsCancellable())
return false;
return cancelled;
}
/**
* Sets the cancelled status for the event
*
* @param cancel Whether the event should be marked as cancelled or not.
*/
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
public PriorityLevel getPriorityLevel() {
Class<?> Current = this.getClass();
return Current.getAnnotation(Priority.class).Level();
}
}

View file

@ -0,0 +1,45 @@
package dev.zontreck.eventsbus;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class EventContainer {
public Class<?> clazz;
public Object instance;
/**
* The method that gets invoked, either statically, or via the instance.
*/
public Method method;
/**
* Indicates whether an event gets removed from the register after being invoked once.
*/
public boolean IsSingleshot;
/**
* The current method's priority level
*/
public PriorityLevel Level;
/**
* Invokes the event
*
* @param EventArg The event instance to pass to the subscribed function
* @param level Current priority level on the call loop. Will refuse to invoke if the priority level mismatches.
* @return True if the event was single shot and should be deregistered
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public boolean invoke(Event EventArg, PriorityLevel level) throws InvocationTargetException, IllegalAccessException {
if (Level != level) return false;
if (instance == null) {
method.invoke(null, EventArg);
} else {
method.invoke(instance, EventArg);
}
return IsSingleshot;
}
}

View file

@ -0,0 +1,124 @@
package dev.zontreck.eventsbus;
import dev.zontreck.eventsbus.annotations.EventSubscriber;
import dev.zontreck.eventsbus.annotations.Priority;
import dev.zontreck.eventsbus.annotations.SingleshotEvent;
import dev.zontreck.eventsbus.annotations.Subscribe;
import dev.zontreck.eventsbus.events.EventBusReadyEvent;
import dev.zontreck.eventsbus.events.ResetEventBusEvent;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class EventDispatcher
{
private static List<Method> singleshot = new ArrayList<>();
private static List<Class<?>> subscribers = new ArrayList<>();
/**
* Scans every Java class that is currently loaded. It then checks for Subscribe, and a proper parameter before posting the Event.
* The Event will only be posted if not cancelled using {@link Event#setCancelled(boolean)} and that {@link Subscribe#allowCancelled()} allows.
* @param event The event to post
* @return True if cancelled.
*/
public static boolean Post(Event event)
{
for(PriorityLevel level : PriorityLevel.values())
{
for(Class<?> clazz : subscribers)
{
for(Method M :clazz.getMethods())
{
if(!M.isAnnotationPresent(Subscribe.class)) continue;
Subscribe subscriber = M.getAnnotation(Subscribe.class);
boolean canPost=true;
Class<?> param = M.getParameterTypes()[0];
if(param == event.getClass())
{
if(M.isAnnotationPresent(SingleshotEvent.class))
{
if(singleshot.contains(M))
{
canPost=false;
}
}
} else canPost=false;
PriorityLevel eventPriotityLevel= PriorityLevel.HIGH; // Default
if(M.isAnnotationPresent(Priority.class))
{
Priority prio = M.getAnnotation(Priority.class);
eventPriotityLevel=prio.Level();
}
if(level != eventPriotityLevel)
{
canPost=false;
}
// Dispatch the event now
if(!canPost) continue;
if(!M.canAccess(null))
{
canPost=false;
System.out.println("ERROR: Even subscriber methods must be static and public");
}
try {
if(event.isCancelled() && !subscriber.allowCancelled())
continue;
else
M.invoke(null, event);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
}
return event.isCancelled();
}
/**
* Register a class
*/
public static void Register(Class<?> clazz)
{
if(clazz.isAnnotationPresent(EventSubscriber.class))
subscribers.add(clazz);
}
/**
* Resets the events system.
* <br/>
* This action clears the Singleshot list for the events that should only be invoked once. And rescans all classes incase new classes were dynamically loaded.
*/
public static void Reset()
{
Post(new ResetEventBusEvent());
subscribers.clear();
singleshot.clear();
Post(new EventBusReadyEvent());
}
}

View file

@ -0,0 +1,15 @@
package dev.zontreck.eventsbus;
/**
* Event priority level.
* <p>
* The higher the priority, the sooner it gets executed. High is executed after
* Highest.
*/
public enum PriorityLevel {
HIGHEST,
HIGH,
MEDIUM,
LOW,
LOWEST
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.eventsbus.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface Cancellable {
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.eventsbus.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface EventSubscriber {
}

View file

@ -0,0 +1,14 @@
package dev.zontreck.eventsbus.annotations;
import dev.zontreck.eventsbus.PriorityLevel;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface Priority {
PriorityLevel Level();
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.eventsbus.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface SingleshotEvent {
}

View file

@ -0,0 +1,18 @@
package dev.zontreck.eventsbus.annotations;
import dev.zontreck.eventsbus.Event;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface Subscribe {
/**
* Marks that the subscribed method will not receive the signal if the event was cancelled with {@link Event#setCancelled(boolean)}
*/
boolean allowCancelled();
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.eventsbus.events;
import dev.zontreck.eventsbus.Event;
/**
* This event is sent out when the Event Bus is ready.
* <p>
* This is also dispatched when a reset occurs, prior to clearing the lists.
*/
public class EventBusReadyEvent extends Event {
}

View file

@ -0,0 +1,17 @@
package dev.zontreck.eventsbus.events;
import dev.zontreck.eventsbus.annotations.Cancellable;
import dev.zontreck.eventsbus.Event;
/**
* Posted when the event bus is about to be reset.
* <p>
* This event can be cancelled to prevent the reset.
* <p>
* The default behavior is: Allow Reset.
* <p>
* Recommended that handlers be implemented to re-register instances, and classes when a reset occurs.
*/
@Cancellable
public class ResetEventBusEvent extends Event {
}

View file

@ -0,0 +1,6 @@
package dev.zontreck.eventsbus.events;
import dev.zontreck.eventsbus.Event;
public class TickEvent extends Event {
}

View file

@ -3,34 +3,39 @@ package dev.zontreck.libzontreck;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import dev.zontreck.ariaslib.util.DelayedExecutorService;
import dev.zontreck.eventsbus.Bus;
import dev.zontreck.libzontreck.chestgui.ChestGUIRegistry;
import dev.zontreck.libzontreck.config.ServerConfig;
import dev.zontreck.libzontreck.currency.Bank;
import dev.zontreck.libzontreck.currency.CurrencyHelper;
import dev.zontreck.libzontreck.items.CreativeModeTabs;
import dev.zontreck.libzontreck.events.BlockRestoreQueueRegistrationEvent;
import dev.zontreck.libzontreck.items.ModItems;
import dev.zontreck.libzontreck.memory.world.BlockRestoreQueue;
import dev.zontreck.libzontreck.memory.world.BlockRestoreQueueRegistry;
import dev.zontreck.libzontreck.memory.world.DatabaseMigrations;
import dev.zontreck.libzontreck.memory.world.DatabaseWrapper;
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 net.minecraftforge.registries.RegisterEvent;
import net.minecraft.server.level.ServerLevel;
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.memory.player.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;
@ -47,7 +52,6 @@ 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();
@ -57,6 +61,7 @@ public class LibZontreck {
public static final UUID NULL_ID;
public static boolean LIBZONTRECK_SERVER_AVAILABLE=false;
public static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
public static LogicalSide CURRENT_SIDE;
@ -83,6 +88,8 @@ public class LibZontreck {
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
// Register the setup method for modloading
bus.addListener(this::setup);
ServerConfig.init();
MinecraftForge.EVENT_BUS.register(this);
@ -91,14 +98,14 @@ public class LibZontreck {
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);
MinecraftForge.EVENT_BUS.register(CurrencyHelper.class);
MinecraftForge.EVENT_BUS.register(Bank.class);
}
private void setup(final FMLCommonSetupEvent event)
@ -110,16 +117,39 @@ public class LibZontreck {
@SubscribeEvent
public void onServerStarted(final ServerStartedEvent event)
{
THE_SERVER = event.getServer();
ALIVE=true;
ServerConfig.init();
try {
DatabaseWrapper.start();
}catch(RuntimeException e) {
LOGGER.warn("Database not configured properly, it will not be available.");
DatabaseWrapper.invalidate();
}
CURRENT_SIDE = LogicalSide.SERVER;
MinecraftForge.EVENT_BUS.post(new BlockRestoreQueueRegistrationEvent());
for(ServerLevel level : event.getServer().getAllLevels())
{
// Queues have been registered, but we now need to initialize the queue's data from saveddata
BlockRestoreQueueRegistry.init(level);
}
if(!DatabaseWrapper.hasDB)return;
try {
DatabaseMigrations.initMigrations();
} catch (SQLException e) {
e.printStackTrace();
}
}
@SubscribeEvent
public void onServerStopping(final ServerStoppingEvent ev)
{
ALIVE=false;
DelayedExecutorService.stop();
Iterator<Profile> iProfile = PROFILES.values().iterator();
while(iProfile.hasNext())

View file

@ -0,0 +1,138 @@
package dev.zontreck.libzontreck.api;
import dev.zontreck.libzontreck.vectors.Vector2f;
import dev.zontreck.libzontreck.vectors.Vector2i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.phys.Vec2;
public interface Vector2<T> extends Cloneable, Comparable<Vector2<T>>
{
/**
* Converts the current Vector2 representation into a minecraft Vec2
* @return Minecraft equivalent Vec2
*/
Vec2 asMinecraftVector();
/**
* Parses a string in serialized format.
* @param vector2 Expects it in the same format returned by Vector2#toString
* @return New Vector2, or a null Vector2 initialized with zeros if invalid data
*/
static Vector2 parseString(String vector2){
throw new UnsupportedOperationException("This method is not implemented by this implementation");
}
/**
* Copies the values to a new and detached instance
* @return New Vector2
*/
Vector2 Clone();
/**
* Saves the X and Y positions to a NBT tag
* @return NBT compound tag
*/
CompoundTag serialize();
/**
* Loads a Vector2 from a NBT tag
* @param tag The NBT tag to load
*/
static Vector2 deserialize(CompoundTag tag)
{
throw new UnsupportedOperationException("This method is not implemented by this implementation");
}
/**
* Compares the two vector2 instances
* @param other The position to check
* @return True if same position
*/
boolean Same(Vector2 other);
/**
* True if the current position is inside the two points
* @param point1 Lowest point
* @param point2 Hightest Point
* @return True if inside
*/
boolean Inside(Vector2 point1, Vector2 point2);
/**
* Converts, if necessary, to Vector2d
* @return A vector2d instance
*/
Vector2f asVector2f();
/**
* Converts, if necessary, to Vector2i
* @return A vector2i instance
*/
Vector2i asVector2i();
/**
* Checks if the current vector is greater than the provided one
* @param other The other vector to check
* @return True if greater
*/
boolean greater(Vector2 other);
/**
* Checks if the current vector is less than the provided one
* @param other The vector to check
* @return True if less than other
*/
boolean less(Vector2 other);
/**
* Alias for Vector2#same
* @param other Vector to check
* @return True if same position
*/
boolean equal(Vector2 other);
/**
* Adds the two vectors together
* @param other Vector to add
* @return New instance after adding the other vector
*/
Vector2 add(Vector2 other);
/**
* Subtracts the other vector from this one
* @param other Vector to subtract
* @return New instance after subtracting
*/
Vector2 subtract(Vector2 other);
/**
* Calculates the distance between the two vectors
* @param other
* @return The distance
*/
double distance(Vector2 other);
/**
* Increments the Y axis by 1
* @return New instance
*/
Vector2 moveUp();
/**
* Decrements the Y axis by 1
* @return New instance
*/
Vector2 moveDown();
/**
* Gets the X value
* @return X
*/
T getX();
/**
* Gets the Y value
* @return Y
*/
T getY();
}

View file

@ -0,0 +1,158 @@
package dev.zontreck.libzontreck.api;
import dev.zontreck.libzontreck.vectors.Vector3d;
import dev.zontreck.libzontreck.vectors.Vector3i;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.phys.Vec3;
public interface Vector3<T> extends Cloneable, Comparable<Vector3<T>>
{
/**
* Converts the current Vector3 representation into a minecraft Vec3
* @return Minecraft equivalent Vec3
*/
Vec3 asMinecraftVector();
/**
* Converts to a vec3i position
* @return Equivalent vec3i
*/
Vec3i asVec3i();
/**
* Converts to a block position
* @return Equivalent block position
*/
BlockPos asBlockPos();
/**
* Parses a string in serialized format.
* @param vector3 Expects it in the same format returned by Vector3#toString
* @return New Vector3, or a null Vector3 initialized with zeros if invalid data
*/
static Vector3 parseString(String vector3){
throw new UnsupportedOperationException("This method is not implemented by this implementation");
}
/**
* Copies the values to a new and detached instance
* @return New Vector3
*/
Vector3 Clone();
/**
* Saves the X, Y, and Z positions to a NBT tag
* @return NBT compound tag
*/
CompoundTag serialize();
/**
* Loads a Vector3 from a NBT tag
* @param tag The NBT tag to load
*/
static Vector3 deserialize(CompoundTag tag)
{
throw new UnsupportedOperationException("This method is not implemented by this implementation");
}
/**
* Compares the two vector3 instances
* @param other The position to check
* @return True if same position
*/
boolean Same(Vector3 other);
/**
* True if the current position is inside the two points
* @param point1 Lowest point
* @param point2 Hightest Point
* @return True if inside
*/
boolean Inside(Vector3 point1, Vector3 point2);
/**
* Converts, if necessary, to Vector3d
* @return A vector2d instance
*/
Vector3d asVector3d();
/**
* Converts, if necessary, to Vector3i
* @return A vector3i instance
*/
Vector3i asVector3i();
/**
* Checks if the current vector is greater than the provided one
* @param other The other vector to check
* @return True if greater
*/
boolean greater(Vector3 other);
/**
* Checks if the current vector is less than the provided one
* @param other The vector to check
* @return True if less than other
*/
boolean less(Vector3 other);
/**
* Alias for Vector3#same
* @param other Vector to check
* @return True if same position
*/
boolean equal(Vector3 other);
/**
* Adds the two vectors together
* @param other Vector to add
* @return New instance after adding the other vector
*/
Vector3 add(Vector3 other);
/**
* Subtracts the other vector from this one
* @param other Vector to subtract
* @return New instance after subtracting
*/
Vector3 subtract(Vector3 other);
/**
* Calculates the distance between the two vectors
* @param other
* @return The distance
*/
double distance(Vector3 other);
/**
* Increments the Y axis by 1
* @return New instance
*/
Vector3 moveUp();
/**
* Decrements the Y axis by 1
* @return New instance
*/
Vector3 moveDown();
/**
* Gets the X value
* @return X
*/
T getX();
/**
* Gets the Y value
* @return Y
*/
T getY();
/**
* Gets the Z value
* @return Z
*/
T getZ();
}

View file

@ -0,0 +1,22 @@
package dev.zontreck.libzontreck.blocks;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class BlockCustomVoxels extends PartialTransparentBlock
{
private VoxelShape superShape;
public BlockCustomVoxels(Properties p_54120_, VoxelShape shape) {
super(p_54120_);
this.superShape = shape;
}
@Override
public VoxelShape getShape(BlockState p_60555_, BlockGetter p_60556_, BlockPos p_60557_, CollisionContext p_60558_) {
return superShape;
}
}

View file

@ -0,0 +1,18 @@
package dev.zontreck.libzontreck.blocks;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.AbstractGlassBlock;
import net.minecraft.world.level.block.state.BlockState;
public class PartialTransparentBlock extends AbstractGlassBlock
{
public PartialTransparentBlock(Properties p_48729_) {
super(p_48729_);
}
@Override
public boolean propagatesSkylightDown(BlockState p_48740_, BlockGetter p_48741_, BlockPos p_48742_) {
return true;
}
}

View file

@ -0,0 +1,19 @@
package dev.zontreck.libzontreck.blocks;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.AbstractGlassBlock;
import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.state.BlockState;
public class PartialTransparentSlabBlock extends SlabBlock
{
public PartialTransparentSlabBlock(Properties p_48729_) {
super(p_48729_);
}
@Override
public boolean propagatesSkylightDown(BlockState p_48740_, BlockGetter p_48741_, BlockPos p_48742_) {
return true;
}
}

View file

@ -0,0 +1,100 @@
package dev.zontreck.libzontreck.blocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public abstract class RedstoneBlock extends RotatableBlock
{
public static final BooleanProperty INPUT_POWER = BooleanProperty.create("inputpower");
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
private List<Direction> sides;
protected RedstoneBlock(Properties pProperties, Direction... validSides) {
super(pProperties);
sides=List.of(validSides);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
return super.getStateForPlacement(pContext).setValue(INPUT_POWER, false).setValue(POWERED, false);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) {
super.createBlockStateDefinition(pBuilder);
pBuilder.add(INPUT_POWER, POWERED);
}
@Override
public boolean canConnectRedstone(BlockState state, BlockGetter level, BlockPos pos, @Nullable Direction direction) {
if(sides.contains(direction)) return true;
else return false;
}
private boolean redstoneIsActivated(LevelReader level, BlockPos pos)
{
ServerLevel srv = (ServerLevel)level;
if(srv.hasNeighborSignal(pos))
return true;
else return false;
}
@Override
public int getSignal(BlockState p_60483_, BlockGetter p_60484_, BlockPos p_60485_, Direction p_60486_) {
if(!sides.contains(p_60486_)) return 0;
if(p_60483_.getValue(POWERED))
return 15;
else return 0;
}
protected abstract void onRedstone(LevelReader level, BlockPos pos, boolean on);
protected abstract void onRedstoneInputChanged(LevelReader level, BlockPos pos, boolean on);
@Override
public void onNeighborChange(BlockState state, LevelReader level, BlockPos pos, BlockPos neighbor) {
boolean rs = redstoneIsActivated(level, pos);
onRedstone(level, pos, rs);
boolean inp = state.getValue(INPUT_POWER);
state.setValue(INPUT_POWER, rs);
if(inp != rs)
onRedstoneInputChanged(level, pos, rs);
}
@Override
public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos other, boolean unknown) {
boolean rs = redstoneIsActivated(level, pos);
onRedstone(level, pos, rs);
boolean inp = state.getValue(INPUT_POWER);
state.setValue(INPUT_POWER, rs);
if(inp != rs)
onRedstoneInputChanged(level, pos, rs);
}
@Override
public void onPlace(BlockState state, Level level, BlockPos pos, BlockState p_60569_, boolean p_60570_) {
boolean rs = redstoneIsActivated(level, pos);
onRedstone(level, pos, rs);
boolean inp = state.getValue(INPUT_POWER);
state.setValue(INPUT_POWER, rs);
if(inp != rs)
onRedstoneInputChanged(level, pos, rs);
}
}

View file

@ -0,0 +1,39 @@
package dev.zontreck.libzontreck.blocks;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
public class RotatableBlock extends HorizontalDirectionalBlock
{
public RotatableBlock(Properties pProperties) {
super(pProperties);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) {
super.createBlockStateDefinition(pBuilder);
pBuilder.add(FACING);
}
@Override
public BlockState rotate(BlockState p_55115_, Rotation p_55116_) {
return p_55115_.setValue(FACING, p_55116_.rotate(p_55115_.getValue(FACING)));
}
@Override
public BlockState mirror(BlockState p_55112_, Mirror p_55113_) {
return p_55112_.rotate(p_55113_.getRotation(p_55112_.getValue(FACING)));
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
return defaultBlockState().setValue(FACING, pContext.getHorizontalDirection());
}
}

View file

@ -0,0 +1,35 @@
package dev.zontreck.libzontreck.blocks;
import dev.zontreck.ariaslib.util.Maps;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import java.util.HashMap;
import java.util.Map;
public class RotatableBlockCustomVoxels extends RotatableBlock
{
private Map<Direction, VoxelShape> rotatedShapes = new HashMap<>();
public RotatableBlockCustomVoxels(Properties properties, VoxelShape north, VoxelShape south, VoxelShape east, VoxelShape west) {
super(properties);
rotatedShapes = Maps.of(new Maps.Entry<>(Direction.NORTH, north), new Maps.Entry<>(Direction.SOUTH, south), new Maps.Entry<>(Direction.WEST, west), new Maps.Entry<>(Direction.EAST, east), new Maps.Entry<>(Direction.NORTH, north), new Maps.Entry<>(Direction.DOWN, north));
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
Direction facing = state.getValue(FACING);
return rotatedShapes.get(facing);
}
@Override
public boolean propagatesSkylightDown(BlockState p_49928_, BlockGetter p_49929_, BlockPos p_49930_) {
return true;
}
}

View file

@ -10,6 +10,10 @@ public class ChatColorFactory {
public String build(){
return built;
}
/**
* Resets the color builder
*/
public void reset()
{
built="";
@ -18,6 +22,11 @@ public class ChatColorFactory {
public ColorBuilder(){}
}
private ColorBuilder instance;
/**
* Resets the chat color builder
* @return The current builder
*/
public ChatColorFactory reset()
{
instance.reset();

View file

@ -1,5 +1,6 @@
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;
@ -17,7 +18,7 @@ public class HoverTip {
*/
public static HoverEvent get(String text)
{
return new HoverEvent(Action.SHOW_TEXT, Component.literal(text));
return new HoverEvent(Action.SHOW_TEXT, ChatHelpers.macro(text));
}
/**

View file

@ -7,11 +7,10 @@ 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.Vector2f;
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;
@ -23,8 +22,6 @@ 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
@ -198,7 +195,7 @@ public class ChestGUI
{
updateUtilityButtons();
MinecraftForge.EVENT_BUS.post(new OpenGUIEvent(id, player, this));
NetworkHooks.openScreen(ServerUtilities.getPlayerByID(player.toString()), new SimpleMenuProvider(ChestGUIMenu.getServerMenu(this), Component.literal((MenuTitle != "") ? MenuTitle : "No Title")));
NetworkHooks.openScreen(ServerUtilities.getPlayerByID(player.toString()), new SimpleMenuProvider(ChestGUIMenu.getServerMenu(this), ChatHelpers.macro((MenuTitle != "") ? MenuTitle : "No Title")));
}
}
@ -231,7 +228,7 @@ public class ChestGUI
return this.id.equals(id);
}
public void handleButtonClicked(int slot, Vector2 pos, Item item) {
public void handleButtonClicked(int slot, Vector2f pos, Item item) {
for(ChestGUIButton button : buttons)
{
if(button.getSlotNum() == slot)

View file

@ -3,10 +3,8 @@ 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;
@ -144,7 +142,7 @@ public class ChestGUIButton
*/
public boolean matchesSlot(Vector2i slot)
{
return position.same(slot);
return position.Same(slot);
}
/**

View file

@ -0,0 +1,39 @@
package dev.zontreck.libzontreck.config;
import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.config.sections.DatabaseSection;
import dev.zontreck.libzontreck.util.SNbtIo;
import net.minecraft.nbt.CompoundTag;
import java.nio.file.Path;
public class ServerConfig
{
public static final Path BASE = LibZontreck.BASE_CONFIG.resolve("server.snbt");
public static DatabaseSection database;
public static void init()
{
if(BASE.toFile().exists())
{
var config = SNbtIo.loadSnbt(BASE);
database = DatabaseSection.deserialize(config.getCompound(DatabaseSection.TAG_NAME));
commit();
} else {
database = new DatabaseSection();
commit();
}
}
public static void commit()
{
CompoundTag tag = new CompoundTag();
tag.put(DatabaseSection.TAG_NAME, database.serialize());
SNbtIo.writeSnbt(BASE, tag);
}
}

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