Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.gradle/
build/

# IntelliJ project files
.idea
Expand All @@ -17,4 +19,20 @@ gen
.project
.classpath
.settings
bin
bin

# Local editors and OS files
.DS_Store
Thumbs.db
.vscode/
*.swp
*.swo

# Local test servers and generated Paper data
servers/
cache/
libraries/
versions/

# Local release jars for the centralized Paper runner
libs/
533 changes: 523 additions & 10 deletions README.md

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
plugins {
id 'java'
}

group = 'com.onemb.xmas'
version = '2.1.0-051'
def projectVersion = version.toString()
def enableDeprecationLint = providers.gradleProperty('lintDeprecatedApi').map { it.toBoolean() }.getOrElse(false)

def javaRelease = 25
def paperCompileVersion = '26.2.build.29-alpha'
def declaredPluginApiVersion = '26.2'
def experimentalCompatibilityTarget = 'future 26.x'
def resourceExpansionProperties = [
version : projectVersion,
apiVersion: declaredPluginApiVersion
]
def sharedServersRoot = file(System.getenv('CODEX_SHARED_SERVERS_ROOT') ?: '/Users/floris/Projects/Codex/servers')
def sharedPaperCache = new File(sharedServersRoot, 'cache/Paper-26.2')
def paper262LibrariesDir = new File(sharedPaperCache, 'libraries')
def paper262Api = new File(sharedPaperCache, "libraries/io/papermc/paper/paper-api/${paperCompileVersion}/paper-api-${paperCompileVersion}.jar")
def placeholderApiJar = new File(sharedPaperCache, 'plugins/PlaceholderAPI-2.12.3-DEV-266.jar')
def paper262ArchiveName = "1MB-XMas-2026-v${projectVersion}-v25-26.2.jar"

[
[paper262Api, "Paper API jar"],
[paper262LibrariesDir, "Paper libraries directory"],
[placeholderApiJar, "PlaceholderAPI jar"],
].each { entry ->
File path = entry[0] as File
String label = entry[1] as String
if (!path.exists()) {
throw new GradleException("${label} not found at ${path}. This project now uses the centralized Paper cache under ${sharedServersRoot}.")
}
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(javaRelease)
}
}

dependencies {
compileOnly files(paper262Api)
compileOnly fileTree(dir: paper262LibrariesDir, include: '**/*.jar')
compileOnly files(placeholderApiJar)
}

tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
options.release = javaRelease
if (enableDeprecationLint) {
options.compilerArgs.add('-Xlint:deprecation')
}
}

tasks.named('processResources') {
filteringCharset = 'UTF-8'
inputs.properties(resourceExpansionProperties)
filesMatching('plugin.yml') {
expand(resourceExpansionProperties)
}
}

tasks.named('jar') {
archiveFileName = paper262ArchiveName
}

tasks.register('releaseJar', Copy) {
description = 'Copies the newest plugin jar into libs/ for the centralized Paper runner.'
group = 'build'
dependsOn tasks.named('jar')
from(tasks.named('jar'))
into(layout.projectDirectory.dir('libs'))
}

tasks.register('paper262Jar') {
description = 'Assembles the Paper 26.2 Java 25 plugin jar and copies it into libs/.'
group = 'build'
dependsOn tasks.named('releaseJar')
}

tasks.register('printBuildConfig') {
description = 'Prints the active centralized build and compatibility configuration.'
group = 'help'
doLast {
println 'XMasTree build config'
println " version: ${projectVersion}"
println " compile target: Paper API ${paperCompileVersion}"
println " declared plugin api-version: ${declaredPluginApiVersion}"
println " experimental compatibility target: Paper ${experimentalCompatibilityTarget}"
println " java release target: ${javaRelease}"
println " centralized Paper cache: ${sharedPaperCache}"
println " PlaceholderAPI compile jar: ${placeholderApiJar}"
println " deprecation lint enabled: ${enableDeprecationLint}"
println " build/libs output: ${layout.buildDirectory.file("libs/${paper262ArchiveName}").get().asFile}"
println " libs/ release copy: ${layout.projectDirectory.file("libs/${paper262ArchiveName}").asFile}"
}
}

