37 Commits

Author SHA1 Message Date
Oliver
5f5d5302cc fancynpcs: Remove newline in VERSION file 2025-12-05 18:57:22 +01:00
Oliver
dc80615146 Add support for 1.21.11-rc2 2025-12-05 18:51:27 +01:00
Oliver
7fb487a344 Add support for 1.21.11-pre5 2025-12-04 14:32:32 +01:00
Oliver
e837ad89d3 fancydialogs: Update changelog path in snapshot deployment config 2025-12-03 16:58:10 +01:00
Oliver
47bb6f7a10 ci: Use FancyVerteiler (#170)
* ci: Use FancyVerteiler for FD snapshot

* Update configs

* Revert some stuff

* Use FancyVerteiler for all plugins

* Fixes

* Fix

* Delete deployment tool
2025-12-03 16:11:23 +01:00
Oliver
54572f1736 fancynpcs, fancyholograms, fancydialogs: Add support for 1.21.11-pre4 2025-12-01 20:55:39 +01:00
Oliver
fb79b5eaed fancynpcs, fancyholograms, fancydialogs: Update FancyAnalytics 2025-11-27 14:45:47 +01:00
Oliver
ef5109444e fancyholograms, fancydialogs: Use 1.21.11-pre3 2025-11-26 20:11:24 +01:00
Oliver
878fee61e7 fancynpcs: Use 1.21.11-pre3 2025-11-26 19:59:06 +01:00
Oliver
c7fb3b0b92 packets, fancynpcs: Update to 1.21.11-pre3 2025-11-25 18:35:43 +01:00
Oliver
9aecf99744 fancynpcs: Update version to 2.8.1 2025-11-25 18:05:01 +01:00
Oliver
1bdf350594 fancyvisuals: Update README.md 2025-11-25 18:00:45 +01:00
Oliver
b285b8f364 docs: Add built in placeholders of FancyCore 2025-11-25 14:33:37 +01:00
Oliver
9cba1bfb31 docs: Update event and punishment service references; add Placeholders API documentation 2025-11-25 13:48:12 +01:00
Oliver
0336844633 docs: Add blog post "introducing hytale plugins" 2025-11-24 18:15:01 +01:00
Oliver
62f387e6b9 docs: Update getting started page for FancyCore 2025-11-24 18:15:01 +01:00
Oliver
4ce6acf325 docs: Add punishment API and some disclaimers for FancyCore 2025-11-24 18:15:01 +01:00
Oliver
1bc13362c1 docs: Add chat and server commands for FancyCore 2025-11-24 18:15:01 +01:00
Oliver
e1c57f8e1c docs: Add economy related commands for FancyCore 2025-11-24 18:15:01 +01:00
Oliver
bcd526db5b docs: Add player related commands for FancyCore 2025-11-24 18:15:01 +01:00
Oliver
a22db1cbb1 docs: Add docs about event system in FancyCore 2025-11-24 18:15:01 +01:00
Oliver
18518f9c19 docs: Add some command documentation for FancyCore 2025-11-24 18:15:01 +01:00
Oliver
30898973c3 docs: Add docs for FancyCore 2025-11-24 18:15:01 +01:00
Oliver
217c4c36cc docs: Add banner and logo of FancyCore 2025-11-24 18:15:01 +01:00
Oliver
6d130bd93e docs: Add dialog examples by reunionsmp 2025-11-24 16:41:53 +01:00
Oliver
22f5ccca29 fancydialogs: Fixed player getting kicked when no button or action is defined
Updated version to 1.0.1
2025-11-23 11:36:50 +01:00
Oliver
1422d42322 docs: More docs for FancyDialogs 2025-11-23 11:12:12 +01:00
Oliver
474a1c3e54 fancydialogs: Update version to 1.0.0 2025-11-23 11:06:17 +01:00
Oliver
169ec91269 docs: Polish docs for FancyDialogs 2025-11-23 11:05:15 +01:00
Oliver
d6dc456f2a fancynpcs: Wrap packets in Npc#update method in bundle packet (1.12.9+) 2025-11-21 21:10:48 +01:00
Oliver
da7bc075aa Update to 1.21.11-pre2 2025-11-21 20:56:00 +01:00
Oliver
00be6cc835 fancyholograms: Update version to 2.8.0.160 2025-11-21 15:02:23 +01:00
Alex
1919b3da4d Added argument validation in SetLineCMD to prevent index errors (#155) 2025-11-21 15:00:55 +01:00
橙汁喵
529821ced6 fancyholograms: reload cannot load hologram (#152) 2025-11-21 15:00:26 +01:00
Oliver
0a6aa9da80 fancynpcs: Try to fix npcs disappearing 2025-11-21 14:34:07 +01:00
Oliver
d7c6f1bc81 fancynpcs, fancyholograms: Drop support for 1.19.4 2025-11-21 14:02:01 +01:00
Oliver
a35c2ac786 Update to 1.21.11-pre1 2025-11-21 13:52:51 +01:00
160 changed files with 1807 additions and 3584 deletions

View File

@@ -2,8 +2,9 @@ name: Deploy FancyDialogs (release)
on:
workflow_dispatch:
jobs:
deploy-plugin:
deploy:
runs-on: ubuntu-latest
steps:
@@ -27,25 +28,20 @@ jobs:
- name: Modify gradlew permissions
run: chmod +x ./gradlew
- name: Build deployment tool
run: ./gradlew :tools:deployment:shadowJar
- name: Build FancyDialogs for Modrinth
- name: Build
env:
RELEASE_CHANNEL: 'release'
RELEASE_PLATFORM: 'modrinth'
run: ./gradlew :plugins:fancydialogs:shadowJar
- name: Deploy to Modrinth
env:
MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run:
cd tools/deployment/build/libs &&
java -jar deployment.jar modrinth ../../../../plugins/fancydialogs/release_deployment_config.json true
- name: Deploy
uses: fancyinnovations/fancyverteiler@main
with:
config_path: "/plugins/fancydialogs/release_deployment_config.json"
modrinth_api_key: ${{ secrets.MODRINTH_API_KEY }}
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
- name: Publish to reposilite (releases)
run: ./gradlew :plugins:fancydialogs:fd-api:publishAllPublicationsToFancyinnovationsReleasesRepository
# - name: Publish to reposilite (releases)
# run: ./gradlew :plugins:fancydialogs:fd-api:publishAllPublicationsToFancyinnovationsReleasesRepository
- name: Publish to reposilite (snapshots)
run: ./gradlew :plugins:fancydialogs:fd-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository
# - name: Publish to reposilite (snapshots)
# run: ./gradlew :plugins:fancydialogs:fd-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository

View File

@@ -2,8 +2,9 @@ name: Deploy FancyHolograms v2 (release)
on:
workflow_dispatch:
jobs:
deploy-plugin:
deploy:
runs-on: ubuntu-latest
steps:
@@ -27,25 +28,20 @@ jobs:
- name: Modify gradlew permissions
run: chmod +x ./gradlew
- name: Build deployment tool
run: ./gradlew :tools:deployment:shadowJar
- name: Build FancyHolograms v2 for Modrinth
- name: Build
env:
RELEASE_CHANNEL: 'release'
RELEASE_PLATFORM: 'modrinth'
run: ./gradlew :plugins:fancyholograms-v2:shadowJar
- name: Deploy to Modrinth
env:
MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run:
cd tools/deployment/build/libs &&
java -jar deployment.jar modrinth ../../../../plugins/fancyholograms-v2/release_deployment_config.json true
- name: Deploy
uses: fancyinnovations/fancyverteiler@main
with:
config_path: "/plugins/fancyholograms-v2/release_deployment_config.json"
modrinth_api_key: ${{ secrets.MODRINTH_API_KEY }}
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
- name: Publish to reposilite (releases)
run: ./gradlew :plugins:fancyholograms-v2:api:publishAllPublicationsToFancyinnovationsReleasesRepository
# - name: Publish to reposilite (releases)
# run: ./gradlew :plugins:fancyholograms-v2:api:publishAllPublicationsToFancyinnovationsReleasesRepository
- name: Publish to reposilite (snapshots)
run: ./gradlew :plugins:fancyholograms-v2:api:publishAllPublicationsToFancyinnovationsSnapshotsRepository
# - name: Publish to reposilite (snapshots)
# run: ./gradlew :plugins:fancyholograms-v2:api:publishAllPublicationsToFancyinnovationsSnapshotsRepository

View File

@@ -2,8 +2,9 @@ name: Deploy FancyHolograms (release)
on:
workflow_dispatch:
jobs:
deploy-plugin:
deploy:
runs-on: ubuntu-latest
steps:
@@ -27,25 +28,20 @@ jobs:
- name: Modify gradlew permissions
run: chmod +x ./gradlew
- name: Build deployment tool
run: ./gradlew :tools:deployment:shadowJar
- name: Build FancyHolograms for Modrinth
- name: Build
env:
RELEASE_CHANNEL: 'release'
RELEASE_PLATFORM: 'modrinth'
run: ./gradlew :plugins:fancyholograms:shadowJar
- name: Deploy to Modrinth
env:
MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run:
cd tools/deployment/build/libs &&
java -jar deployment.jar modrinth ../../../../plugins/fancyholograms/release_deployment_config.json true
- name: Deploy
uses: fancyinnovations/fancyverteiler@main
with:
config_path: "/plugins/fancyholograms/release_deployment_config.json"
modrinth_api_key: ${{ secrets.MODRINTH_API_KEY }}
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
- name: Publish to reposilite (releases)
run: ./gradlew :plugins:fancyholograms:fh-api:publishAllPublicationsToFancyinnovationsReleasesRepository
# - name: Publish to reposilite (releases)
# run: ./gradlew :plugins:fancyholograms:fh-api:publishAllPublicationsToFancyinnovationsReleasesRepository
- name: Publish to reposilite (snapshots)
run: ./gradlew :plugins:fancyholograms:fh-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository
# - name: Publish to reposilite (snapshots)
# run: ./gradlew :plugins:fancyholograms:fh-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository

View File

@@ -2,8 +2,9 @@ name: Deploy FancyNpcs (release)
on:
workflow_dispatch:
jobs:
deploy-plugin:
deploy:
runs-on: ubuntu-latest
steps:
@@ -27,25 +28,20 @@ jobs:
- name: Modify gradlew permissions
run: chmod +x ./gradlew
- name: Build deployment tool
run: ./gradlew :tools:deployment:shadowJar
- name: Build FancyNpcs for Modrinth
- name: Build
env:
RELEASE_CHANNEL: 'release'
RELEASE_PLATFORM: 'modrinth'
run: ./gradlew :plugins:fancynpcs:shadowJar
- name: Deploy to Modrinth
env:
MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run:
cd tools/deployment/build/libs &&
java -jar deployment.jar modrinth ../../../../plugins/fancynpcs/release_deployment_config.json true
- name: Deploy
uses: fancyinnovations/fancyverteiler@main
with:
config_path: "/plugins/fancynpcs/release_deployment_config.json"
modrinth_api_key: ${{ secrets.MODRINTH_API_KEY }}
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
- name: Publish to reposilite (releases)
run: ./gradlew :plugins:fancynpcs:fn-api:publishAllPublicationsToFancyinnovationsReleasesRepository
# - name: Publish to reposilite (releases)
# run: ./gradlew :plugins:fancynpcs:fn-api:publishAllPublicationsToFancyinnovationsReleasesRepository
- name: Publish to reposilite (snapshots)
run: ./gradlew :plugins:fancynpcs:fn-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository
# - name: Publish to reposilite (snapshots)
# run: ./gradlew :plugins:fancynpcs:fn-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository

View File

@@ -2,8 +2,9 @@ name: Deploy FancyDialogs (snapshot)
on:
workflow_dispatch:
jobs:
deploy-fancydialogs:
deploy:
runs-on: ubuntu-latest
steps:
@@ -27,22 +28,17 @@ jobs:
- name: Modify gradlew permissions
run: chmod +x ./gradlew
- name: Build deployment tool
run: ./gradlew :tools:deployment:shadowJar
- name: Build FancyDialogs for Modrinth
- name: Build
env:
RELEASE_CHANNEL: 'snapshot'
RELEASE_PLATFORM: 'modrinth'
run: ./gradlew :plugins:fancydialogs:shadowJar
- name: Deploy to Modrinth
env:
MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run:
cd tools/deployment/build/libs &&
java -jar deployment.jar modrinth ../../../../plugins/fancydialogs/snapshot_deployment_config.json true
- name: Deploy
uses: fancyinnovations/fancyverteiler@main
with:
config_path: "/plugins/fancydialogs/snapshot_deployment_config.json"
modrinth_api_key: ${{ secrets.MODRINTH_API_KEY }}
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
- name: Publish to reposilite (snapshots)
run: ./gradlew :plugins:fancydialogs:fd-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository
# - name: Publish to reposilite (snapshots)
# run: ./gradlew :plugins:fancydialogs:fd-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository

View File

@@ -2,8 +2,9 @@ name: Deploy FancyHolograms v2 (snapshot)
on:
workflow_dispatch:
jobs:
deploy-fancyholograms:
deploy:
runs-on: ubuntu-latest
steps:
@@ -27,22 +28,17 @@ jobs:
- name: Modify gradlew permissions
run: chmod +x ./gradlew
- name: Build deployment tool
run: ./gradlew :tools:deployment:shadowJar
- name: Build FancyHolograms v2 for Modrinth
- name: Build
env:
RELEASE_CHANNEL: 'snapshot'
RELEASE_PLATFORM: 'modrinth'
run: ./gradlew :plugins:fancyholograms-v2:shadowJar
- name: Deploy to Modrinth
env:
MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run:
cd tools/deployment/build/libs &&
java -jar deployment.jar modrinth ../../../../plugins/fancyholograms-v2/snapshot_deployment_config.json true
- name: Deploy
uses: fancyinnovations/fancyverteiler@main
with:
config_path: "/plugins/fancyholograms-v2/snapshot_deployment_config.json"
modrinth_api_key: ${{ secrets.MODRINTH_API_KEY }}
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
- name: Publish to reposilite (snapshots)
run: ./gradlew :plugins:fancyholograms-v2:api:publishAllPublicationsToFancyinnovationsSnapshotsRepository
# - name: Publish to reposilite (snapshots)
# run: ./gradlew :plugins:fancyholograms-v2:api:publishAllPublicationsToFancyinnovationsSnapshotsRepository

View File

@@ -2,8 +2,9 @@ name: Deploy FancyHolograms (snapshot)
on:
workflow_dispatch:
jobs:
deploy-plugin:
deploy:
runs-on: ubuntu-latest
steps:
@@ -27,22 +28,17 @@ jobs:
- name: Modify gradlew permissions
run: chmod +x ./gradlew
- name: Build deployment tool
run: ./gradlew :tools:deployment:shadowJar
- name: Build FancyHolograms for Modrinth
- name: Build
env:
RELEASE_CHANNEL: 'snapshot'
RELEASE_PLATFORM: 'modrinth'
run: ./gradlew :plugins:fancyholograms:shadowJar
- name: Deploy to Modrinth
env:
MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run:
cd tools/deployment/build/libs &&
java -jar deployment.jar modrinth ../../../../plugins/fancyholograms/snapshot_deployment_config.json true
- name: Deploy
uses: fancyinnovations/fancyverteiler@main
with:
config_path: "/plugins/fancyholograms/snapshot_deployment_config.json"
modrinth_api_key: ${{ secrets.MODRINTH_API_KEY }}
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
- name: Publish to reposilite (snapshots)
run: ./gradlew :plugins:fancyholograms:fh-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository
# - name: Publish to reposilite (snapshots)
# run: ./gradlew :plugins:fancyholograms:fh-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository

View File

@@ -2,8 +2,9 @@ name: Deploy FancyNpcs (snapshot)
on:
workflow_dispatch:
jobs:
deploy-plugin:
deploy:
runs-on: ubuntu-latest
steps:
@@ -27,36 +28,17 @@ jobs:
- name: Modify gradlew permissions
run: chmod +x ./gradlew
- name: Build deployment tool
run: ./gradlew :tools:deployment:shadowJar
- name: Build FancyNpcs for Modrinth
- name: Build
env:
RELEASE_CHANNEL: 'snapshot'
RELEASE_PLATFORM: 'modrinth'
run: ./gradlew :plugins:fancynpcs:shadowJar
- name: Deploy to Modrinth
env:
MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run:
cd tools/deployment/build/libs &&
java -jar deployment.jar modrinth ../../../../plugins/fancynpcs/snapshot_deployment_config.json true
- name: Deploy
uses: fancyinnovations/fancyverteiler@main
with:
config_path: "/plugins/fancynpcs/snapshot_deployment_config.json"
modrinth_api_key: ${{ secrets.MODRINTH_API_KEY }}
discord_webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
# - name: Build FancyNpcs for Hangar
# env:
# RELEASE_CHANNEL: 'snapshot'
# RELEASE_PLATFORM: 'hangar'
# run: ./gradlew :plugins:fancynpcs:shadowJar
#
# - name: Deploy to Hangar
# env:
# HANGAR_API_KEY: "${{ secrets.HANGAR_API_KEY }}"
# DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
# run:
# cd tools/deployment/build/libs &&
# java -jar deployment.jar hangar ../../../../plugins/fancynpcs/snapshot_deployment_config.json true
- name: Publish to reposilite (snapshots)
run: ./gradlew :plugins:fancynpcs:fn-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository
# - name: Publish to reposilite (snapshots)
# run: ./gradlew :plugins:fancynpcs:fn-api:publishAllPublicationsToFancyinnovationsSnapshotsRepository

View File

@@ -35,7 +35,6 @@ This is a [monorepo](docs/src/development-guidelines/monorepo.md) for all plugin
- Packets: packet handling library (also called FancySitula)
**Tools:**
- Deployment: deploy plugins to platforms like modrinth
- Quick E2E: generate a quick end-to-end environment for testing
## Usage

View File

@@ -15,12 +15,5 @@ allprojects {
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://repo.fancyinnovations.com/releases")
maven(url = "https://jitpack.io")
maven("https://maven-prs.papermc.io/Paper/pr13194") {
name = "Maven for PR #13194" // https://github.com/PaperMC/Paper/pull/13194
mavenContent {
includeModule("io.papermc.paper", "dev-bundle")
includeModule("io.papermc.paper", "paper-api")
}
}
}
}

View File

@@ -0,0 +1,93 @@
---
authors:
- name: Oliver Schlüter
email: oliver@fancyinnovations.com
link: https://github.com/OliverSchlueter
avatar: https://avatars.githubusercontent.com/u/79666085?v=4
date: 2025-11-24
title: "Introducing Hytale Plugins"
description: "The first Hytale plugin by FancyInnovations will be: FancyCore, a powerful plugin that provides a wide range of features and tools for Hytale server owners."
---
![](../static/blogs/introducing-hytale-plugins/hytale-plugins.png)
[Hytale](https://hytale.com/) is finally heading into early access, and I couldnt be more excited. With that, Im thrilled to announce that **FancyInnovations will be creating server-side plugins for the Hytale ecosystem**.
The moment I read the [“Hytale is saved!”](https://hytale.com/news/2025/11/hytale-is-saved) announcement, my brain immediately jumped into brainstorming mode.
After digging through the currently available information about Hytale modding, one thing became very clear:
**Hytale needs a plugin that provides a strong set of essential features — a foundation others can build on.**
And thats exactly what Im creating.
## Introducing FancyCore
With FancyCore I want to create a platform where gamemode specific plugins can be built on. It will cover many features you probably would expect from a core plugin.
Lets look at some features:
- Teleportation (teleport, teleport request, teleport all, spawn, warps, player homes, …)
- World (create, teleport, change day time, weather, spawn protection, …)
- Inventory (kits, virtual backpacks, …)
- Economy (balance, pay, sell items, shops, …)
- Chat (chat format, player-to-player messages, nicknames, help, rules, broadcast, mute chat, clear chat, chat rooms, …)
- Moderation (report, warn, kick, mute, ban, chat / command history, vanish, sudo, …)
- Permissions (groups, permissions, …)
- Server (list online players, uptime, tps, mspt, cpu usage, ram usage, disk usage, …)
- Player (gamemode, playtime, fly, heal, feed, god, ping, …)
- Easy to use API
Notable API features:
- Permissions API
- Economy API
- Placeholder API
Other features for the future:
- Discord integration
- Built-in WebUI
This is a long list of features and not all will be available on day 1.
As I am writing this blog post, there is no public Hytale API documentation, so all I can do at the moment is write all the business logic and implement the actual commands and other Hytale specific features as soon as the API documentation is available.
For now, it will be a big all-in-one plugin, in the future I might create separate plugins for each category, but that's not final yet.
**FancyCore will be a Hytale only plugin**, I dont plan to create a Minecraft plugin out of this at the moment.
For now the plan is to get FancyCore working for Hytale as soon as possible while, but while keeping a good quality.
The plugin will be free and open-source, just like all Minecraft plugins. You can already take a look at the new mono-repo for Hytale plugins [here](https://github.com/FancyInnovations/HytalePlugins).
Some parts that dont require the Hytale server dependency are already being worked on.
Feel free to take a look and contribute to it if you want.
Parts of the documentation is also already written (mostly the commands). You can take a look at it here.
From what Ive seen, you wont be able to upload Hytale plugins to Modrinth (just speculations).
The only popular platform that supports distribution of Hytale plugins is Curseforge.
I'm currently not sure if I want to distribute FancyCore there.
In the meanwhile Ive been programming a little download service myself to distribute Hytale plugins, so they will for sure be available on the fancyinnovations.com website.
I know the community is currently working on alternative platforms as well, so we will see how that develops.
## FancyAnalytics
Alongside FancyCore, Ill also be releasing FancyAnalytics for Hytale — a toolset for gathering analytics from your Hytale server or plugins.
It will include:
* A Hytale plugin for collecting metrics such as online players, TPS, entity counts, CPU usage, and more
* An SDK for plugin developers to track usage metrics, including support for custom data points
This gives developers powerful insight into how their plugins are used — and helps server owners better understand performance.
## Conclusion
If youre as excited as I am about Hytale — and FancyCore — then join our Discord community!
Assign yourself the “FancyCore” role to get all the latest updates.
I'm currently working on it daily and will share progress updates there.
If you have any suggestions or feature requests for FancyCore, feel free to share them in the `#core-discussion` channel or DM me directly (`real_oliver`).
Theres also a dedicated channel for general Hytale news.
(The release date for early access will be announced this week!)
*Oliver*

View File

@@ -0,0 +1,2 @@
icon: code
order: 7

View File

@@ -0,0 +1,30 @@
---
icon: dot
order: 9
---
# Events API
FancyCore has its own event system that allows you to listen to various events that happen in the FancyCore system.
## Registering an event listener
Example for registering a listener for the `PlayerReportedEvent`:
```java
EventService eventService = EventService.get();
eventService.registerListener(PlayerReportedEvent.class, (event) -> {
System.out.println("PlayerReportedEvent fired with report id: " + event.getReport().id());
});
```
## Available events
### Player events
| Event | Description |
|-----------------------|-------------------------------------------------------------------------------|
| `PlayerModifiedEvent` | Event fired when a player's data is modified (through FancyPlayer's setters). |
| `PlayerReportedEvent` | Fired when a player is reported. |
| `PlayerPunishedEvent` | Fired when a player receives a punishment (warning, kick, mute or ban). |

View File

@@ -0,0 +1,51 @@
---
icon: dot
order: 10
---
# Getting started
## Include the API in your project
To include the FancyCore API in your project, you need to add the following dependency to your `build.gradle.kts` or `pom.xml` file.
**Gradle:**
```kotlin
repositories {
maven("https://repo.fancyinnovations.com/releases")
}
```
```kotlin
dependencies {
compileOnly("com.fancyinnovations:FancyCore:VERSION")
}
```
**Maven:**
```xml
<repository>
<id>fancyinnovations-releases</id>
<name>FancyInnovations Repository</name>
<url>https://repo.fancyinnovations.com/releases</url>
</repository>
```
```xml
<dependency>
<groupId>com.fancyinnovations</groupId>
<artifactId>FancyCore</artifactId>
<version>VERSION</version>
<scope>provided</scope>
</dependency>
```
Replace `VERSION` with the version of the API you want to use. You can find the latest version on the download pages or in the GitHub releases.
## JavaDocs and help
You can find the JavaDocs for the FancyDialogs API [here](https://repo.fancyinnovations.com/javadoc/releases/com/fancyinnovations/FancyCore/latest).
Join the [FancyInnovations Discord](https://discord.gg/ZUgYCEJUEx) for help and support. There is a dedicated channel for help about the api (`#core-api`).
```

View File

@@ -0,0 +1,48 @@
---
icon: dot
order: 7
---
# Placeholder API
FancyCore includes a Placeholders API that allows you to create and manage custom placeholders for use in various plugins.
## Parse placeholders
To parse placeholders in a string, use the `PlaceholderService`'s `parse` method. Here's an example:
```java
PlaceholderService placeholderService = PlaceholderService.get();
String parsedString = placeholderService.parse(player, "Hello, {player_name}! Your rank is {player_rank}.");
```
## Creating a custom placeholder
To create a custom placeholder, implement the `PlaceholderProvider` interface and register it with the `PlaceholderService`. Here's an example of creating a simple placeholder that returns a player's rank:
```java
public class PlayerRankPlaceholder implements PlaceholderProvider {
@Override
public String getName() {
return "Player Rank Placeholder";
}
@Override
public String getIdentifier() {
return "player_rank";
}
@Override
public String parse(FancyPlayer player, String input) {
return player.getRank().getName();
}
}
```
You can then register your placeholder provider with the `PlaceholderService`:
```java
PlaceholderService placeholderService = PlaceholderService.get();
placeholderService.registerPlaceholderProvider(new PlayerRankPlaceholder());
```

View File

@@ -0,0 +1,38 @@
---
icon: dot
order: 8
---
# Punishment API
FancyCore provides a comprehensive Punishment API that allows you to manage player punishments such as warnings, kicks, mutes, and bans.
## Using the Punishment Service
With the Punishment Service, you can easily issue various types of punishments to players. Below are examples of how to use the Punishment Service:
```java
PunishmentService punishmentService = PunishmentService.get();
punishmentService.warnPlayer(player, staff, "reason", duration);
punishmentService.mutePlayer(player, staff, "reason"); // Permanent mute
punishmentService.mutePlayer(player, staff, "reason", 1000*60*60*4); // Temporary mute (4 hours)
punishmentService.kickPlayer(player, staff, "reason");
punishmentService.banPlayer(player, staff, "reason", duration); // Permanent ban
punishmentService.banPlayer(player, staff, "reason", 1000*60*60*24); // Temporary ban (1 day)
```
You can also retrieve existing punishments for a player:
```java
List<Punishment> punishments = punishmentService.getPunishmentsForPlayer(player);
```
Player reports are also managed through the Punishment Service:
```java
punishmentService.reportPlayer(player, staff, "reason");
```

View File

@@ -0,0 +1,2 @@
icon: log
order: 5

View File

@@ -0,0 +1,9 @@
---
icon: dot
title: V0
order: 1
---
# FancyCore v0.x.x

View File

@@ -0,0 +1,99 @@
---
icon: dot
title: Chat
---
![](../../static/commands.png)
# Commands for the chat system
!!!warning
The command list is not complete and not all commands are properly documented yet.
Some commands might not be implemented yet.
!!!
## Messages
### Message
Description: Sends a private message to the specified player.<br/>
Syntax: ``/Message (player) (message)`` or ``/Msg (player) (message)``<br/>
Permission: ``fancycore.commands.message``
### Reply
Description: Replies to the last private message received.<br/>
Syntax: ``/Reply (message)`` or ``/R (message)``<br/>
Permission: ``fancycore.commands.reply``
### Message Spy
Description: Toggles message spying to see private messages between other players.<br/>
Syntax: ``/MessageSpy`` or ``/MsgSpy``<br/>
Permission: ``fancycore.commands.messagespy``
### ToggleMessages
Description: Toggles the ability to receive private messages.<br/>
Syntax: ``/ToggleMessages`` or ``/ToggleMsg``<br/>
Permission: ``fancycore.commands.togglemessages``
## Chat rooms
### CreateChatRoom
Description: Creates a new chat room with the specified name.<br/>
Syntax: ``/CreateChatRoom (name)`` or ``/CCR (name)``<br/>
Permission: ``fancycore.commands.createchatroom``
### JoinChatRoom
Description: Joins the specified chat room.<br/>
Syntax: ``/JoinChatRoom (name)`` or ``/JCR (name)``<br/>
Permission: ``fancycore.commands.joinchatroom``
### LeaveChatRoom
Description: Leaves the current chat room.<br/>
Syntax: ``/LeaveChatRoom`` or ``/LCR``<br/>
Permission: ``fancycore.commands.leavechatroom``
### ListChatRooms
Description: Lists all available chat rooms on the server.<br/>
Syntax: ``/ListChatRooms`` or ``/LCRs``<br/>
Permission: ``fancycore.commands.listchatrooms``
### ChatRoomInfo
Description: Displays information about the specified chat room.<br/>
Syntax: ``/ChatRoomInfo (name)`` or ``/CRInfo (name)``<br/>
Permission: ``fancycore.commands.chatroominfo``
## Chat Management
### ClearChat
Description: Clears the chat for all players on the server.<br/>
Syntax: ``/ClearChat`` or ``/CC``<br/>
Permission: ``fancycore.commands.clearchat``
### SlowChat
Description: Sets a slow mode for chat, limiting how often players can send messages.<br/>
Syntax: ``/SlowChat (seconds)`` or ``/Slow (seconds)``<br/>
Permission: ``fancycore.commands.slowchat``
### MuteChat
Description: Mutes the chat for all players, preventing them from sending messages.<br/>
Syntax: ``/MuteChat``<br/>
Permission: ``fancycore.commands.mutechat``
### UnmuteChat
Description: Unmutes the chat, allowing players to send messages again.<br/>
Syntax: ``/UnmuteChat``<br/>
Permission: ``fancycore.commands.unmutechat``

View File

@@ -0,0 +1,2 @@
order: 9
icon: command-palette

View File

@@ -0,0 +1,49 @@
---
icon: dot
title: Economy
---
![](../../static/commands.png)
# Commands for the economy system
!!!warning
The command list is not complete and not all commands are properly documented yet.
Some commands might not be implemented yet.
!!!
### Balance
Description: Displays the balance of the specified player or your own balance if no player is specified.<br/>
Syntax: ``/Balance [player]``<br/>
Permission: ``fancycore.commands.balance``
### Pay
Description: Transfers a specified amount of money from your balance to another player's balance.<br/>
Syntax: ``/Pay (player) (amount)``<br/>
Permission: ``fancycore.commands.pay``
### Set Balance
Description: Sets the balance of the specified player to a given amount.<br/>
Syntax: ``/SetBalance (player) (amount)``<br/>
Permission: ``fancycore.commands.setbalance``
### Add Balance
Description: Adds a specified amount of money to the balance of the specified player.<br/>
Syntax: ``/AddBalance (player) (amount)``<br/>
Permission: ``fancycore.commands.addbalance``
### Remove Balance
Description: Removes a specified amount of money from the balance of the specified player.<br/>
Syntax: ``/RemoveBalance (player) (amount)``<br/>
Permission: ``fancycore.commands.removebalance``
### Top Balances
Description: Displays a leaderboard of players with the highest balances.<br/>
Syntax: ``/TopBalances [page]``<br/>
Permission: ``fancycore.commands.topbalances``

View File

@@ -0,0 +1,79 @@
---
icon: dot
title: Inventory
---
![](../../static/commands.png)
# Commands for the inventory system
!!!warning
The command list is not complete and not all commands are properly documented yet.
Some commands might not be implemented yet.
!!!
## Kits
### Create Kit
Description: Creates a new kit with the specified name. It contains all items in your inventory<br/>
Syntax: ``/CreateKit (name)``<br/>
Permission: ``fancycore.commands.createkit``
### Delete Kit
Description: Deletes the specified kit.<br/>
Syntax: ``/DeleteKit (name)``<br/>
Permission: ``fancycore.commands.deletekit``
### Give Kit
Description: Gives the specified kit to the targeted player(s).<br/>
Syntax: ``/Kit (name) [player]``<br/>
Permission: ``fancycore.commands.kit.(name)``
### List Kits
Description: Lists all available kits.<br/>
Syntax: ``/Kits`` or ``/ListKits``<br/>
Permission: ``fancycore.commands.listkits``
## Backpacks
### Open Backpack
Description: Opens the specified backpack of the targeted player.<br/>
Syntax: ``/Backpack (name) [player]``<br/>
Permission: ``fancycore.commands.backpack``
### Create Backpack
Description: Creates a new backpack with the specified name and size.<br/>
Syntax: ``/CreateBackpack (name) (size)``<br/>
Permission: ``fancycore.commands.createbackpack``
### Delete Backpack
Description: Deletes the specified backpack.<br/>
Syntax: ``/DeleteBackpack (name)``<br/>
Permission: ``fancycore.commands.deletebackpack``
### List Backpacks
Description: Lists all available backpacks.<br/>
Syntax: ``/Backpacks`` or ``/ListBackpacks``<br/>
Permission: ``fancycore.commands.listbackpacks``
## Utilities
### Clear Inventory
Description: Clears the inventory of the targeted player(s).<br/>
Syntax: ``/ClearInventory [player]``<br/>
Permission: ``fancycore.commands.clearinventory``
### Open another Player's Inventory
Description: Opens the inventory of the targeted player.<br/>
Syntax: ``/OpenInventory (player)`` or ``/Invsee (player)``<br/>
Permission: ``fancycore.commands.openinventory``

View File

@@ -0,0 +1,110 @@
---
icon: dot
title: Moderation
---
![](../../static/commands.png)
# Commands for the moderation system
!!!warning
The command list is not complete and not all commands are properly documented yet.
Some commands might not be implemented yet.
!!!
## Report
### Report a Player
Description: Reports a player for misconduct.<br/>
Syntax: ``/Report (player) [reason]``<br/>
Permission: ``fancycore.commands.report``
### List Reports
Description: Lists all active player reports.<br/>
Syntax: ``/Reports list``<br/>
Permission: ``fancycore.commands.reports.list``
### View Report Details
Description: Views details of a specific report.<br/>
Syntax: ``/Reports view (reportID)``<br/>
Permission: ``fancycore.commands.reports.view``
### Close Report
Description: Closes a specific report.<br/>
Syntax: ``/Reports close (reportID)``<br/>
Permission: ``fancycore.commands.reports.close``
## Warn
### Warn a Player
Description: Issues a warning to a player.<br/>
Syntax: ``/Warn (player) [reason]``<br/>
Permission: ``fancycore.commands.warn``
## Mute
### Mute a Player
Description: Mutes a player, preventing them from sending chat messages.<br/>
Syntax: ``/Mute (player) [reason]``<br/>
Permission: ``fancycore.commands.mute``
### Temporary Mute a Player
Description: Temporarily mutes a player for a specified duration.<br/>
Syntax: ``/Tempmute (player) (duration) [reason]``<br/>
Permission: ``fancycore.commands.tempmute``
### Unmute a Player
Description: Unmutes a player.<br/>
Syntax: ``/Unmute (player)``<br/>
Permission: ``fancycore.commands.unmute``
## Kick
### Kick a Player
Description: Kicks a player from the server.<br/>
Syntax: ``/Kick (player) [reason]``<br/>
Permission: ``fancycore.commands.kick``
## Ban
### Ban a Player
Description: Bans a player from the server.<br/>
Syntax: ``/Ban (player) [reason]``<br/>
Permission: ``fancycore.commands.ban``
### Temporary Ban a Player
Description: Temporarily bans a player from the server for a specified duration.<br/>
Syntax: ``/Tempban (player) (duration) [reason]``<br/>
Permission: ``fancycore.commands.tempban``
### Unban a Player
Description: Unbans a player from the server.<br/>
Syntax: ``/Unban (player)``<br/>
Permission: ``fancycore.commands.unban``
## Logs
### View Moderation Logs
Description: Views the moderation logs.<br/>
Syntax: ``/Modlogs [player]``<br/>
Permission: ``fancycore.commands.modlogs``
### View Chat Logs
Description: Views the chat logs.<br/>
Syntax: ``/Chatlogs [player] [--withCommands]``<br/>
Permission: ``fancycore.commands.chatlogs``

View File

@@ -0,0 +1,107 @@
---
icon: dot
title: Permissions
---
![](../../static/commands.png)
# Commands for the permissions system
!!!warning
The command list is not complete and not all commands are properly documented yet.
Some commands might not be implemented yet.
!!!
## Groups
### Create Group
Description: Creates a new group with the specified name.<br/>
Syntax: ``/Groups create (name)``<br/>
Permission: ``fancycore.commands.creategroup``
### Delete Group
Description: Deletes the specified permission group.<br/>
Syntax: ``/Groups delete (name)``<br/>
Permission: ``fancycore.commands.deletegroup``
### List Groups
Description: Lists all available permission groups.<br/>
Syntax: ``/Groups list``<br/>
Permission: ``fancycore.commands.listgroups``
### Info Group
Description: Displays information about the specified permission group.<br/>
Syntax: ``/Groups info (name)``<br/>
Permission: ``fancycore.commands.infogroup``
### Set Parent Group
Description: Sets the parent group for the specified permission group.<br/>
Syntax: ``/Groups parent (group) set (parent)``<br/>
Permission: ``fancycore.commands.setparentgroup``
### Add Permission to Group
Description: Adds the specified permission to the permission group.<br/>
Syntax: ``/Groups permission (group) add (permission)``<br/>
Permission: ``fancycore.commands.addpermtogroup``
### Remove Permission from Group
Description: Removes the specified permission from the permission group.<br/>
Syntax: ``/Groups permission (group) remove (permission)``<br/>
Permission: ``fancycore.commands.removepermfromgroup``
### Set Prefix for Group
Description: Sets the prefix for the specified permission group.<br/>
Syntax: ``/Groups prefix (group) set (prefix)``<br/>
Permission: ``fancycore.commands.setprefixforgroup``
### Set Suffix for Group
Description: Sets the suffix for the specified permission group.<br/>
Syntax: ``/Groups suffix (group) set (suffix)``<br/>
Permission: ``fancycore.commands.setsuffixforgroup``
### Add Player to Group
Description: Adds the specified player to the permission group.<br/>
Syntax: ``/Groups player (player) add (group)``<br/>
Permission: ``fancycore.commands.addplayertogroup``
### Remove Player from Group
Description: Removes the specified player from the permission group.<br/>
Syntax: ``/Groups player (player) remove (group)``<br/>
Permission: ``fancycore.commands.removeplayerfromgroup``
## Player Permissions
### Add Permission to Player
Description: Adds the specified permission to the targeted player.<br/>
Syntax: ``/Permission add (permission) [player]``<br/>
Permission: ``fancycore.commands.addpermtoplayer``
### Remove Permission from Player
Description: Removes the specified permission from the targeted player.<br/>
Syntax: ``/Permission remove (permission) [player]``<br/>
Permission: ``fancycore.commands.removepermfromplayer``
### Check Player Permission
Description: Checks if the targeted player has the specified permission.<br/>
Syntax: ``/Permission check (permission) [player]``<br/>
Permission: ``fancycore.commands.checkplayerperm``
### List Player Permissions
Description: Lists all permissions of the targeted player.<br/>
Syntax: ``/Permission list [player]``<br/>
Permission: ``fancycore.commands.listplayerperms``

View File

@@ -0,0 +1,91 @@
---
icon: dot
title: Player
---
![](../../static/commands.png)
# Commands for the player system
!!!warning
The command list is not complete and not all commands are properly documented yet.
Some commands might not be implemented yet.
!!!
### Gamemode
Description: Changes the gamemode of a player.<br/>
Syntax: ``/Gamemode (gamemode) [player]`` or ``/GM (gamemode)``<br/>
Permission: ``fancycore.commands.gamemode``
### Gamemode explorer
Description: Changes the gamemode of a player to explorer mode.<br/>
Syntax: ``/gme [player]``<br/>
Permission: ``fancycore.commands.gamemode``
### Gamemode creative
Description: Changes the gamemode of a player to creative mode.<br/>
Syntax: ``/gmc [player]``<br/>
Permission: ``fancycore.commands.gamemode``
### Fly
Description: Toggles fly mode for a player.<br/>
Syntax: ``/Fly [player]``<br/>
Permission: ``fancycore.commands.fly``
### Speed
Description: Sets the walk and fly speed of a player.<br/>
Syntax: ``/Speed (speed) [player]``<br/>
Permission: ``fancycore.commands.speed``
### Heal
Description: Heals a player to full health.<br/>
Syntax: ``/Heal [player]``<br/>
Permission: ``fancycore.commands.heal``
### Feed
Description: Feeds a player to full hunger.<br/>
Syntax: ``/Feed [player]``<br/>
Permission: ``fancycore.commands.feed``
### God mode
Description: Toggles god mode for a player.<br/>
Syntax: ``/God [player]``<br/>
Permission: ``fancycore.commands.god``
### Vanish
Description: Toggles vanish mode for a player.<br/>
Syntax: ``/Vanish [player]``<br/>
Permission: ``fancycore.commands.vanish``
### Playtime
Description: Displays the playtime of a player.<br/>
Syntax: ``/Playtime [player]``<br/>
Permission: ``fancycore.commands.playtime``
### Seen
Description: Displays the last seen time of a player.<br/>
Syntax: ``/Seen (player)``<br/>
Permission: ``fancycore.commands.seen``
### Near
Description: Lists players near the command sender within a specified radius.<br/>
Syntax: ``/Near [radius]``<br/>
Permission: ``fancycore.commands.near``
### Ping
Description: Displays the ping of a player.<br/>
Syntax: ``/Ping [player]``<br/>
Permission: ``fancycore.commands.ping``

View File

@@ -0,0 +1,91 @@
---
icon: dot
title: Server
---
![](../../static/commands.png)
# Commands for the server system
!!!warning
The command list is not complete and not all commands are properly documented yet.
Some commands might not be implemented yet.
!!!
## Server control
### Restart
Description: Restarts the server after a specified delay.<br/>
Syntax: ``/Restart (delay)``<br/>
Permission: ``fancycore.commands.restart``
### Stop
Description: Stops the server after a specified delay.<br/>
Syntax: ``/Stop (delay)``<br/>
Permission: ``fancycore.commands.stop``
### Save All
Description: Forces the server to save all data immediately.<br/>
Syntax: ``/SaveAll``<br/>
Permission: ``fancycore.commands.saveall``
## Server health
### Health
Description: Displays an overview of the server's health status.<br/>
Syntax: ``/Health``<br/>
Permission: ``fancycore.commands.health``
### TPS
Description: Displays the current ticks per second (TPS) of the server.<br/>
Syntax: ``/Health tps``<br/>
Permission: ``fancycore.commands.health.tps``
### Memory
Description: Displays the current memory usage of the server.<br/>
Syntax: ``/Health memory``<br/>
Permission: ``fancycore.commands.health.memory``
### Uptime
Description: Displays the server's uptime since the last restart.<br/>
Syntax: ``/Health uptime``<br/>
Permission: ``fancycore.commands.health.uptime``
### CPU Usage
Description: Displays the current CPU usage of the server.<br/>
Syntax: ``/Health cpu``<br/>
Permission: ``fancycore.commands.health.cpu``
### Entity Count
Description: Displays the total number of entities currently loaded on the server.<br/>
Syntax: ``/Health entities``<br/>
Permission: ``fancycore.commands.health.entities``
### Player Count
Description: Displays the current number of players online on the server.<br/>
Syntax: ``/Health players``<br/>
Permission: ``fancycore.commands.health.players``
## Players
### List online players
Description: Lists all players currently online on the server.<br/>
Syntax: ``/OnlinePlayers``<br/>
Permission: ``fancycore.commands.onlineplayers``
### List all registered players
Description: Lists all players registered on the server.<br/>
Syntax: ``/RegisteredPlayers``<br/>
Permission: ``fancycore.commands.registeredplayers``

View File

@@ -0,0 +1,129 @@
---
icon: dot
title: Teleportation
---
![](../../static/commands.png)
# Commands for the teleportation system
!!!warning
The command list is not complete and not all commands are properly documented yet.
Some commands might not be implemented yet.
!!!
## Player Teleportation
### Teleport to another player
Description: Teleports you or the specified player to another player's location.<br/>
Syntax: ``/TP (target player) [destination player]`` or ``/Teleport (target player) [destination player]``<br/>
Permission: ``fancycore.commands.tp``
### Teleport another player to you
Description: Teleports the specified player to your location.<br/>
Syntax: ``/TPHere (player)`` or ``/TeleportHere (player)``<br/>
Permission: ``fancycore.commands.tphere``
### Teleport all players to you
Description: Teleports all players on the server to your location.<br/>
Syntax: ``/TPAll`` or ``/TeleportAll``<br/>
Permission: ``fancycore.commands.tpall``
### Teleport to specific coordinates
Description: Teleports you to the specified coordinates<br/>
Syntax: ``/TPPos (x) (y) (z) [world]`` or ``/TeleportPos (x) (y) (z) [world]``<br/>
Permission: ``fancycore.commands.tppos``
### Request teleport to another player
Description: Sends a teleport request to another player to teleport to their location.<br/>
Syntax: ``/TPR (player)``, ``/TPRequest (player)`` or ``/TeleportRequest (player)``<br/>
Permission: ``fancycore.commands.tprequest``
### Accept teleport request
Description: Accepts a pending teleport request from another player.<br/>
Syntax: ``/TPA [player]``, ``/TPAccept [player]`` or ``/TeleportAccept [player]``<br/>
Permission: ``fancycore.commands.tpaccept``
### Deny teleport request
Description: Denies a pending teleport request from another player.<br/>
Syntax: ``/TPD [player]``, ``/TPDeny [player]`` or ``/TeleportDeny [player]``<br/>
Permission: ``fancycore.commands.tpdeny``
### Teleport back to previous location
Description: Teleports you back to your previous location before your last teleport.<br/>
Syntax: ``/Back``<br/>
Permission: ``fancycore.commands.back``
### Teleport to last death location
Description: Teleports you to the location where you last died.<br/>
Syntax: ``/DeathBack``, ``/DeathTP`` or ``/DeathTeleport``<br/>
Permission: ``fancycore.commands.deathback``
## Spawn
### Set spawn point
Description: Sets the server's spawn point to your current location.<br/>
Syntax: ``/SetSpawn``<br/>
Permission: ``fancycore.commands.setspawn``
### Teleport to spawn point
Description: Teleports you to the server's spawn point.<br/>
Syntax: ``/Spawn``<br/>
Permission: ``fancycore.commands.spawn``
## Warps
### Create a warp point
Description: Creates a warp point at your current location with the specified name.<br/>
Syntax: ``/CreateWarp (name)``<br/>
Permission: ``fancycore.commands.createwarp``
### Delete a warp point
Description: Deletes the warp point with the specified name.<br/>
Syntax: ``/DeleteWarp (name)``<br/>
Permission: ``fancycore.commands.deletewarp``
### Teleport to a warp point
Description: Teleports you to the warp point with the specified name.<br/>
Syntax: ``/Warp (name)``<br/>
Permission: ``fancycore.commands.warp.(name)``
### List all warp points
Description: Lists all available warp points on the server.<br/>
Syntax: ``/ListWarps``, ``/Warps``<br/>
Permission: ``fancycore.commands.listwarps``
## Homes
### Set home point
Description: Sets your home point to your current location.<br/>
Syntax: ``/SetHome (name)``<br/>
Permission: ``fancycore.commands.sethome``
### Delete home point
Description: Deletes your home point with the specified name.<br/>
Syntax: ``/DeleteHome (name)``<br/>
Permission: ``fancycore.commands.deletehome``
### Teleport to home point
Description: Teleports you to your home point with the specified name or the first home if no name is provided.<br/>
Syntax: ``/Home [name]``<br/>
Permission: ``fancycore.commands.home``

View File

@@ -0,0 +1,59 @@
---
icon: dot
title: World
---
![](../../static/commands.png)
# Commands for the world management system
!!!warning
The command list is not complete and not all commands are properly documented yet.
Some commands might not be implemented yet.
!!!
## World Management
### Create a new world
Description: Creates a new world with the specified name.<br/>
Syntax: ``/CreateWorld (world name) [type]``<br/>
Permission: ``fancycore.commands.createworld``
### Copy an existing world
Description: Creates a copy of the specified world.<br/>
Syntax: ``/CopyWorld (source world name) (new world name)``<br/>
Permission: ``fancycore.commands.copyworld``
### Delete an existing world
Description: Deletes the specified world from the server.<br/>
Syntax: ``/DeleteWorld (world name)``<br/>
Permission: ``fancycore.commands.deleteworld``
### List all worlds
Description: Lists all available worlds on the server.<br/>
Syntax: ``/ListWorlds``, ``/Worlds``<br/>
Permission: ``fancycore.commands.listworlds``
### Teleport to a world
Description: Teleports you to the specified world.<br/>
Syntax: ``/World (world name)``<br/>
Permission: ``fancycore.commands.world``
## Utility Commands
### Set weather
Description: Sets the weather in the current world.<br/>
Syntax: ``/SetWeather (sun|rain)``<br/>
Permission: ``fancycore.commands.setweather``
### Set time
Description: Sets the time of day in the current world.<br/>
Syntax: ``/SetTime (time)``<br/>
Permission: ``fancycore.commands.settime``

View File

@@ -0,0 +1,33 @@
---
title: FancyCore [Hytale]
icon: package
order: 90
---
#
![](../static/logos-and-banners/fancycore-banner.png)
!!!
Essential features every Hytale server needs. From permission management over world management to economy and more.
!!!
## Features
With FancyCore, you get a wide variety of features that are essential for running a Hytale server:
- **Permissions**: permission management system to control access to commands and features
- **Economy**: robust economy system with virtual currency, shops, and trading
- **Chat**: advanced chat management with channels, formatting, nicknames and msgs
- **Moderation**: tools for server admins including bans, kicks, warnings, and logs
- **World**: create and manage multiple worlds with different settings and environments
- **Inventory**: manage player inventories, kits and player backpacks
- **Teleportation**: spawn point, warps, player homes, and teleport requests
- **Player**: utility commands such as fly, speed, gamemode, heal, and more
- **Server**: view server stats and manage plugins
- **API**: comprehensive API for developers to extend and customize FancyCore
- **And much more!**
FancyCore is designed to provide all the essential features needed to build a successful Hytale server, while being easy to use and highly customizable.
We are trying to get a usable version out as soon as possible.
If you don't want to miss any updates, join our [Discord](https://discord.gg/ZUgYCEJUEx) and assign yourself the "FancyCore" role.

10
docs/src/fancycore/faq.md Normal file
View File

@@ -0,0 +1,10 @@
---
order: 6
icon: book
---
# FAQ
### Is FancyCore available for Minecraft?
No, FancyCore is a Hytale only plugin. There are no plans to make it available for Minecraft at this time.

View File

@@ -0,0 +1,29 @@
---
order: 10
icon: info
---
# Getting started
!!!danger
Be aware that this plugin is only made for Hytale servers. Only the latest version of Hytale is supported.
!!!
## Installation
To install FancyCore, you need to download the latest version from one of the following sources:
[!button size="s" icon="download" iconAlign="left" text="SOON" target="blank"]()
!!!warning
It's not yet decided on which platforms FancyCore will be available.
You keep an eye on the discord server for updates: [FancyInnovations Discord](https://discord.gg/ZUgYCEJUEx)
!!!
After downloading the plugin, you can install it by placing the downloaded file in the `plugins` folder of your server.
Restart your server and you are ready to go!
To check if the plugin is installed correctly, you can use the command `/fancycore version`. If the plugin is installed correctly, it will show you the version of the plugin.
You can now learn more about the commands in the `Commands` section of the documentation or learn how to configure the plugin in the `Tutorials` section.
The API documentation can be found in the `Api` section.

View File

@@ -0,0 +1,14 @@
---
order: 8
icon: paste
---
# Placeholders
FancyCore provides a set of built-in placeholders that can be used in various parts of the system.
You can use placeholders in almost any text field within FancyCore.
FancyCore also offers an API for creating and parse placeholders programmatically, read more about it in the [API documentation](../api/placeholders.md).
## Built-in Placeholders
* [Player related placeholders](player.md)

View File

@@ -0,0 +1,19 @@
---
icon: dot
title: Player
---
# Player placeholders
| Name | Identfier | Description | Examples outputs |
|------------------------------------------|---------------------------|------------------------------------------------------------|----------------------------------------|
| Player balance (formatted) | `player_balance` | Displays the player's current balance (formatted) | "0", "123", "123.45", "13,123.97" |
| Player balance (raw) | `player_balance_raw` | Displays the player's current balance (raw) | "0", "123", "123.45", "13123.9417" |
| Player chat color (hex) | `player_chat_color` | Displays the player's chat color in hex format | "#FF0000", "#00FF00", "#0000FF" |
| Player first time joined | `player_first_joined` | Displays the date and time the player first joined | "2023-01-01 12:00:00" |
| Player first time joined (raw timestamp) | `player_first_joined_raw` | Displays the raw timestamp of when the player first joined | "1672531200" |
| Player name | `player_name` | Displays the player's name | "Simon", "OliverHD" |
| Player nickname | `player_nickname` | Displays the player's nickname | "Oli" |
| Player play time (formatted) | `player_play_time` | Displays the player's total play time (formatted) | "0s", "5m 30s", "2h 15m" |
| Player play time (ms) | `player_play_time_ms` | Displays the player's total play time in milliseconds | "0", "330000", "8100000" |
| Player UUID | `player_uuid` | Displays the player's UUID | "9b605d04-5a59-4353-bba3-2ddf570eb38a" |

View File

@@ -0,0 +1,2 @@
order: 7
icon: mortar-board

View File

@@ -0,0 +1,23 @@
---
icon: dot
order: 2
---
![](../../static/changelog_v1_x_x.png)
#
## v1.0.1 [!badge variant="info" text="2025-11-23"] [!badge variant="danger" text="Hotfix"]
- Fixed player kick issue when no button or action is defined. ([#147](https://github.com/FancyInnovations/FancyPlugins/issues/147))
## v1.0.0 [!badge variant="info" text="2025-11-23"]
- Create dialogs using the [JSON schema](https://docs.fancyinnovations.com/fancydialogs/tutorials/json-schema/)
- PlaceholderAPI and MiniMessage support in dialog texts
- Execute actions when dialog buttons are clicked
- Open a dialog when the user joins the server for the first time (see `welcome_dialog_id` in the config)
- A quick actions dialog which can be opened with the `/qa` or `/quickactions` commands
- FancyNpcs ingegration to open dialogs when interacting with NPCs (see [docs](https://docs.fancyinnovations.com/fancydialogs/tutorials/open-dialog-npc-action/))
- API for other plugins to open dialogs (see [docs](https://docs.fancyinnovations.com/fancydialogs/api/getting-started/))

View File

@@ -71,7 +71,7 @@ Unregisters a dialog by its ID.
## Joined Players Cache
## Clear joined players cache
### Clear joined players cache
Clears the cache of players who have joined a dialog.

View File

@@ -1,5 +1,5 @@
---
title: FancyDialogs [WIP]
title: FancyDialogs
icon: browser
order: 90
---
@@ -21,11 +21,6 @@ FancyDialogs uses the new dialog feature, Minecraft introduced in **1.21.6** and
The plugin will only for **Paper** servers on **1.21.6** or newer!
!!!
!!!warning
FancyDialogs is still in development and some features are not yet implemented.
See the [TODO](#todo) section for more information.
!!!
**Core advantages of FancyDialogs:**
- Simple custom dialog creation (in JSON format or in code)
- A lot of different dialog components (text, buttons, input fields, etc.)
@@ -52,17 +47,3 @@ Common use cases are:
- Confirmation dialogs for critical actions
- Shop UIs (replacing inventories UIs)
- Dialogs for quests
## TODO
- [X] Create dialogs in JSON format
- [X] Create dialogs in code
- [X] Customize dialog content and buttons
- [X] Open dialogs for players (via commands or code)
- [X] Welcome dialog for new players
- [X] FancyNpcs integration (open_dialog action)
- [X] Confirmation and notice dialogs (API)
- [x] Add button action system
- [ ] Add support for the quick action hotkey
- [ ] Add tutorial features
- [ ] Add input controls

View File

@@ -9,6 +9,10 @@ The following examples show how to use FancyDialogs in different ways. They are
Almost all examples are made by the community. If you have a nice example that you want to share, feel free come to our discord server and show it to us.
![Provided by reunionsmp.com](../static/fancydialogs/examples/reunionsmp-1.png)
![Provided by reunionsmp.com](../static/fancydialogs/examples/reunionsmp-2.png)
![Provided by oliver](../static/fancydialogs/examples/oliver-welcome_to_fd.png)
![Provided by oliver](../static/fancydialogs/examples/oliver-welcome.png)

View File

@@ -1,6 +1,6 @@
---
icon: dot
order: 9
order: 7
---
# Open dialog npc action

View File

@@ -0,0 +1,13 @@
---
icon: dot
order: 8
---
# Quick actions
FancyDialogs doesn't support the quick-actions hotkey, but has a command to open a quick action dialog.
To open the quick actions dialog, use the command: `/qa` or `/quickactions`.
You can customize the quick actions dialog in the `plugins/FancyDialogs/data/dialogs/quick_actions.json` file.
If you want to disable the quick actions dialog, you can set the `disable-quick-actions-dialog` option to true in the `plugins/FancyDialogs/featureFlags.yml` file.

View File

@@ -0,0 +1,16 @@
---
icon: dot
order: 9
---
# Welcome dialog
You can configure a dialog to be shown to players when they join the server for the first time.
A default welcome dialog is included with FancyDialogs, but you can customize it or create your own welcome dialog.
You can find the default welcome dialog in the `plugins/FancyDialogs/data/dialogs/welcome.json` file.
Feel free to edit this file to customize the welcome dialog to your liking.
If you want to use another dialog as the welcome dialog, you can change the id in the `plugins/FancyDialogs/config.yml` file by changing the `welcome_dialog_id` option to the ID of your desired dialog.
To completely disable the welcome dialog, you can set the `disable-welcome-dialog` to true in the `plugins/FancyDialogs/featureFlags.yml` file.

View File

@@ -7,6 +7,17 @@ order: 2
#
## v2.8.1 [!badge variant="info" text="2025-11-25"]
- Removed support for 1.19.4
- Fixed npcs randomly disappearing
- Fixed skin mirroring for 1.21.9
- Added inverted permission check for `need_permission` action (use prefix `!` to invert)
- Added `/npc rotate <npc> <yaw> <pitch>` command to set NPC orientation
- Added `swing_arm_on_update` config option
- Added `use-minecraft-usercache` feature flag
## v2.8.0 [!badge variant="info" text="2025-10-10"]
- Added support for 1.21.9 and 1.21.10

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@@ -14,7 +14,7 @@ repositories {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.19.4-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.20-R0.1-SNAPSHOT")
compileOnly("de.oliver.FancyAnalytics:logger:0.0.8")
compileOnly("org.jetbrains:annotations:26.0.2")

View File

@@ -6,7 +6,7 @@ plugins {
paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION
dependencies {
paperweight.paperDevBundle("25w46a-R0.1-SNAPSHOT")
paperweight.paperDevBundle("1.21.11-rc2-R0.1-SNAPSHOT")
compileOnly(project(":libraries:packets:packets-api"))
testImplementation(project(":libraries:packets"))

View File

@@ -7,7 +7,7 @@ import java.util.List;
public enum ServerVersion {
v1_21_11("1.21.11", 774),
v1_21_11("1.21.11 Release Candidate 2", 774),
v1_21_10("1.21.10", 773),
v1_21_9("1.21.9", 773),
v1_21_8("1.21.8", 772),

View File

@@ -0,0 +1 @@
- Fixed player kick issue when no button or action is defined. ([#147](https://github.com/FancyInnovations/FancyPlugins/issues/147))

View File

@@ -1 +1 @@
0.0.32
1.0.1.37

View File

@@ -45,8 +45,8 @@ dependencies {
implementation(project(":libraries:common"))
implementation(project(":libraries:jdb"))
implementation(project(":libraries:config"))
implementation("de.oliver.FancyAnalytics:java-sdk:0.0.4")
implementation("de.oliver.FancyAnalytics:mc-api:0.1.11")
implementation("de.oliver.FancyAnalytics:java-sdk:0.0.5")
implementation("de.oliver.FancyAnalytics:mc-api:0.1.12")
implementation("de.oliver.FancyAnalytics:logger:0.0.8")
compileOnly(project(":plugins:fancynpcs:fn-api"))
@@ -85,14 +85,14 @@ paper {
tasks {
runServer {
minecraftVersion("1.21.10")
minecraftVersion("1.21.11-rc2")
downloadPlugins {
modrinth("fancynpcs", "2.8.0")
// modrinth("fancynpcs", "2.8.0")
// hangar("ViaVersion", "5.3.2")
// hangar("ViaBackwards", "5.3.2")
// modrinth("multiverse-core", "4.3.11")
hangar("PlaceholderAPI", "2.11.6")
// hangar("PlaceholderAPI", "2.11.6")
}
}

View File

@@ -1,9 +1,10 @@
{
"project_name": "FancyDialogs",
"plugin_jar_path": "/plugins/fancydialogs/build/libs/FancyDialogs-%VERSION%.jar",
"changelog_path": "/plugins/fancydialogs/CHANGELOG.md",
"version_path": "/plugins/fancydialogs/VERSION",
"modrinth": {
"project_id": "Sx6YwpnK",
"plugin_jar_path": "../../../../plugins/fancydialogs/build/libs/FancyDialogs-%VERSION%.jar",
"changelog_path": "../../../../plugins/fancydialogs/CHANGELOG.md",
"version_path": "../../../../plugins/fancydialogs/VERSION",
"supported_versions": [
"1.21.6",
"1.21.7",
@@ -12,10 +13,11 @@
"1.21.10",
"1.21.11"
],
"channel": "RELEASE",
"channel": "release",
"loaders": [
"paper",
"folia"
],
"featured": false
"featured": true
}
}

View File

@@ -1,20 +1,23 @@
{
"project_name": "FancyDialogs",
"plugin_jar_path": "/plugins/fancydialogs/build/libs/FancyDialogs-%VERSION%.jar",
"changelog_path": "/plugins/fancydialogs/CHANGELOG-SNAPSHOT.md",
"version_path": "/plugins/fancydialogs/VERSION",
"modrinth": {
"project_id": "Sx6YwpnK",
"plugin_jar_path": "../../../../plugins/fancydialogs/build/libs/FancyDialogs-%VERSION%.jar",
"changelog_path": "../../../../plugins/fancydialogs/CHANGELOG-SNAPSHOT.md",
"version_path": "../../../../plugins/fancydialogs/VERSION",
"supported_versions": [
"1.21.6",
"1.21.7",
"1.21.8",
"1.21.9",
"1.21.10"
"1.21.10",
"1.21.11-rc2"
],
"channel": "BETA",
"channel": "beta",
"loaders": [
"paper",
"folia"
],
"featured": false
}
}

View File

@@ -10,6 +10,7 @@ import com.fancyinnovations.fancydialogs.api.data.inputs.DialogInput;
import com.fancyinnovations.fancydialogs.api.data.inputs.DialogSelect;
import com.fancyinnovations.fancydialogs.api.data.inputs.DialogTextField;
import de.oliver.fancysitula.api.dialogs.FS_CommonDialogData;
import de.oliver.fancysitula.api.dialogs.FS_Dialog;
import de.oliver.fancysitula.api.dialogs.FS_DialogAction;
import de.oliver.fancysitula.api.dialogs.actions.FS_CommonButtonData;
import de.oliver.fancysitula.api.dialogs.actions.FS_DialogActionButton;
@@ -18,6 +19,7 @@ import de.oliver.fancysitula.api.dialogs.body.FS_DialogBody;
import de.oliver.fancysitula.api.dialogs.body.FS_DialogTextBody;
import de.oliver.fancysitula.api.dialogs.inputs.*;
import de.oliver.fancysitula.api.dialogs.types.FS_MultiActionDialog;
import de.oliver.fancysitula.api.dialogs.types.FS_NoticeDialog;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.factories.FancySitula;
import org.bukkit.entity.Player;
@@ -35,7 +37,7 @@ public class DialogImpl extends Dialog {
super(id, data);
}
private FS_MultiActionDialog buildForPlayer(Player player) {
private FS_Dialog buildForPlayer(Player player) {
List<FS_DialogBody> body = new ArrayList<>();
for (DialogBodyData bodyData : data.body()) {
FS_DialogTextBody fsDialogTextBody = new FS_DialogTextBody(
@@ -109,6 +111,30 @@ public class DialogImpl extends Dialog {
actions.add(fsDialogActionButton);
}
if (actions.isEmpty()) {
return new FS_NoticeDialog(
new FS_CommonDialogData(
ChatColorHandler.translate(data.title(), player, ParserTypes.placeholder()),
ChatColorHandler.translate(data.title(), player, ParserTypes.placeholder()),
data.canCloseWithEscape(),
false,
FS_DialogAction.CLOSE,
body,
inputs
),
new FS_DialogActionButton(
new FS_CommonButtonData(
"Close",
null,
150 // default button width
),
new FS_DialogCustomAction(
"fancydialogs_dialog_action--none",
Map.of())
)
);
}
return new FS_MultiActionDialog(
new FS_CommonDialogData(
ChatColorHandler.translate(data.title(), player, ParserTypes.placeholder()),
@@ -118,53 +144,6 @@ public class DialogImpl extends Dialog {
FS_DialogAction.CLOSE,
body,
inputs
// List.of(
// new FS_DialogInput(
// "input1",
// new FS_DialogTextInput(
// 200,
// "Enter something",
// true,
// "default text",
// 100,
// null
// )
// ),
// new FS_DialogInput(
// "input2",
// new FS_DialogBooleanInput(
// "input2",
// false,
// "true",
// "false"
// )
// ),
// new FS_DialogInput(
// "input3",
// new FS_DialogNumberRangeInput(
// 200,
// "Number Input",
// "options.generic_value",
// 0,
// 100,
// 50.f,
// 1.0f
// )
// ),
// new FS_DialogInput(
// "input4",
// new FS_DialogSingleOptionInput(
// 200,
// List.of(
// new FS_DialogSingleOptionInput.Entry("option1", "Option 1", true),
// new FS_DialogSingleOptionInput.Entry("option2", "Option 2", false),
// new FS_DialogSingleOptionInput.Entry("option3", "Option 3", false)
// ),
// "Select an option",
// true
// )
// )
// )
),
actions, // actions
null,

View File

@@ -46,6 +46,10 @@ public class CustomClickActionPacketListener {
String dialogId = packet.getPayload().get("dialog_id");
String buttonId = packet.getPayload().get("button_id");
if (dialogId == null || buttonId == null) {
return; // Missing necessary information
}
new DialogButtonClickedEvent(event.player(), dialogId, buttonId, packet.getPayload()).callEvent();
if (dialogId.startsWith("confirmation_dialog_")) {

View File

@@ -36,7 +36,7 @@ With this plugin you can create holograms with customizable properties like:
## Installation
Paper **1.19.4** - **1.21.8** with **Java 21** (or higher) is required. Plugin should also work on **Paper** forks.
Paper **1.20** - **1.21.8** with **Java 21** (or higher) is required. Plugin should also work on **Paper** forks.
**Spigot** is **not** supported.

View File

@@ -1 +1 @@
2.8.0.158
2.8.0.165

View File

@@ -4,7 +4,7 @@ plugins {
id("com.gradleup.shadow")
}
val minecraftVersion = "1.19.4"
val minecraftVersion = "1.20"
dependencies {
compileOnly("io.papermc.paper:paper-api:$minecraftVersion-R0.1-SNAPSHOT")

View File

@@ -39,7 +39,6 @@ dependencies {
implementation(project(":plugins:fancyholograms-v2:implementation_1_20_4", configuration = "reobf"))
implementation(project(":plugins:fancyholograms-v2:implementation_1_20_2", configuration = "reobf"))
implementation(project(":plugins:fancyholograms-v2:implementation_1_20_1", configuration = "reobf"))
implementation(project(":plugins:fancyholograms-v2:implementation_1_19_4", configuration = "reobf"))
rootProject.subprojects
.filter { it.path.startsWith(":libraries:packets:implementations") }
@@ -49,8 +48,8 @@ dependencies {
implementation(project(":libraries:common"))
implementation(project(":libraries:jdb"))
implementation(project(":libraries:config"))
implementation("de.oliver.FancyAnalytics:java-sdk:0.0.4")
implementation("de.oliver.FancyAnalytics:mc-api:0.1.11")
implementation("de.oliver.FancyAnalytics:java-sdk:0.0.5")
implementation("de.oliver.FancyAnalytics:mc-api:0.1.12")
implementation("de.oliver.FancyAnalytics:logger:0.0.8")
compileOnly(project(":plugins:fancynpcs:fn-api"))
@@ -91,7 +90,7 @@ paper {
tasks {
runServer {
minecraftVersion("1.21.10")
minecraftVersion("1.21.11-rc2")
downloadPlugins {
// modrinth("fancynpcs", "2.5.2")

View File

@@ -1,33 +0,0 @@
plugins {
id("java-library")
id("io.papermc.paperweight.userdev")
}
val minecraftVersion = "1.19.4"
dependencies {
paperweight.paperDevBundle("$minecraftVersion-R0.1-SNAPSHOT")
implementation(project(":plugins:fancyholograms-v2:api"))
implementation(project(":libraries:common"))
compileOnly("com.viaversion:viaversion-api:5.2.1")
}
tasks {
named("assemble") {
dependsOn(named("reobfJar"))
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release.set(17)
}
}

View File

@@ -1,271 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
import com.mojang.math.Transformation;
import de.oliver.fancyholograms.api.data.*;
import de.oliver.fancyholograms.api.events.HologramHideEvent;
import de.oliver.fancyholograms.api.events.HologramShowEvent;
import de.oliver.fancyholograms.api.hologram.Hologram;
import de.oliver.fancylib.ReflectionUtils;
import io.papermc.paper.adventure.PaperAdventure;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData.DataItem;
import net.minecraft.network.syncher.SynchedEntityData.DataValue;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Brightness;
import net.minecraft.world.entity.Display;
import net.minecraft.world.entity.Display.TextDisplay;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import java.util.ArrayList;
import static de.oliver.fancylib.ReflectionUtils.getValue;
public final class Hologram1_19_4 extends Hologram {
@Nullable
private Display display;
public Hologram1_19_4(@NotNull final HologramData data) {
super(data);
}
@Override
public int getEntityId() {
return display.getId();
}
@Override
public @Nullable org.bukkit.entity.Display getDisplayEntity() {
return display != null ? (org.bukkit.entity.Display) display.getBukkitEntity() : null;
}
@Override
public void create() {
final var location = data.getLocation();
if (location.getWorld() == null) {
return; // no location data, cannot be created
}
ServerLevel world = ((CraftWorld) location.getWorld()).getHandle();
switch (data.getType()) {
case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world);
case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world);
case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world);
}
if (data instanceof DisplayHologramData dd) {
final var DATA_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_19_4.DATA_INTERPOLATION_DURATION_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_DURATION_ID, dd.getInterpolationDuration());
final var DATA_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_19_4.DATA_INTERPOLATION_START_DELTA_TICKS_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_START_DELTA_TICKS_ID, 0);
}
update();
}
@Override
public void delete() {
this.display = null;
}
@Override
public void update() {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to update
}
// location data
final var location = data.getLocation();
if (!location.isWorldLoaded()) {
return;
} else {
display.setPosRaw(location.x(), location.y(), location.z());
display.setYRot(location.getYaw());
display.setXRot(location.getPitch());
}
if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) {
// line width
final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_19_4.DATA_LINE_WIDTH_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH);
// background
final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_19_4.DATA_BACKGROUND_COLOR_ID.getMapping());
final var background = textData.getBackground();
if (background == null) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND);
} else if (background == Hologram.TRANSPARENT) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, 0);
} else {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, background.asARGB());
}
// text shadow
if (textData.hasTextShadow()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SHADOW));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SHADOW));
}
// text alignment
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.LEFT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_LEFT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_LEFT));
}
// see through
if (textData.isSeeThrough()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SEE_THROUGH));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SEE_THROUGH));
}
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.RIGHT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_RIGHT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT));
}
} else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) {
// item
itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack()));
} else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) {
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':'));
blockDisplay.setBlockState(block.defaultBlockState());
}
if (data instanceof DisplayHologramData displayData) {
// billboard data
display.setBillboardConstraints(switch (displayData.getBillboard()) {
case FIXED -> Display.BillboardConstraints.FIXED;
case VERTICAL -> Display.BillboardConstraints.VERTICAL;
case HORIZONTAL -> Display.BillboardConstraints.HORIZONTAL;
case CENTER -> Display.BillboardConstraints.CENTER;
});
// brightness
if (displayData.getBrightness() != null) {
display.setBrightnessOverride(new Brightness(displayData.getBrightness().getBlockLight(), displayData.getBrightness().getSkyLight()));
}
// entity scale AND MORE!
display.setTransformation(new Transformation(
displayData.getTranslation(),
new Quaternionf(),
displayData.getScale(),
new Quaternionf())
);
// entity shadow
display.setShadowRadius(displayData.getShadowRadius());
display.setShadowStrength(displayData.getShadowStrength());
// view range
display.setViewRange(displayData.getVisibilityDistance());
}
}
@Override
public boolean show(@NotNull final Player player) {
if (!new HologramShowEvent(this, player).callEvent()) {
return false;
}
if (this.display == null) {
create(); // try to create it if it doesn't exist every time
}
final var display = this.display;
if (display == null) {
return false; // could not be created, nothing to show
}
if (!data.getLocation().getWorld().getName().equals(player.getLocation().getWorld().getName())) {
return false;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
// TODO: cache player protocol version
// TODO: fix this
// final var protocolVersion = FancyHologramsPlugin.get().isUsingViaVersion() ? Via.getAPI().getPlayerVersion(player) : MINIMUM_PROTOCOL_VERSION;
// if (protocolVersion < MINIMUM_PROTOCOL_VERSION) {
// return false;
// }
serverPlayer.connection.send(new ClientboundAddEntityPacket(display));
this.viewers.add(player.getUniqueId());
refreshHologram(player);
return true;
}
@Override
public boolean hide(@NotNull final Player player) {
if (!new HologramHideEvent(this, player).callEvent()) {
return false;
}
final var display = this.display;
if (display == null) {
return false; // doesn't exist, nothing to hide
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId()));
this.viewers.remove(player.getUniqueId());
return true;
}
@Override
public void refresh(@NotNull final Player player) {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to refresh
}
if (!isViewer(player)) {
return;
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display));
if (display instanceof TextDisplay textDisplay) {
textDisplay.setText(PaperAdventure.asVanilla(getShownText(player)));
}
final var values = new ArrayList<DataValue<?>>();
//noinspection unchecked
for (final var item : ((Int2ObjectMap<DataItem<?>>) getValue(display.getEntityData(), "e")).values()) {
values.add(item.value());
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values));
}
}

View File

@@ -1,20 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
public enum MappingKeys1_19_4 {
DATA_INTERPOLATION_DURATION_ID("r"),
DATA_INTERPOLATION_START_DELTA_TICKS_ID("q"),
DATA_LINE_WIDTH_ID("aL"),
DATA_BACKGROUND_COLOR_ID("aM"),
;
private final String mapping;
MappingKeys1_19_4(String mapping) {
this.mapping = mapping;
}
public String getMapping() {
return mapping;
}
}

View File

@@ -1,11 +1,11 @@
{
"project_name": "FancyHolograms",
"plugin_jar_path": "/plugins/fancyholograms-v2/build/libs/FancyHolograms-%VERSION%.jar",
"changelog_path": "/plugins/fancyholograms-v2/CHANGELOG.md",
"version_path": "/plugins/fancyholograms-v2/VERSION",
"modrinth": {
"project_id": "5QNgOj66",
"plugin_jar_path": "../../../../plugins/fancyholograms-v2/build/libs/FancyHolograms-%VERSION%.jar",
"changelog_path": "../../../../plugins/fancyholograms-v2/CHANGELOG.md",
"version_path": "../../../../plugins/fancyholograms-v2/VERSION",
"supported_versions": [
"1.19.4",
"1.20",
"1.20.1",
"1.20.2",
@@ -26,10 +26,11 @@
"1.21.10",
"1.21.11"
],
"channel": "RELEASE",
"channel": "release",
"loaders": [
"paper",
"folia"
],
"featured": true
}
}

View File

@@ -1,11 +1,11 @@
{
"project_name": "FancyHolograms",
"plugin_jar_path": "/plugins/fancyholograms-v2/build/libs/FancyHolograms-%VERSION%.jar",
"changelog_path": "/plugins/fancyholograms-v2/CHANGELOG-SNAPSHOT.md",
"version_path": "/plugins/fancyholograms-v2/VERSION",
"modrinth": {
"project_id": "5QNgOj66",
"plugin_jar_path": "../../../../plugins/fancyholograms-v2/build/libs/FancyHolograms-%VERSION%.jar",
"changelog_path": "../../../../plugins/fancyholograms-v2/CHANGELOG-SNAPSHOT.md",
"version_path": "../../../../plugins/fancyholograms-v2/VERSION",
"supported_versions": [
"1.19.4",
"1.20",
"1.20.1",
"1.20.2",
@@ -23,12 +23,14 @@
"1.21.7",
"1.21.8",
"1.21.9",
"1.21.10"
"1.21.10",
"1.21.11-rc2"
],
"channel": "BETA",
"channel": "beta",
"loaders": [
"paper",
"folia"
],
"featured": false
}
}

View File

@@ -17,7 +17,10 @@ import de.oliver.fancyholograms.api.hologram.Hologram;
import de.oliver.fancyholograms.commands.FancyHologramsCMD;
import de.oliver.fancyholograms.commands.FancyHologramsTestCMD;
import de.oliver.fancyholograms.commands.HologramCMD;
import de.oliver.fancyholograms.hologram.version.*;
import de.oliver.fancyholograms.hologram.version.Hologram1_20_1;
import de.oliver.fancyholograms.hologram.version.Hologram1_20_2;
import de.oliver.fancyholograms.hologram.version.Hologram1_20_4;
import de.oliver.fancyholograms.hologram.version.HologramImpl;
import de.oliver.fancyholograms.listeners.*;
import de.oliver.fancyholograms.storage.FlatFileHologramStorage;
import de.oliver.fancyholograms.storage.converter.FHConversionRegistry;
@@ -109,7 +112,7 @@ public final class FancyHolograms extends JavaPlugin implements FancyHologramsPl
final var adapter = resolveHologramAdapter();
if (adapter == null) {
List<String> supportedVersions = new ArrayList<>(List.of("1.19.4", "1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4"));
List<String> supportedVersions = new ArrayList<>(List.of("1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4"));
supportedVersions.addAll(ServerVersion.getSupportedVersions());
fancyLogger.warn("""
@@ -268,7 +271,6 @@ public final class FancyHolograms extends JavaPlugin implements FancyHologramsPl
case "1.20.3", "1.20.4" -> Hologram1_20_4::new;
case "1.20.2" -> Hologram1_20_2::new;
case "1.20", "1.20.1" -> Hologram1_20_1::new;
case "1.19.4" -> Hologram1_19_4::new;
default -> null;
};
}

View File

@@ -47,7 +47,7 @@ public final class HologramManagerImpl implements HologramManager {
HologramManagerImpl(@NotNull final FancyHolograms plugin, @NotNull final Function<HologramData, Hologram> adapter) {
this.plugin = plugin;
this.adapter = adapter;
hologramLoadLogging = plugin.getHologramConfiguration().isHologramLoadLogging();
this.hologramLoadLogging = plugin.getHologramConfiguration().isHologramLoadLogging();
}
/**
@@ -102,7 +102,7 @@ public final class HologramManagerImpl implements HologramManager {
* @param hologram The hologram to remove.
*/
public void removeHologram(@NotNull final Hologram hologram) {
removeHologram(hologram.getData().getName());
this.removeHologram(hologram.getData().getName());
}
/**
@@ -122,7 +122,7 @@ public final class HologramManagerImpl implements HologramManager {
}
}
FancyHolograms.get().getHologramThread().submit(() -> plugin.getHologramStorage().delete(hologram));
FancyHolograms.get().getHologramThread().submit(() -> this.plugin.getHologramStorage().delete(hologram));
}
);
@@ -142,44 +142,48 @@ public final class HologramManagerImpl implements HologramManager {
}
public void saveHolograms() {
if (!isLoaded) {
if (!this.isLoaded) {
return;
}
plugin.getHologramStorage().saveBatch(getPersistentHolograms(), false);
this.plugin.getHologramStorage().saveBatch(this.getPersistentHolograms(), false);
}
@Override
public void loadHolograms() {
FancyHolograms.get().getHologramThread().submit(() -> {
List<Hologram> allLoaded = new ArrayList<>();
for (World world : Bukkit.getWorlds()) {
Collection<Hologram> loaded = plugin.getHologramStorage().loadAll(world.getName());
Collection<Hologram> loaded = this.plugin.getHologramStorage().loadAll(world.getName());
loaded.forEach(this::addHologram);
allLoaded.addAll(loaded);
}
isLoaded = true;
this.isLoaded = true;
FancyHolograms.get().getHologramThread().submit(() -> Bukkit.getPluginManager().callEvent(new HologramsLoadedEvent(ImmutableList.copyOf(allLoaded))));
if (hologramLoadLogging) FancyHolograms.get().getFancyLogger().info(String.format("Loaded %d holograms for all loaded worlds", allLoaded.size()));
Bukkit.getPluginManager().callEvent(new HologramsLoadedEvent(ImmutableList.copyOf(allLoaded)));
if (this.hologramLoadLogging) FancyHolograms.get().getFancyLogger().info(String.format("Loaded %d holograms for all loaded worlds", allLoaded.size()));
});
}
@Override
public boolean isLoaded() {
return isLoaded;
return this.isLoaded;
}
public void loadHolograms(String world) {
ImmutableList<Hologram> loaded = ImmutableList.copyOf(plugin.getHologramStorage().loadAll(world));
FancyHolograms.get().getHologramThread().submit(() -> {
ImmutableList<Hologram> loaded = ImmutableList.copyOf(this.plugin.getHologramStorage().loadAll(world));
loaded.forEach(this::addHologram);
isLoaded = true;
this.isLoaded = true;
Bukkit.getPluginManager().callEvent(new HologramsLoadedEvent(ImmutableList.copyOf(loaded)));
if (hologramLoadLogging) FancyHolograms.get().getFancyLogger().info(String.format("Loaded %d holograms for world %s", loaded.size(), world));
if (this.hologramLoadLogging)
FancyHolograms.get().getFancyLogger().info(String.format("Loaded %d holograms for world %s", loaded.size(), world));
});
}
/**
@@ -188,9 +192,9 @@ public final class HologramManagerImpl implements HologramManager {
* This method is intended to be called internally by the plugin.
*/
void initializeTasks() {
ScheduledExecutorService hologramThread = plugin.getHologramThread();
ScheduledExecutorService hologramThread = this.plugin.getHologramThread();
hologramThread.submit(() -> {
loadHolograms();
this.loadHolograms();
hologramThread.scheduleAtFixedRate(() -> {
for (final Hologram hologram : this.plugin.getHologramsManager().getHolograms()) {
@@ -198,7 +202,7 @@ public final class HologramManagerImpl implements HologramManager {
hologram.forceUpdateShownStateFor(player);
}
}
}, 0, plugin.getHologramConfiguration().getUpdateVisibilityInterval() * 50L, TimeUnit.MILLISECONDS);
}, 0, this.plugin.getHologramConfiguration().getUpdateVisibilityInterval() * 50L, TimeUnit.MILLISECONDS);
});
final var updateTimes = CacheBuilder.newBuilder()
@@ -208,7 +212,7 @@ public final class HologramManagerImpl implements HologramManager {
hologramThread.scheduleAtFixedRate(() -> {
final var time = System.currentTimeMillis();
for (final var hologram : getHolograms()) {
for (final var hologram : this.getHolograms()) {
HologramData data = hologram.getData();
if (data.hasChanges()) {
hologram.forceUpdate();
@@ -225,7 +229,7 @@ public final class HologramManagerImpl implements HologramManager {
hologramThread.scheduleWithFixedDelay(() -> {
final var time = System.currentTimeMillis();
for (final var hologram : getHolograms()) {
for (final var hologram : this.getHolograms()) {
if (hologram.getData() instanceof TextHologramData textData) {
final var interval = textData.getTextUpdateInterval();
if (interval < 1) {
@@ -250,8 +254,8 @@ public final class HologramManagerImpl implements HologramManager {
* Reloads holograms by clearing the existing holograms and loading them again from the plugin's configuration.
*/
public void reloadHolograms() {
unloadHolograms();
loadHolograms();
this.unloadHolograms();
this.loadHolograms();
}
public void unloadHolograms() {
@@ -278,7 +282,7 @@ public final class HologramManagerImpl implements HologramManager {
final var online = List.copyOf(Bukkit.getOnlinePlayers());
FancyHolograms.get().getHologramThread().submit(() -> {
List<Hologram> h = getPersistentHolograms().stream()
List<Hologram> h = this.getPersistentHolograms().stream()
.filter(hologram -> hologram.getData().getLocation().getWorld().getName().equals(world))
.toList();

View File

@@ -1 +1 @@
3.0.0-SNAPSHOT.11
3.0.0-SNAPSHOT.16

View File

@@ -46,8 +46,8 @@ dependencies {
implementation(project(":libraries:config"))
implementation(project(":libraries:packets"))
implementation(project(":libraries:packets:packets-api"))
implementation("de.oliver.FancyAnalytics:java-sdk:0.0.4")
implementation("de.oliver.FancyAnalytics:mc-api:0.1.11")
implementation("de.oliver.FancyAnalytics:java-sdk:0.0.5")
implementation("de.oliver.FancyAnalytics:mc-api:0.1.12")
implementation("de.oliver.FancyAnalytics:logger:0.0.8")
implementation("io.github.revxrsal:lamp.common:4.0.0-rc.12")
@@ -96,7 +96,7 @@ paper {
tasks {
runServer {
minecraftVersion("1.21.10")
minecraftVersion("1.21.11-rc2")
downloadPlugins {
modrinth("fancynpcs", "2.7.0")

View File

@@ -4,7 +4,7 @@ plugins {
id("com.gradleup.shadow")
}
val minecraftVersion = "1.19.4"
val minecraftVersion = "1.20"
dependencies {
compileOnly("io.papermc.paper:paper-api:$minecraftVersion-R0.1-SNAPSHOT")

View File

@@ -1,9 +1,10 @@
{
"project_name": "FancyHolograms",
"plugin_jar_path": "/plugins/fancyholograms/build/libs/FancyHolograms-%VERSION%.jar",
"changelog_path": "/plugins/fancyholograms/CHANGELOG.md",
"version_path": "/plugins/fancyholograms/VERSION",
"modrinth": {
"project_id": "5QNgOj66",
"plugin_jar_path": "../../../../plugins/fancyholograms/build/libs/FancyHolograms-%VERSION%.jar",
"changelog_path": "../../../../plugins/fancyholograms/CHANGELOG.md",
"version_path": "../../../../plugins/fancyholograms/VERSION",
"supported_versions": [
"1.20.5",
"1.20.6",
@@ -20,10 +21,11 @@
"1.21.10",
"1.21.11"
],
"channel": "RELEASE",
"channel": "release",
"loaders": [
"paper",
"folia"
],
"featured": true
}
}

View File

@@ -1,9 +1,10 @@
{
"project_name": "FancyHolograms",
"plugin_jar_path": "/plugins/fancyholograms/build/libs/FancyHolograms-%VERSION%.jar",
"changelog_path": "/plugins/fancyholograms/CHANGELOG-SNAPSHOT.md",
"version_path": "/plugins/fancyholograms/VERSION",
"modrinth": {
"project_id": "5QNgOj66",
"plugin_jar_path": "../../../../plugins/fancyholograms/build/libs/FancyHolograms-%VERSION%.jar",
"changelog_path": "../../../../plugins/fancyholograms/CHANGELOG-SNAPSHOT.md",
"version_path": "../../../../plugins/fancyholograms/VERSION",
"supported_versions": [
"1.20.5",
"1.20.6",
@@ -17,12 +18,14 @@
"1.21.7",
"1.21.8",
"1.21.9",
"1.21.10"
"1.21.10",
"1.21.11-rc2"
],
"channel": "ALPHA",
"channel": "alpha",
"loaders": [
"paper",
"folia"
],
"featured": false
}
}

View File

@@ -76,6 +76,11 @@ public class SetLineCMD implements Subcommand {
index--;
if (args.length < 5) {
MessageHelper.error(player, "Please provide text for the line");
return false;
}
String text = "";
for (int i = 4; i < args.length; i++) {
text += args[i] + " ";

View File

@@ -1,4 +1,5 @@
- Added support for 1.21.11
- Removed support for 1.19.4
- Fixed npcs randomly disappearing
- Fixed skin mirroring for 1.21.9
- Added inverted permission check for `need_permission` action (use prefix `!` to invert)
- Added `/npc rotate <npc> <yaw> <pitch>` command to set NPC orientation

View File

@@ -35,7 +35,7 @@ Check out **[images section](#images)** down below.
## Installation
Paper **1.19.4** - **1.21.11** with **Java 21** (or higher) is required. Plugin should also work on **Paper** forks.
Paper **1.20** - **1.21.11** with **Java 21** (or higher) is required. Plugin should also work on **Paper** forks.
**Spigot** is **not** supported.

View File

@@ -1 +1 @@
2.8.0.309
2.8.1.317

View File

@@ -43,7 +43,6 @@ dependencies {
implementation(project(":plugins:fancynpcs:implementation_1_20_2", configuration = "reobf"))
implementation(project(":plugins:fancynpcs:implementation_1_20_1", configuration = "reobf"))
implementation(project(":plugins:fancynpcs:implementation_1_20", configuration = "reobf"))
implementation(project(":plugins:fancynpcs:implementation_1_19_4", configuration = "reobf"))
rootProject.subprojects
.filter { it.path.startsWith(":libraries:packets:implementations") }
@@ -55,8 +54,8 @@ dependencies {
implementation(project(":libraries:plugin-tests"))
implementation(project(":libraries:config"))
compileOnly("org.lushplugins:ChatColorHandler:6.0.0")
implementation("de.oliver.FancyAnalytics:java-sdk:0.0.4")
implementation("de.oliver.FancyAnalytics:mc-api:0.1.11")
implementation("de.oliver.FancyAnalytics:java-sdk:0.0.5")
implementation("de.oliver.FancyAnalytics:mc-api:0.1.12")
implementation("de.oliver.FancyAnalytics:logger:0.0.8")
implementation("org.incendo:cloud-core:2.0.0")
implementation("org.incendo:cloud-paper:2.0.0-beta.13")
@@ -96,7 +95,7 @@ paper {
tasks {
runServer {
minecraftVersion("1.21.10")
minecraftVersion("1.21.11-rc2")
downloadPlugins {
// hangar("ViaVersion", "5.4.0")

View File

@@ -4,7 +4,7 @@ plugins {
id("com.gradleup.shadow")
}
val minecraftVersion = "1.19.4"
val minecraftVersion = "1.20"
dependencies {
compileOnly("io.papermc.paper:paper-api:$minecraftVersion-R0.1-SNAPSHOT")

View File

@@ -1,34 +0,0 @@
plugins {
id("java-library")
id("io.papermc.paperweight.userdev")
}
val minecraftVersion = "1.19.4"
dependencies {
paperweight.paperDevBundle("$minecraftVersion-R0.1-SNAPSHOT")
compileOnly(project(":plugins:fancynpcs:fn-api"))
compileOnly(project(":libraries:common"))
compileOnly("org.lushplugins:ChatColorHandler:5.1.6") // KEEP, newer versions require Java 21
}
tasks {
named("assemble") {
dependsOn(named("reobfJar"))
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release = 17
}
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}

View File

@@ -1,23 +0,0 @@
package de.oliver.fancynpcs.v1_19_4;
public enum MappingKeys1_19_4 {
ENTITY_TYPE__FACTORY("bA"),
SYNCHED_ENTITY_DATA__ITEMS_BY_ID("e"),
CLIENTBOUND_TELEPORT_ENTITY_PACKET__X("b"),
CLIENTBOUND_TELEPORT_ENTITY_PACKET__Y("c"),
CLIENTBOUND_TELEPORT_ENTITY_PACKET__Z("d"),
CLIENTBOUND_PLAYER_INFO_UPDATE_PACKET__ENTRIES("b"),
PANDA__DATA_ID_FLAGS("ca"),
;
private final String mapping;
MappingKeys1_19_4(String mapping) {
this.mapping = mapping;
}
public String getMapping() {
return mapping;
}
}

View File

@@ -1,391 +0,0 @@
package de.oliver.fancynpcs.v1_19_4;
import com.google.common.collect.ImmutableList;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.datafixers.util.Pair;
import de.oliver.fancylib.ReflectionUtils;
import de.oliver.fancynpcs.api.FancyNpcsPlugin;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.api.NpcData;
import de.oliver.fancynpcs.api.events.NpcSpawnEvent;
import de.oliver.fancynpcs.api.utils.NpcEquipmentSlot;
import io.papermc.paper.adventure.PaperAdventure;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.*;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
import net.minecraft.world.entity.Display;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.scores.Team;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_19_R3.util.CraftNamespacedKey;
import org.bukkit.entity.Player;
import org.lushplugins.chatcolorhandler.ModernChatColorHandler;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class Npc_1_19_4 extends Npc {
private final String localName;
private final UUID uuid;
private Entity npc;
private Display.TextDisplay sittingVehicle;
public Npc_1_19_4(NpcData data) {
super(data);
this.localName = generateLocalName();
this.uuid = UUID.randomUUID();
}
@Override
public void create() {
MinecraftServer minecraftServer = ((CraftServer) Bukkit.getServer()).getServer();
ServerLevel serverLevel = ((CraftWorld) data.getLocation().getWorld()).getHandle();
GameProfile gameProfile = new GameProfile(uuid, localName);
if (data.getType() == org.bukkit.entity.EntityType.PLAYER) {
npc = new ServerPlayer(minecraftServer, serverLevel, new GameProfile(uuid, ""));
((ServerPlayer) npc).gameProfile = gameProfile;
} else {
EntityType<?> nmsType = BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(data.getType().getKey()));
EntityType.EntityFactory factory = (EntityType.EntityFactory) ReflectionUtils.getValue(nmsType, MappingKeys1_19_4.ENTITY_TYPE__FACTORY.getMapping()); // EntityType.factory
npc = factory.create(nmsType, serverLevel);
isTeamCreated.clear();
}
}
@Override
public void spawn(Player player) {
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
if (npc == null) {
return;
}
if (!data.getLocation().getWorld().getName().equalsIgnoreCase(serverPlayer.getLevel().getWorld().getName())) {
return;
}
if (data.getSkinData() != null && data.getSkinData().hasTexture()) {
String value = data.getSkinData().getTextureValue();
String signature = data.getSkinData().getTextureSignature();
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues(
"textures",
ImmutableList.of(new Property("textures", value, signature))
);
}
NpcSpawnEvent spawnEvent = new NpcSpawnEvent(this, player);
spawnEvent.callEvent();
if (spawnEvent.isCancelled()) {
return;
}
if (npc instanceof ServerPlayer npcPlayer) {
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = EnumSet.noneOf(ClientboundPlayerInfoUpdatePacket.Action.class);
actions.add(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER);
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
if (data.isShowInTab()) {
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
}
ClientboundPlayerInfoUpdatePacket playerInfoPacket = new ClientboundPlayerInfoUpdatePacket(actions, List.of(npcPlayer));
if (data.isMirrorSkin()) {
handleMirroredSkin(playerInfoPacket, serverPlayer);
}
serverPlayer.connection.send(playerInfoPacket);
if (data.isSpawnEntity()) {
npc.setPos(data.getLocation().x(), data.getLocation().y(), data.getLocation().z());
ClientboundAddPlayerPacket spawnPlayerPacket = new ClientboundAddPlayerPacket(npcPlayer);
serverPlayer.connection.send(spawnPlayerPacket);
}
}
ClientboundAddEntityPacket addEntityPacket = new ClientboundAddEntityPacket(npc);
serverPlayer.connection.send(addEntityPacket);
isVisibleForPlayer.put(player.getUniqueId(), true);
int removeNpcsFromPlayerlistDelay = FancyNpcsPlugin.get().getFancyNpcConfig().getRemoveNpcsFromPlayerlistDelay();
if (!data.isShowInTab() && removeNpcsFromPlayerlistDelay > 0) {
FancyNpcsPlugin.get().getNpcThread().schedule(() -> {
ClientboundPlayerInfoRemovePacket playerInfoRemovePacket = new ClientboundPlayerInfoRemovePacket(List.of(npc.getUUID()));
serverPlayer.connection.send(playerInfoRemovePacket);
}, removeNpcsFromPlayerlistDelay, TimeUnit.MILLISECONDS);
}
update(player);
}
@Override
public void remove(Player player) {
if (npc == null) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
if (npc instanceof ServerPlayer npcPlayer) {
ClientboundPlayerInfoRemovePacket playerInfoRemovePacket = new ClientboundPlayerInfoRemovePacket(List.of((npcPlayer.getUUID())));
serverPlayer.connection.send(playerInfoRemovePacket);
}
// remove entity
ClientboundRemoveEntitiesPacket removeEntitiesPacket = new ClientboundRemoveEntitiesPacket(npc.getId());
serverPlayer.connection.send(removeEntitiesPacket);
// remove sitting vehicle
if (sittingVehicle != null) {
ClientboundRemoveEntitiesPacket removeSittingVehiclePacket = new ClientboundRemoveEntitiesPacket(sittingVehicle.getId());
serverPlayer.connection.send(removeSittingVehiclePacket);
}
isVisibleForPlayer.put(serverPlayer.getUUID(), false);
}
@Override
public void lookAt(Player player, Location location) {
if (npc == null) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
npc.setRot(location.getYaw(), location.getPitch());
npc.setYHeadRot(location.getYaw());
npc.setXRot(location.getPitch());
npc.setYRot(location.getYaw());
ClientboundTeleportEntityPacket teleportEntityPacket = new ClientboundTeleportEntityPacket(npc);
serverPlayer.connection.send(teleportEntityPacket);
float angelMultiplier = 256f / 360f;
ClientboundRotateHeadPacket rotateHeadPacket = new ClientboundRotateHeadPacket(npc, (byte) (location.getYaw() * angelMultiplier));
serverPlayer.connection.send(rotateHeadPacket);
}
@Override
public void update(Player player, boolean swingArm) {
if (npc == null) {
return;
}
if (!isVisibleForPlayer.getOrDefault(player.getUniqueId(), false)) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
PlayerTeam team = new PlayerTeam(new Scoreboard(), "npc-" + localName);
team.getPlayers().clear();
team.getPlayers().add(npc instanceof ServerPlayer npcPlayer ? npcPlayer.getGameProfile().getName() : npc.getStringUUID());
team.setColor(PaperAdventure.asVanilla(data.getGlowingColor()));
if (!data.isCollidable()) {
team.setCollisionRule(Team.CollisionRule.NEVER);
}
net.kyori.adventure.text.Component displayName = ModernChatColorHandler.translate(data.getDisplayName(), serverPlayer.getBukkitEntity());
Component vanillaComponent = PaperAdventure.asVanilla(displayName);
if (!(npc instanceof ServerPlayer)) {
npc.setCustomName(vanillaComponent);
npc.setCustomNameVisible(true);
} else {
npc.setCustomName(null);
npc.setCustomNameVisible(false);
}
if (data.getDisplayName().equalsIgnoreCase("<empty>")) {
team.setNameTagVisibility(Team.Visibility.NEVER);
npc.setCustomName(null);
npc.setCustomNameVisible(false);
} else {
team.setNameTagVisibility(Team.Visibility.ALWAYS);
}
if (npc instanceof ServerPlayer npcPlayer) {
team.setPlayerPrefix(vanillaComponent);
npcPlayer.listName = vanillaComponent;
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = EnumSet.noneOf(ClientboundPlayerInfoUpdatePacket.Action.class);
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
if (data.isShowInTab()) {
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
}
ClientboundPlayerInfoUpdatePacket playerInfoPacket = new ClientboundPlayerInfoUpdatePacket(actions, List.of(npcPlayer));
if (data.isMirrorSkin()) {
handleMirroredSkin(playerInfoPacket, serverPlayer);
}
serverPlayer.connection.send(playerInfoPacket);
}
boolean isTeamCreatedForPlayer = this.isTeamCreated.getOrDefault(player.getUniqueId(), false);
serverPlayer.connection.send(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, !isTeamCreatedForPlayer));
isTeamCreated.put(player.getUniqueId(), true);
npc.setGlowingTag(data.isGlowing());
if (data.getEquipment() != null && data.getEquipment().size() > 0) {
List<Pair<EquipmentSlot, ItemStack>> equipmentList = new ArrayList<>();
for (NpcEquipmentSlot slot : data.getEquipment().keySet()) {
equipmentList.add(new Pair<>(EquipmentSlot.byName(slot.toNmsName()), CraftItemStack.asNMSCopy(data.getEquipment().get(slot))));
}
ClientboundSetEquipmentPacket setEquipmentPacket = new ClientboundSetEquipmentPacket(npc.getId(), equipmentList);
serverPlayer.connection.send(setEquipmentPacket);
}
if (npc instanceof ServerPlayer) {
// Enable second layer of skin (https://wiki.vg/Entity_metadata#Player)
npc.getEntityData().set(net.minecraft.world.entity.player.Player.DATA_PLAYER_MODE_CUSTOMISATION, (byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
}
data.applyAllAttributes(this);
refreshEntityData(player);
if (data.isSpawnEntity() && data.getLocation() != null) {
move(player, swingArm);
}
NpcAttribute playerPoseAttr = FancyNpcsPlugin.get().getAttributeManager().getAttributeByName(org.bukkit.entity.EntityType.PLAYER, "pose");
if (data.getAttributes().containsKey(playerPoseAttr)) {
String pose = data.getAttributes().get(playerPoseAttr);
if (pose.equals("sitting")) {
setSitting(serverPlayer);
} else {
if (sittingVehicle != null) {
ClientboundRemoveEntitiesPacket removeSittingVehiclePacket = new ClientboundRemoveEntitiesPacket(sittingVehicle.getId());
serverPlayer.connection.send(removeSittingVehiclePacket);
}
}
}
}
@Override
protected void refreshEntityData(Player player) {
if (!isVisibleForPlayer.getOrDefault(player.getUniqueId(), false)) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
Int2ObjectMap<SynchedEntityData.DataItem<?>> itemsById = (Int2ObjectMap<SynchedEntityData.DataItem<?>>) ReflectionUtils.getValue(npc.getEntityData(), MappingKeys1_19_4.SYNCHED_ENTITY_DATA__ITEMS_BY_ID.getMapping()); // itemsById
List<SynchedEntityData.DataValue<?>> entityData = new ArrayList<>();
for (SynchedEntityData.DataItem<?> dataItem : itemsById.values()) {
entityData.add(dataItem.value());
}
ClientboundSetEntityDataPacket setEntityDataPacket = new ClientboundSetEntityDataPacket(npc.getId(), entityData);
serverPlayer.connection.send(setEntityDataPacket);
}
public void move(Player player, boolean swingArm) {
if (npc == null) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
npc.setPosRaw(data.getLocation().x(), data.getLocation().y(), data.getLocation().z());
npc.setRot(data.getLocation().getYaw(), data.getLocation().getPitch());
npc.setYHeadRot(data.getLocation().getYaw());
npc.setXRot(data.getLocation().getPitch());
npc.setYRot(data.getLocation().getYaw());
ClientboundTeleportEntityPacket teleportEntityPacket = new ClientboundTeleportEntityPacket(npc);
ReflectionUtils.setValue(teleportEntityPacket, MappingKeys1_19_4.CLIENTBOUND_TELEPORT_ENTITY_PACKET__X.getMapping(), data.getLocation().x()); // 'x'
ReflectionUtils.setValue(teleportEntityPacket, MappingKeys1_19_4.CLIENTBOUND_TELEPORT_ENTITY_PACKET__Y.getMapping(), data.getLocation().y()); // 'y'
ReflectionUtils.setValue(teleportEntityPacket, MappingKeys1_19_4.CLIENTBOUND_TELEPORT_ENTITY_PACKET__Z.getMapping(), data.getLocation().z()); // 'z'
serverPlayer.connection.send(teleportEntityPacket);
float angelMultiplier = 256f / 360f;
ClientboundRotateHeadPacket rotateHeadPacket = new ClientboundRotateHeadPacket(npc, (byte) (data.getLocation().getYaw() * angelMultiplier));
serverPlayer.connection.send(rotateHeadPacket);
if (swingArm && npc instanceof ServerPlayer) {
ClientboundAnimatePacket animatePacket = new ClientboundAnimatePacket(npc, 0);
serverPlayer.connection.send(animatePacket);
}
}
public void setSitting(ServerPlayer serverPlayer) {
if (npc == null) {
return;
}
if (sittingVehicle == null) {
sittingVehicle = new Display.TextDisplay(EntityType.TEXT_DISPLAY, ((CraftWorld) data.getLocation().getWorld()).getHandle());
}
sittingVehicle.setPos(data.getLocation().x(), data.getLocation().y(), data.getLocation().z());
ClientboundAddEntityPacket addEntityPacket = new ClientboundAddEntityPacket(sittingVehicle);
serverPlayer.connection.send(addEntityPacket);
sittingVehicle.passengers = ImmutableList.of(npc);
ClientboundSetPassengersPacket packet = new ClientboundSetPassengersPacket(sittingVehicle);
serverPlayer.connection.send(packet);
}
private void handleMirroredSkin(ClientboundPlayerInfoUpdatePacket playerInfoUpdatePacket, ServerPlayer viewer) {
if (!ServerLoginPacketListenerImpl.isValidUsername(viewer.getGameProfile().getName())) return;
ClientboundPlayerInfoUpdatePacket.Entry entry = playerInfoUpdatePacket.entries().get(0);
GameProfile profile = entry.profile();
GameProfile newProfile = new GameProfile(profile.getId(), profile.getName());
newProfile.getProperties().putAll(viewer.getGameProfile().getProperties());
ClientboundPlayerInfoUpdatePacket.Entry newEntry = new ClientboundPlayerInfoUpdatePacket.Entry(
entry.profileId(),
newProfile,
entry.listed(),
entry.latency(),
entry.gameMode(),
entry.displayName(),
entry.chatSession()
);
ReflectionUtils.setValue(playerInfoUpdatePacket, "b", List.of(newEntry)); // 'entries'
}
@Override
public float getEyeHeight() {
return npc.getEyeHeight();
}
@Override
public int getEntityId() {
return npc.getId();
}
public Entity getNpc() {
return npc;
}
}

View File

@@ -1,74 +0,0 @@
package de.oliver.fancynpcs.v1_19_4;
import de.oliver.fancylib.FancyLib;
import de.oliver.fancylib.ReflectionUtils;
import de.oliver.fancynpcs.api.FancyNpcsPlugin;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.actions.ActionTrigger;
import de.oliver.fancynpcs.api.events.PacketReceivedEvent;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import net.minecraft.network.protocol.game.ServerboundInteractPacket;
import net.minecraft.server.level.ServerPlayer;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.inventory.EquipmentSlot;
import java.util.List;
public class PacketReader_1_19_4 implements Listener {
public static boolean inject(Player player) {
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
Channel channel = serverPlayer.connection.connection.channel;
if (channel.pipeline().get("PacketInjector") != null) {
return false;
}
channel.pipeline().addAfter("decoder", "PacketInjector", new MessageToMessageDecoder<ServerboundInteractPacket>() {
@Override
protected void decode(ChannelHandlerContext ctx, ServerboundInteractPacket msg, List<Object> out) {
out.add(msg);
PacketReceivedEvent packetReceivedEvent = new PacketReceivedEvent(msg, player);
FancyLib.getInstance().getScheduler().runTaskLater(null, 1L, packetReceivedEvent::callEvent);
}
});
return true;
}
@EventHandler
public void onPacketReceived(final PacketReceivedEvent event) {
// Skipping packets other than ServerboundInteractPacket...
if (!(event.getPacket() instanceof ServerboundInteractPacket interactPacket))
return;
// Getting NPC from entity identifier.
final Npc npc = FancyNpcsPlugin.get().getNpcManager().getNpc(interactPacket.getEntityId());
// Skipping entities that are not FancyNpcs' NPCs...
if (npc == null)
return;
// Getting interaction information.
final boolean isAttack = (interactPacket.getActionType() == ServerboundInteractPacket.ActionType.ATTACK);
final boolean isInteract = (interactPacket.getActionType() == ServerboundInteractPacket.ActionType.INTERACT_AT);
final EquipmentSlot hand = (interactPacket.getActionType() == ServerboundInteractPacket.ActionType.ATTACK)
? EquipmentSlot.HAND
: ReflectionUtils.getValue(ReflectionUtils.getValue(interactPacket, "b"), "a").toString().equals("MAIN_HAND") // ServerboundInteractPacket.InteractionAction.hand
? EquipmentSlot.HAND
: EquipmentSlot.OFF_HAND;
// This can optionally be ALSO called for OFF-HAND slot. Making sure to run logic only ONCE.
if (hand == EquipmentSlot.HAND) {
// This packet can be sent multiple times for interactions that are NOT attacks, making sure to run logic only ONCE.
if (isAttack || !isInteract || npc.getData().getType() == EntityType.ARMOR_STAND) {
npc.interact(event.getPlayer(), isAttack ? ActionTrigger.LEFT_CLICK : ActionTrigger.RIGHT_CLICK);
}
}
}
}

View File

@@ -1,13 +0,0 @@
package de.oliver.fancynpcs.v1_19_4;
import de.oliver.fancylib.ReflectionUtils;
import de.oliver.fancynpcs.api.Npc;
import net.minecraft.world.entity.Entity;
public class ReflectionHelper {
public static <T extends Entity> T getEntity(Npc npc) {
return (T) ReflectionUtils.getValue(npc, "npc");
}
}

View File

@@ -1,38 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.AgeableMob;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AgeableMobAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"baby",
List.of("true", "false"),
Arrays.stream(EntityType.values())
.filter(type -> type.getEntityClass() != null && Ageable.class.isAssignableFrom(type.getEntityClass()))
.toList(),
AgeableMobAttributes::setBaby
));
return attributes;
}
private static void setBaby(Npc npc, String value) {
AgeableMob mob = ReflectionHelper.getEntity(npc);
boolean isBaby = Boolean.parseBoolean(value);
mob.setBaby(isBaby);
}
}

View File

@@ -1,34 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.animal.allay.Allay;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class AllayAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"dancing",
List.of("true", "false"),
List.of(EntityType.ALLAY),
AllayAttributes::setDancing
));
return attributes;
}
private static void setDancing(Npc npc, String value) {
Allay allay = ReflectionHelper.getEntity(npc);
boolean dancing = Boolean.parseBoolean(value);
allay.setDancing(dancing);
}
}

View File

@@ -1,35 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.decoration.ArmorStand;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class ArmorStandAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"show_arms",
List.of("true", "false"),
List.of(EntityType.ARMOR_STAND),
ArmorStandAttributes::setShowArms
));
return attributes;
}
private static void setShowArms(Npc npc, String value) {
ArmorStand armorStand = ReflectionHelper.getEntity(npc);
boolean showArms = Boolean.parseBoolean(value.toLowerCase());
armorStand.setShowArms(showArms);
}
}

View File

@@ -1,51 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.NpcAttribute;
import java.util.ArrayList;
import java.util.List;
public class Attributes_1_19_4 {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.addAll(EntityAttributes.getAllAttributes());
attributes.addAll(LivingEntityAttributes.getAllAttributes());
attributes.addAll(AgeableMobAttributes.getAllAttributes());
attributes.addAll(IllagerAttributes.getAllAttributes());
attributes.addAll(SpellCasterAttributes.getAllAttributes());
attributes.addAll(PlayerAttributes.getAllAttributes());
attributes.addAll(SheepAttributes.getAllAttributes());
attributes.addAll(VillagerAttributes.getAllAttributes());
attributes.addAll(FrogAttributes.getAllAttributes());
attributes.addAll(HorseAttributes.getAllAttributes());
attributes.addAll(ParrotAttributes.getAllAttributes());
attributes.addAll(AxolotlAttributes.getAllAttributes());
attributes.addAll(TropicalFishAttributes.getAllAttributes());
attributes.addAll(FoxAttributes.getAllAttributes());
attributes.addAll(PandaAttributes.getAllAttributes());
attributes.addAll(GoatAttributes.getAllAttributes());
attributes.addAll(AllayAttributes.getAllAttributes());
attributes.addAll(CamelAttributes.getAllAttributes());
attributes.addAll(RabbitAttributes.getAllAttributes());
attributes.addAll(PiglinAttributes.getAllAttributes());
attributes.addAll(CatAttributes.getAllAttributes());
attributes.addAll(ShulkerAttributes.getAllAttributes());
attributes.addAll(WolfAttributes.getAllAttributes());
attributes.addAll(SlimeAttributes.getAllAttributes());
attributes.addAll(PigAttributes.getAllAttributes());
attributes.addAll(ArmorStandAttributes.getAllAttributes());
attributes.addAll(BeeAttributes.getAllAttributes());
attributes.addAll(VexAttributes.getAllAttributes());
attributes.addAll(DisplayAttributes.getAllAttributes());
attributes.addAll(TextDisplayAttributes.getAllAttributes());
attributes.addAll(BlockDisplayAttributes.getAllAttributes());
attributes.addAll(InteractionAttributes.getAllAttributes());
return attributes;
}
}

View File

@@ -1,51 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.animal.axolotl.Axolotl;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AxolotlAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
Arrays.stream(Axolotl.Variant.values())
.map(Enum::name)
.toList(),
List.of(EntityType.AXOLOTL),
AxolotlAttributes::setVariant
));
attributes.add(new NpcAttribute(
"playing_dead",
List.of("true", "false"),
List.of(EntityType.AXOLOTL),
AxolotlAttributes::setPlayingDead
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
Axolotl axolotl = ReflectionHelper.getEntity(npc);
Axolotl.Variant variant = Axolotl.Variant.valueOf(value.toUpperCase());
axolotl.setVariant(variant);
}
private static void setPlayingDead(Npc npc, String value) {
Axolotl axolotl = ReflectionHelper.getEntity(npc);
boolean playingDead = Boolean.parseBoolean(value);
axolotl.setPlayingDead(playingDead);
}
}

View File

@@ -1,84 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.animal.Bee;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class BeeAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"angry",
List.of("true", "false"),
List.of(EntityType.BEE),
BeeAttributes::setAngry
));
attributes.add(new NpcAttribute(
"sting",
List.of("true", "false"),
List.of(EntityType.BEE),
BeeAttributes::setSting
));
attributes.add(new NpcAttribute(
"nectar",
List.of("true", "false"),
List.of(EntityType.BEE),
BeeAttributes::setNectar
));
attributes.add(new NpcAttribute(
"rolling",
List.of("true", "false"),
List.of(EntityType.BEE),
BeeAttributes::setRolling
));
return attributes;
}
private static void setAngry(Npc npc, String value) {
Bee bee = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "true" -> bee.setRemainingPersistentAngerTime(1);
case "false" -> bee.setRemainingPersistentAngerTime(0);
}
}
private static void setSting(Npc npc, String value) {
Bee bee = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "true" -> bee.setHasStung(false);
case "false" -> bee.setHasStung(true);
}
}
private static void setNectar(Npc npc, String value) {
Bee bee = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "true" -> bee.setHasNectar(true);
case "false" -> bee.setHasNectar(false);
}
}
private static void setRolling(Npc npc, String value) {
Bee bee = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "true" -> bee.setRolling(true);
case "false" -> bee.setRolling(false);
}
}
}

View File

@@ -1,42 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Display;
import net.minecraft.world.level.block.Block;
import org.bukkit.Material;
import org.bukkit.Registry;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.StreamSupport;
public class BlockDisplayAttributes {
private static final List<String> BLOCKS = StreamSupport.stream(Registry.MATERIAL.spliterator(), false).filter(Material::isBlock).map(it -> it.key().value()).toList();
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"block",
BLOCKS,
List.of(EntityType.BLOCK_DISPLAY),
BlockDisplayAttributes::setBlock
));
return attributes;
}
private static void setBlock(Npc npc, String value) {
Display.BlockDisplay display = ReflectionHelper.getEntity(npc);
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + value.toLowerCase(), ':'));
display.setBlockState(block.defaultBlockState());
}
}

View File

@@ -1,46 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.animal.camel.Camel;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class CamelAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "sitting", "dashing"),
List.of(EntityType.CAMEL),
CamelAttributes::setPose
));
return attributes;
}
private static void setPose(Npc npc, String value) {
Camel camel = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> {
camel.setDashing(false);
camel.standUp();
}
case "sitting" -> {
camel.setDashing(false);
camel.sitDown();
}
case "dashing" -> {
camel.standUp();
camel.setDashing(true);
}
}
}
}

View File

@@ -1,92 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.animal.Cat;
import net.minecraft.world.item.DyeColor;
import org.bukkit.entity.EntityType;
import org.checkerframework.checker.units.qual.N;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CatAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
Arrays.stream(org.bukkit.entity.Cat.Type.values())
.map(Enum::name)
.toList(),
List.of(EntityType.CAT),
CatAttributes::setVariant
));
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "sleeping", "sitting"),
List.of(EntityType.CAT),
CatAttributes::setPose
));
attributes.add(new NpcAttribute(
"collar_color",
List.of("RED", "BLUE", "YELLOW", "GREEN", "PURPLE", "ORANGE", "LIME", "MAGENTA", "BROWN", "WHITE", "GRAY", "LIGHT_GRAY", "LIGHT_BLUE", "BLACK", "CYAN", "PINK", "NONE"),
List.of(EntityType.CAT),
CatAttributes::setCollarColor
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
final Cat cat = ReflectionHelper.getEntity(npc);
BuiltInRegistries.CAT_VARIANT.getOptional(ResourceLocation.of(value.toLowerCase(), ':'))
.ifPresent(cat::setVariant);
}
private static void setPose(Npc npc, String value) {
final Cat cat = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> {
cat.setInSittingPose(false, false);
cat.setLying(false);
}
case "sleeping" -> {
cat.setInSittingPose(false, false);
cat.setLying(true);
}
case "sitting" -> {
cat.setLying(false);
cat.setOrderedToSit(true);
cat.setInSittingPose(true, false);
}
}
}
private static void setCollarColor(Npc npc, String value){
final Cat cat = ReflectionHelper.getEntity(npc);
if (value.equalsIgnoreCase("none") || value.isEmpty()){
cat.setTame(false);
return;
}
try {
DyeColor color = DyeColor.valueOf(value.toUpperCase());
if (!cat.isTame()){
cat.setTame(true);
}
cat.setCollarColor(color);
} catch (IllegalArgumentException e){
System.out.print("Invalid Color: " + value);
}
}
}

View File

@@ -1,37 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.Display;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class DisplayAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"billboard",
Arrays.stream(org.bukkit.entity.Display.Billboard.values())
.map(Enum::name)
.toList(),
List.of(EntityType.TEXT_DISPLAY, EntityType.BLOCK_DISPLAY, EntityType.ITEM_DISPLAY),
DisplayAttributes::setBillboard
));
return attributes;
}
private static void setBillboard(Npc npc, String value) {
Display display = ReflectionHelper.getEntity(npc);
Display.BillboardConstraints billboard = Display.BillboardConstraints.valueOf(value.toUpperCase());
display.setBillboardConstraints(billboard);
}
}

View File

@@ -1,103 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.Entity;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class EntityAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"on_fire",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setOnFire
));
attributes.add(new NpcAttribute(
"invisible",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setInvisible
));
attributes.add(new NpcAttribute(
"silent",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setSilent
));
attributes.add(new NpcAttribute(
"shaking",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setShaking
));
attributes.add(new NpcAttribute(
"on_ground",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setOnGround
));
/*attributes.add(new NpcAttribute(
"entity_pose",
Arrays.stream(Pose.values()).map(Enum::toString).toList(),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setEntityPose
));*/
return attributes;
}
private static void setOnFire(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean onFire = Boolean.parseBoolean(value);
entity.setSharedFlagOnFire(onFire);
}
private static void setInvisible(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean invisible = Boolean.parseBoolean(value);
entity.setInvisible(invisible);
}
private static void setSilent(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean silent = Boolean.parseBoolean(value);
entity.setSilent(silent);
}
private static void setShaking(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean shaking = Boolean.parseBoolean(value);
entity.setTicksFrozen(shaking ? entity.getTicksRequiredToFreeze() : 0);
}
private static void setOnGround(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean onGround = Boolean.parseBoolean(value);
entity.setOnGround(onGround);
}
}

View File

@@ -1,66 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.animal.Fox;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FoxAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"type",
Arrays.stream(Fox.Type.values())
.map(Enum::name)
.toList(),
List.of(EntityType.FOX),
FoxAttributes::setType
));
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "sleeping", "sitting"),
List.of(EntityType.FOX),
FoxAttributes::setPose
));
return attributes;
}
private static void setType(Npc npc, String value) {
Fox fox = ReflectionHelper.getEntity(npc);
Fox.Type type = Fox.Type.valueOf(value.toUpperCase());
fox.setVariant(type);
}
private static void setPose(Npc npc, String value) {
Fox fox = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> {
fox.setIsCrouching(false);
fox.setSleeping(false);
fox.setSitting(false, false);
}
case "sleeping" -> {
fox.setSleeping(true);
fox.setSitting(false, false);
fox.setIsCrouching(false);
}
case "sitting" -> {
fox.setSitting(true, false);
fox.setSleeping(false);
fox.setIsCrouching(false);
}
}
}
}

View File

@@ -1,44 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.animal.FrogVariant;
import net.minecraft.world.entity.animal.frog.Frog;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FrogAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
Arrays.stream(org.bukkit.entity.Frog.Variant.values())
.map(Enum::name)
.toList(),
List.of(EntityType.FROG),
FrogAttributes::setVariant
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
Frog frog = ReflectionHelper.getEntity(npc);
FrogVariant variant;
switch (value.toUpperCase()) {
case "COLD" -> variant = FrogVariant.COLD;
case "WARM" -> variant = FrogVariant.WARM;
default -> variant = FrogVariant.TEMPERATE;
}
frog.setVariant(variant);
}
}

View File

@@ -1,44 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.animal.goat.Goat;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class GoatAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"horns",
List.of("none", "left", "right", "both"),
List.of(EntityType.GOAT),
GoatAttributes::setHorns
));
return attributes;
}
private static void setHorns(Npc npc, String value) {
Goat goat = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "none" -> goat.removeHorns();
case "both" -> goat.addHorns();
case "left" -> {
goat.getEntityData().set(Goat.DATA_HAS_LEFT_HORN, true);
goat.getEntityData().set(Goat.DATA_HAS_RIGHT_HORN, false);
}
case "right" -> {
goat.getEntityData().set(Goat.DATA_HAS_RIGHT_HORN, true);
goat.getEntityData().set(Goat.DATA_HAS_LEFT_HORN, false);
}
}
}
}

View File

@@ -1,84 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.animal.horse.Horse;
import net.minecraft.world.entity.animal.horse.Markings;
import net.minecraft.world.entity.animal.horse.Variant;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class HorseAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
Arrays.stream(Variant.values())
.map(Enum::name)
.toList(),
List.of(EntityType.HORSE),
HorseAttributes::setVariant
));
attributes.add(new NpcAttribute(
"markings",
Arrays.stream(Markings.values())
.map(Enum::name)
.toList(),
List.of(EntityType.HORSE),
HorseAttributes::setMarkings
));
attributes.add(new NpcAttribute(
"pose",
List.of("eating", "rearing", "standing"),
Arrays.stream(EntityType.values())
.filter(type -> type.getEntityClass() != null && (type == EntityType.HORSE || type == EntityType.DONKEY ||
type == EntityType.MULE || type == EntityType.SKELETON_HORSE ||type == EntityType.ZOMBIE_HORSE))
.toList(),
HorseAttributes::setPose
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
Horse horse = ReflectionHelper.getEntity(npc);
Variant variant = Variant.valueOf(value.toUpperCase());
horse.setVariant(variant);
}
private static void setMarkings(Npc npc, String value) {
Horse horse = ReflectionHelper.getEntity(npc);
Markings markings = Markings.valueOf(value.toUpperCase());
horse.setVariantAndMarkings(horse.getVariant(), markings);
}
private static void setPose(Npc npc, String value) {
net.minecraft.world.entity.animal.horse.AbstractHorse horse = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> {
horse.setEating(false);
horse.setForceStanding(false);
}
case "rearing" -> {
horse.setForceStanding(true);
horse.setEating(false);
}
case "eating" -> {
horse.setForceStanding(false);
horse.setEating(true);
}
}
}
}

View File

@@ -1,39 +0,0 @@
package de.oliver.fancynpcs.v1_19_4.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_19_4.ReflectionHelper;
import net.minecraft.world.entity.raid.Raider;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Illager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class IllagerAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"celebrating",
List.of("true", "false"),
Arrays.stream(EntityType.values())
.filter(type -> type.getEntityClass() != null && Illager.class.isAssignableFrom(type.getEntityClass()))
.toList(),
IllagerAttributes::setCelebrating
));
return attributes;
}
private static void setCelebrating(Npc npc, String value) {
Raider raider = ReflectionHelper.getEntity(npc);
boolean isCelebrating = Boolean.parseBoolean(value);
raider.setCelebrating(isCelebrating);
}
}

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