tasks.register('buildAllJars') {
description = 'Builds the current Paper 26.2 target jar and copies it into libs/.'
group = 'build'
dependsOn tasks.named('releaseJar')
finalizedBy tasks.named('printBuildConfig')
}

tasks.named('assemble') {
dependsOn tasks.named('paper262Jar')
}
22 changes: 22 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# XMas Tree Documentation

This directory contains source documentation for the central 1MoreBlock docs importer.

Canonical public URL:

[docs.1moreblock.com/custom-server-plugins/xmas-tree/](https://docs.1moreblock.com/custom-server-plugins/xmas-tree/)

## Pages

- [Player Guide](player-guide.md)
- [Commands](commands.md)
- [Permissions](permissions.md)
- [Placeholders](placeholders.md)
- [Configuration](configuration.md)
- [Installation and Building](installation.md)
- [Integrations](integrations.md)
- [Troubleshooting](troubleshooting.md)

## Import Manifest

The importer manifest is [plugin-docs.yml](plugin-docs.yml).
58 changes: 58 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# XMas Tree Commands

Primary command: `/xmastree`

The old `/xmas` command is not registered by this plugin, leaving it free for a broader event command or another plugin.

## Player Commands

| Command | Permission | Description |
| --- | --- | --- |
| `/xmastree` | `onembxmastree.command.status` | Shows plugin version, event status, auto-end, refund status, tree count, and owner count. |
| `/xmastree help` | `onembxmastree.command.help` | Shows the command list. |
| `/xmastree info` | `onembxmastree.command.info` | Shows a short player guide and the canonical docs link. |
| `/xmastree journal [player]` | `onembxmastree.command.journal` | Shows tree count, highest tree level, gift totals, streaks, claimable milestones, tree history, and claimed milestone history. Viewing another player requires `onembxmastree.tree.override`. |
| `/xmastree journal gui [player]` | `onembxmastree.command.journal` | Opens the journal GUI for yourself or, with override permission, another player. |
| `/xmastree milestones [player]` | `onembxmastree.command.milestones` | Shows personal milestone progress and claim state. Viewing another player requires `onembxmastree.tree.override`. |
| `/xmastree milestones claim <key>` | `onembxmastree.command.milestones.claim` | Claims a ready personal milestone reward for yourself. |
| `/xmastree community` | `onembxmastree.command.community` | Shows server-wide community milestone progress. |

## Gift Management

| Command | Permission | Description |
| --- | --- | --- |
| `/xmastree gifts` | `onembxmastree.command.gifts` | Spawns presents under every loaded XMas tree. |
| `/xmastree gifts spawn` | `onembxmastree.command.gifts` | Explicit form of `/xmastree gifts`. |
| `/xmastree gifts list [page]` | `onembxmastree.command.gifts` | Lists configured gift rewards by index, weight, and roll chance. |
| `/xmastree gifts roll` | `onembxmastree.command.gifts` | Previews one weighted random gift roll without giving it to anyone. |
| `/xmastree gifts remove <index>` | `onembxmastree.command.gifts` | Removes a configured gift reward by list index. |
| `/xmastree gifts weight <index> <weight>` | `onembxmastree.command.gifts` | Sets a positive whole-number roll weight for a gift reward. |
| `/xmastree gifts addhand` | `onembxmastree.command.addhand` | Adds the held item to the gift pool and saves it to `config.yml`. |
| `/xmastree addhand` | `onembxmastree.command.addhand` | Compatibility shortcut for `/xmastree gifts addhand`. |

## Staff and Admin Commands

| Command | Permission | Description |
| --- | --- | --- |
| `/xmastree give <player>` | `onembxmastree.command.give` | Gives an online player a Christmas Crystal. |
| `/xmastree reload` | `onembxmastree.command.reload` | Reloads config, translations, theme, prefix, crystal text, present heads, gifts, luck settings, and tree level requirements. Prints a reload report. |
| `/xmastree inspect` | `onembxmastree.command.inspect` | Inspects the tree you are looking at, or the nearest tree if no tree block is targeted. |
| `/xmastree inspect nearest <player>` | `onembxmastree.command.inspect` | Inspects the nearest loaded tree to an online player. |
| `/xmastree inspect <tree-uuid>` | `onembxmastree.command.inspect` | Inspects a specific loaded tree by UUID. |
| `/xmastree test sound first [player]` | `onembxmastree.command.test` | Previews the configured first accepted ingredient sound. |
| `/xmastree test sound repeat [player]` | `onembxmastree.command.test` | Previews the configured repeat ingredient sound. |
| `/xmastree test particle <level> [all\|ambient\|swag\|body] [player]` | `onembxmastree.command.test` | Previews configured particles for a tree stage. |
| `/xmastree test refund [tree-uuid\|nearest [player]]` | `onembxmastree.command.test` | Dry-runs refund delivery without editing data or giving items. |
| `/xmastree data backup [trees\|progress\|all]` | `onembxmastree.command.data` | Creates timestamped data backups. Defaults to `trees`. |
| `/xmastree data validate` | `onembxmastree.command.data` | Validates `trees.yml` for invalid IDs, owners, levels, locations, worlds, requirements, and duplicate locations. |
| `/xmastree data report` | `onembxmastree.command.data` | Shows an event wrap-up report with tree, gift, milestone, and returning-player summary data. |
| `/xmastree data migrate-world <from> <to> [dry-run\|apply]` | `onembxmastree.command.data` | Reviews or rewrites saved tree world names. `apply` creates a backup first. |
| `/xmastree milestones test <key> [player]` | `onembxmastree.command.test` | Previews personal milestone reward commands without claiming or running them. |
| `/xmastree community test <key>` | `onembxmastree.command.test` | Previews community milestone reward commands without claiming or running them. |
| `/xmastree community claim <key> confirm` | `onembxmastree.command.community.claim` | Claims a ready community milestone reward. Requires explicit `confirm`. |
| `/xmastree debug` | `onembxmastree.command.debug` | Opens the status debug section. |
| `/xmastree debug [section\|page]` | `onembxmastree.command.debug` | Shows debug output for `status`, `commands`, `permissions`, `placeholders`, `config`, or `diagnostics`. Numeric pages `1-6` still work. |
| `/xmastree debug toggle <key> true\|false` | `onembxmastree.command.debug.toggle` | Toggles supported global boolean config keys and reloads the plugin config. |
| `/xmastree end` | `onembxmastree.command.end` | Ends the event and sets `core.plugin-enabled` to `false`. |

`onembxmastree.admin` includes all command permissions and tree override access.
151 changes: 151 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# XMas Tree Configuration

Main config file:

```text
plugins/X-Mas/config.yml
```

The plugin preserves existing admin-edited values while adding missing defaults and missing bundled comments when it loads config. Most settings apply with `/xmastree reload`; the exceptions are noted below.

## Core Settings

| Key | Default | Reload Behavior | Notes |
| --- | --- | --- | --- |
| `core.plugin-enabled` | `true` | `/xmastree reload`; also live-toggleable with `/xmastree debug toggle core.plugin-enabled true\|false` | Master event switch. Turning the event back on after an end state is safest with a restart. |
| `core.locale` | `en` | `/xmastree reload` | Loads `plugins/X-Mas/translations/locale_<locale>.yml`. |
| `core.tree-limit` | `3` | `/xmastree reload` | Applies to future placement checks. |
| `core.holiday-ends.enabled` | `true` | `/xmastree reload`; live-toggleable | Enables time-based event shutdown. |
| `core.holiday-ends.date` | `10-01-2027 03-33-33` | `/xmastree reload` | Format is `dd-MM-yyyy HH-mm-ss`. |
| `core.holiday-ends.resource-back` | `true` | `/xmastree reload`; live-toggleable | Returns actually spent upgrade materials when a tree is destroyed after confirmation. |
| `core.update-speed` | `7` ticks | Restart recommended | Main tree update task cadence. Reload reads the value, but a restart is recommended to recreate the scheduled task cadence. |
| `core.particles-delay` | `35` ticks | Restart recommended | Particle task cadence. |
| `core.particles-enabled` | `true` | `/xmastree reload`; live-toggleable | Global particle switch. |
| `core.sounds.grow.first-volume` | `0.5` | `/xmastree reload` | First accepted item sound volume. Use `0.0` for silent and `1.0` for full volume. |
| `core.sounds.grow.repeat-volume` | `0.2` | `/xmastree reload` | Repeated accepted item sound volume for the same material requirement. |

## Luck

| Key | Default | Reload Behavior | Notes |
| --- | --- | --- | --- |
| `xmas.luck.enabled` | `false` | `/xmastree reload`; live-toggleable | When disabled, presents always use the main gift pool. |
| `xmas.luck.chance` | `75` | `/xmastree reload` | Percent chance for the normal gift outcome when luck is enabled. |

## Presents and Gifts

`xmas.presents` controls the player-head textures used for present blocks. Modern entries should be `textures.minecraft.net` URLs. Old player-name entries still load for compatibility, but diagnostics warn about them.

`xmas.gifts` controls rewards from opened presents. Supported formats:

```yaml
xmas:
gifts:
- DIAMOND
- EMERALD:3
- item: GOLD_INGOT
weight: 10
```

Supported gift entry forms:

- `MATERIAL`
- `MATERIAL:AMOUNT`
- Base64 item strings saved by `/xmastree gifts addhand`
- weighted entries with `item` and positive whole-number `weight`

Invalid modern material names, legacy material names, malformed texture URLs, and unsafe texture URL hosts are skipped and surfaced in reload/debug diagnostics.

## Milestones

Milestones live under:

```yaml
xmas:
milestones:
player:
community:
```

Supported milestone fields:

| Field | Notes |
| --- | --- |
| `enabled` | `true` or `false`. |
| `type` | Player milestones support `daily_gifts`, `total_gifts`, and `streak_days`. Community milestones support `community_gifts`. |
| `target` | Whole number `1` or higher. |
| `display-name` | Name shown in milestone commands and journals. |
| `reward-commands` | Console commands run when the milestone is claimed. |

Reward command tokens:

- `{player}`
- `{claimer}`
- `{milestone}`
- `{display_name}`
- `{target}`
- `{progress}`

Example:

```yaml
reward-commands:
- cmi kit christmas {player}
- cmi money give {player} 250
- cmi toast {player} -t:task -icon:EMERALD -text:"{display_name} complete!"
```

Milestone definition changes apply with `/xmastree reload`. Existing progress and claim state are stored in `progress.yml` and are not reset by changing config.

## Tree Levels

Tree stages live under `xmas.tree-lvl`:

- `sapling`
- `small_tree`
- `tree`
- `magic_tree`
- `super_tree`

Each stage can define:

- `gift-cooldown`
- `particles.ambient`
- `particles.swag`
- `particles.body`
- `lvlup` material requirements for the next stage

Use modern Paper/Bukkit material names for `lvlup`. Particle names should come from the Paper 26.2 `Particle` enum:

[jd.papermc.io/paper/26.2/org/bukkit/Particle.html](https://jd.papermc.io/paper/26.2/org/bukkit/Particle.html)

`/xmastree reload` is enough for new trees and newly loaded trees. A restart is recommended when every existing loaded tree should use refreshed stage settings consistently.

## World Aliases and Migration

Legacy world-name remapping lives under:

```yaml
migration:
world-aliases:
general: world
wild: world
```

Aliases let old `trees.yml` records load in renamed worlds without rewriting data. To rewrite saved world names, use:

```text
/xmastree data migrate-world <from> <to>
/xmastree data migrate-world <from> <to> apply
```

The `apply` form creates a backup before writing and should be followed by a restart before testing migrated legacy trees.

## Translation and Theme

Player/admin messages, the chat prefix, and theme aliases live in:

```text
plugins/X-Mas/translations/locale_en.yml
```

MiniMessage is supported. The bundled locale uses semantic tags such as `<xm-text>`, `<xm-accent>`, `<xm-label>`, `<xm-command>`, `<xm-success>`, `<xm-warning>`, `<xm-error>`, and `<xm-info>`.
Loading