From 38b44fc1083734d7510dfd9e98897ee5367cc4e1 Mon Sep 17 00:00:00 2001 From: Banoffee Date: Tue, 30 Sep 2025 21:10:34 +0300 Subject: [PATCH 1/4] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BE=20=D0=B2=D0=B5=D1=80=D1=81?= =?UTF-8?q?=D0=B8=D0=B8=201.0.3:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D0=BA=D0=B8=D1=85=20=D1=8F=D0=B7?= =?UTF-8?q?=D1=8B=D0=BA=D0=BE=D0=B2=D1=8B=D1=85=20=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2,=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=20?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B5=D0=B4=D0=B6=D0=B5=D1=80=20=D1=8F=D0=B7?= =?UTF-8?q?=D1=8B=D0=BA=D0=BE=D0=B2,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20GitHub=20Actions=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D0=B7?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D1=81?= =?UTF-8?q?=D0=B1=D0=BE=D1=80=D0=BE=D0=BA=20=D0=B8=20=D1=80=D0=B5=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=BE=D0=B2,=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B8=20CHANGELOG.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 26 +++ .github/workflows/build.yml | 42 +++++ .github/workflows/quality-check.yml | 41 +++++ .github/workflows/release.yml | 67 ++++++++ CHANGELOG.md | 21 +++ CONTRIBUTING.md | 149 ++++++++++++++++++ README.md | 24 ++- RELEASE_GUIDE.md | 113 +++++++++++++ build.gradle.kts | 4 +- modrinth.md | 17 +- .../java/com/sleapplugin/SleepPlugin.java | 32 +++- src/main/resources/config.yml | 4 +- src/main/resources/lang/en_EN.yml | 2 +- src/main/resources/lang/ru_RU.yml | 2 +- src/main/resources/lang/template.yml | 35 ++++ 15 files changed, 561 insertions(+), 18 deletions(-) create mode 100644 .gitattributes create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/quality-check.yml create mode 100644 .github/workflows/release.yml create mode 100644 CONTRIBUTING.md create mode 100644 RELEASE_GUIDE.md create mode 100644 src/main/resources/lang/template.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c709cbd --- /dev/null +++ b/.gitattributes @@ -0,0 +1,26 @@ +# Auto detect text files and normalize line endings to LF +* text=auto eol=lf + +# Explicitly declare text files +*.java text +*.yml text +*.yaml text +*.md text +*.txt text +*.gradle text +*.kts text +*.properties text + +# Declare files that will always have CRLF line endings on checkout +*.bat text eol=crlf + +# Denote all files that are truly binary and should not be modified +*.jar binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.zip binary +*.tar binary +*.gz binary diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..edc20bc --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,42 @@ +name: Build SleepPlugin + +on: + push: + branches: [ master, main, develop ] + pull_request: + branches: [ master, main ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: 'gradle' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: ./gradlew build + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: SleepPlugin-${{ github.sha }} + path: build/libs/*.jar + retention-days: 30 + + - name: Display build info + run: | + echo "Build completed successfully!" + echo "Artifact location: build/libs/" + ls -lh build/libs/ diff --git a/.github/workflows/quality-check.yml b/.github/workflows/quality-check.yml new file mode 100644 index 0000000..48a359f --- /dev/null +++ b/.github/workflows/quality-check.yml @@ -0,0 +1,41 @@ +name: Code Quality Check + +on: + push: + branches: [ master, main, develop ] + pull_request: + branches: [ master, main ] + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: 'gradle' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Run Gradle check + run: ./gradlew check + + - name: Verify JAR can be built + run: ./gradlew jar + + - name: Check for Java warnings + run: ./gradlew compileJava --warning-mode all + + - name: Display results + if: always() + run: | + echo "Code quality check completed!" + echo "Build directory contents:" + ls -R build/ || echo "Build directory not found" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..de0bd5e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,67 @@ +name: Create Release + +on: + push: + tags: + - 'v*.*.*' + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: 'gradle' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: ./gradlew build + + - name: Get version from tag + id: get_version + run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT + + - name: Extract changelog for this version + id: changelog + run: | + # Extract changelog section for current version + VERSION=${{ steps.get_version.outputs.VERSION }} + CHANGELOG=$(sed -n "/## Version $VERSION/,/^## Version/p" CHANGELOG.md | sed '$d' | tail -n +2) + echo "CHANGELOG<> $GITHUB_OUTPUT + echo "$CHANGELOG" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + files: build/libs/*.jar + body: | + # SleepPlugin v${{ steps.get_version.outputs.VERSION }} + + ## Changes + ${{ steps.changelog.outputs.CHANGELOG }} + + ## Installation + 1. Download `SleepPlugin-${{ steps.get_version.outputs.VERSION }}.jar` + 2. Place in your server's `plugins/` folder + 3. Restart the server + + ## Requirements + - Minecraft: 1.21.5 + - Server: Paper (or compatible) + - Java: 21+ + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index bfd4cab..524ae61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # SleepPlugin Changelog +## Version 1.0.3 (2025-10-xx) + +### New Features +- Added support for custom language files - users can now create their own localizations beyond English and Russian +- Added `template.yml` language file template for easier translation creation +- Added GitHub Actions for automated builds and releases + +### Improvements +- Removed language file validation restrictions - any custom language file is now automatically supported +- Enhanced LanguageManager to dynamically load any .yml language file from the lang/ directory +- Added automated CI/CD pipeline with GitHub Actions +- Added build status badges to README + +### Technical Changes +- Language files are no longer restricted to en_EN and ru_RU only +- Plugin now accepts any valid language code format (e.g., de_DE, fr_FR, es_ES, etc.) +- Created three GitHub Actions workflows: build, release, and quality check +- Automated release creation when version tags are pushed + +--- + ## Version 1.0.2 (2025-05-25) ### New Features diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0f49160 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,149 @@ +# Contributing to SleepPlugin + +Thank you for your interest in contributing to SleepPlugin! This document provides guidelines for contributing to the project. + +## How to Contribute + +### Reporting Bugs + +If you find a bug, please open an issue on GitHub with: +- A clear, descriptive title +- Steps to reproduce the issue +- Expected behavior vs actual behavior +- Your server version, plugin version, and Java version +- Any relevant logs or error messages + +### Suggesting Features + +Feature suggestions are welcome! Please open an issue with: +- A clear description of the feature +- Why this feature would be useful +- Any implementation ideas (optional) + +### Pull Requests + +1. **Fork the repository** and create your branch from `master` +2. **Make your changes** following the code style guidelines below +3. **Test your changes** on a local Paper server +4. **Update documentation** if needed (README.md, CHANGELOG.md) +5. **Commit your changes** with clear, descriptive commit messages +6. **Push to your fork** and submit a pull request + +## Code Style Guidelines + +### Java Code Style + +- **Indentation**: 4 spaces (no tabs) +- **Naming conventions**: + - Classes: `PascalCase` + - Methods: `camelCase` + - Variables: `camelCase` + - Constants: `UPPER_SNAKE_CASE` +- **Braces**: Opening brace on same line +- **Comments**: Use Javadoc for public methods, inline comments for complex logic +- **Line length**: Try to keep lines under 120 characters + +Example: +```java +public class MyClass { + private static final int MAX_VALUE = 100; + private String myVariable; + + /** + * Does something useful + * @param input the input parameter + * @return the result + */ + public String doSomething(String input) { + if (input == null) { + return null; + } + return input.toUpperCase(); + } +} +``` + +### Configuration Files + +- **YAML files**: Use 2 spaces for indentation +- **Comments**: Add comments for complex configurations +- **Keys**: Use `kebab-case` for multi-word keys + +### Commit Messages + +Write clear, descriptive commit messages: +- Use present tense ("Add feature" not "Added feature") +- Keep first line under 50 characters +- Add detailed description after blank line if needed + +Good examples: +``` +Add storm skip functionality +Fix null pointer in bed leave event +Update documentation for custom languages +``` + +## Development Setup + +1. **Prerequisites**: + - Java 21 or higher + - Gradle 8.x (wrapper included) + - A Paper 1.21.5 test server + +2. **Clone and build**: + ```bash + git clone https://github.com/NovaDAndrew/sleep-plugin.git + cd sleep-plugin + ./gradlew build + ``` + +3. **Test**: + - Copy `build/libs/SleepPlugin-*.jar` to your test server's `plugins/` folder + - Start the server and test your changes + - Check console for errors + +## Testing Guidelines + +Before submitting a pull request, test: +- Plugin loads without errors +- All features work as expected +- No console errors or warnings +- Config updates correctly +- Language files load properly +- Multi-world support works +- Edge cases (1 player, odd numbers, etc.) + +## Adding Translations + +To add a new language: + +1. Copy `src/main/resources/lang/template.yml` +2. Rename to your language code (e.g., `de_DE.yml`) +3. Translate all message strings +4. Test by setting `language: de_DE` in config.yml +5. Submit a pull request with your translation + +## Documentation + +When making changes that affect: +- **User-facing features**: Update README.md and modrinth.md +- **Configuration**: Update config examples in documentation +- **Breaking changes**: Add migration notes to CHANGELOG.md + +## Questions? + +If you have questions about contributing: +- Open a discussion on GitHub +- Check existing issues and pull requests +- Contact the maintainer: NovaDAndrew + +## Code of Conduct + +- Be respectful and constructive +- Focus on the code, not the person +- Accept constructive criticism gracefully +- Help others learn and grow + +## License + +By contributing, you agree that your contributions will be licensed under the MIT License. diff --git a/README.md b/README.md index fe2bf49..7f93fc8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # SleepPlugin +[![Build](https://github.com/NovaDAndrew/sleep-plugin/actions/workflows/build.yml/badge.svg)](https://github.com/NovaDAndrew/sleep-plugin/actions/workflows/build.yml) +[![Code Quality](https://github.com/NovaDAndrew/sleep-plugin/actions/workflows/quality-check.yml/badge.svg)](https://github.com/NovaDAndrew/sleep-plugin/actions/workflows/quality-check.yml) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Modrinth](https://img.shields.io/modrinth/dt/sleep-plugin?label=Modrinth&logo=modrinth)](https://modrinth.com/plugin/sleep-plugin) + Minecraft Paper 1.21.х plugin for enhanced sleep mechanics - only half of online players need to sleep to skip the night. ## Features @@ -12,7 +17,7 @@ Minecraft Paper 1.21.х plugin for enhanced sleep mechanics - only half of onlin - Smooth time transition from night to morning - Configuration update system (preserves settings during updates) - Multi-world support -- Multi-language support (English and Russian) +- Multi-language support (English, Russian, and custom languages) ## Examples @@ -30,7 +35,7 @@ Minecraft Paper 1.21.х plugin for enhanced sleep mechanics - only half of onlin ## Installation -1. Download `SleepPlugin-1.0.2.jar` +1. Download `SleepPlugin-1.0.3.jar` 2. Place in server's `plugins` folder 3. Restart server @@ -41,7 +46,7 @@ After first server start with the plugin, a configuration file will be created a ```yaml # SleepPlugin Configuration # Do not change this version number manually -version: "1.0.2" +version: "1.0.3" language: en_EN skip-delay: 3 @@ -75,6 +80,19 @@ storm-settings: - `storm-settings`: Settings for the storm skipping feature - `skip-storms`: When true, players can skip storms by sleeping +## Custom Language Files + +You can create your own language translations by: + +1. Navigate to `plugins/SleepPlugin/lang/` +2. Copy `en_EN.yml` or `ru_RU.yml` as a template +3. Rename it to your language code (e.g., `de_DE.yml`, `fr_FR.yml`, `es_ES.yml`) +4. Translate all message strings in the file +5. Set `language: de_DE` (or your language code) in `config.yml` +6. Restart the server + +The plugin will automatically detect and load any custom language file you create! + ## Building 1. Install Java 21+ diff --git a/RELEASE_GUIDE.md b/RELEASE_GUIDE.md new file mode 100644 index 0000000..5876e95 --- /dev/null +++ b/RELEASE_GUIDE.md @@ -0,0 +1,113 @@ +# Release Guide for SleepPlugin + +This document describes how to create a new release of SleepPlugin. + +## Automated Release Process + +The plugin uses GitHub Actions for automated builds and releases. + +### Creating a New Release + +1. **Update Version Numbers** + - Update version in `build.gradle.kts` (2 places: `version` and `paper.version`) + - Update version in `src/main/resources/config.yml` + - Update version in `src/main/resources/lang/en_EN.yml` + - Update version in `src/main/resources/lang/ru_RU.yml` + - Update constant `PLUGIN_VERSION` in `SleepPlugin.java` + - Update version in `displayPluginInfo()` method + +2. **Update Documentation** + - Add new version section to `CHANGELOG.md` + - Update version references in `README.md` + - Update version references in `modrinth.md` + +3. **Commit Changes** + ```bash + git add . + git commit -m "Release version 1.0.3" + git push origin master + ``` + +4. **Create and Push Tag** + ```bash + git tag v1.0.3 + git push origin v1.0.3 + ``` + +5. **Automatic Actions** + - GitHub Actions will automatically build the plugin + - A GitHub Release will be created with the JAR file + - Release notes will be extracted from CHANGELOG.md + +## Manual Build + +If you need to build manually: + +```bash +# Clone repository +git clone https://github.com/NovaDAndrew/sleep-plugin.git +cd sleep-plugin + +# Build with Gradle +./gradlew build + +# Find the JAR file +ls build/libs/ +``` + +## GitHub Actions Workflows + +### build.yml +- Triggers on: push to master/main/develop, pull requests +- Actions: Builds the plugin and uploads artifacts +- Retention: 30 days + +### release.yml +- Triggers on: version tags (v*.*.*) +- Actions: + - Builds the plugin + - Creates GitHub Release + - Uploads JAR file + - Extracts changelog from CHANGELOG.md + +### quality-check.yml +- Triggers on: push to master/main/develop, pull requests +- Actions: + - Runs Gradle check + - Verifies JAR compilation + - Checks for Java warnings + +## Versioning Scheme + +SleepPlugin follows Semantic Versioning (SemVer): +- **MAJOR** version (1.x.x): Breaking changes or major rewrites +- **MINOR** version (x.1.x): New features, backwards compatible +- **PATCH** version (x.x.1): Bug fixes, backwards compatible + +Example: `v1.0.3` + +## Post-Release Checklist + +After creating a release: +- [ ] Verify GitHub Release is created successfully +- [ ] Download and test the released JAR file +- [ ] Update Modrinth page if needed +- [ ] Announce the release in relevant communities +- [ ] Update documentation if needed + +## Troubleshooting + +### Build Fails on GitHub Actions +- Check Java version (must be 21+) +- Verify gradlew has execute permissions +- Check for syntax errors in build.gradle.kts + +### Release Not Created +- Verify tag format is correct (v*.*.*) +- Check GITHUB_TOKEN permissions +- Ensure CHANGELOG.md has the version section + +### JAR File Missing from Release +- Check build logs for errors +- Verify build/libs/ directory contains the JAR +- Ensure the workflow has write permissions diff --git a/build.gradle.kts b/build.gradle.kts index 170708c..93c90a0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } group = "com.sleapplugin" -version = "1.0.2" +version = "1.0.3" description = "A plugin that allows night skip with half of online players" repositories { @@ -26,7 +26,7 @@ java { paper { main = "com.sleapplugin.SleepPlugin" name = "SleepPlugin" - version = "1.0.2" + version = "1.0.3" description = "A plugin that allows night skip with half of online players" apiVersion = "1.21" author = "NovaDAndrew" //Puer33 minecraft nickname diff --git a/modrinth.md b/modrinth.md index 95e9e02..b8e75e1 100644 --- a/modrinth.md +++ b/modrinth.md @@ -12,7 +12,7 @@ Minecraft Paper 1.21.x plugin for enhanced sleep mechanics - only half of online - Smooth time transition from night to morning - Configuration update system (preserves settings during updates) - Multi-world support -- Multi-language support (English and Russian) +- Multi-language support (English, Russian, and custom languages) ## Examples @@ -29,7 +29,7 @@ After first server start with the plugin, a configuration file will be created a ```yaml # SleepPlugin Configuration # Do not change this version number manually -version: "1.0.2" +version: "1.0.3" language: en_EN skip-delay: 3 @@ -62,3 +62,16 @@ storm-settings: - `steps`: Number of intermediate steps (higher = smoother) - `storm-settings`: Settings for the storm skipping feature - `skip-storms`: When true, players can skip storms by sleeping + +## Custom Language Files + +You can create your own language translations: + +1. Navigate to `plugins/SleepPlugin/lang/` +2. Copy `en_EN.yml` or `ru_RU.yml` as a template +3. Rename to your language code (e.g., `de_DE.yml`, `fr_FR.yml`) +4. Translate all message strings +5. Set `language: de_DE` in `config.yml` +6. Restart server + +The plugin automatically detects all custom language files! diff --git a/src/main/java/com/sleapplugin/SleepPlugin.java b/src/main/java/com/sleapplugin/SleepPlugin.java index dd1df61..61762ee 100644 --- a/src/main/java/com/sleapplugin/SleepPlugin.java +++ b/src/main/java/com/sleapplugin/SleepPlugin.java @@ -39,7 +39,7 @@ public class SleepPlugin extends JavaPlugin implements Listener { private static final long PROGRESS_MESSAGE_COOLDOWN = 3000; - private static final String PLUGIN_VERSION = "1.0.2"; + private static final String PLUGIN_VERSION = "1.0.3"; @Override public void onEnable() { @@ -77,19 +77,37 @@ public void onEnable() { } private void updateLanguageFiles(ConfigUpdater configUpdater) { - String[] supportedLanguages = {"en_EN", "ru_RU"}; - File langDir = new File(getDataFolder(), "lang"); if (!langDir.exists()) { langDir.mkdirs(); } - - for (String langCode : supportedLanguages) { + String[] bundledLanguages = {"en_EN", "ru_RU"}; + for (String langCode : bundledLanguages) { boolean updated = configUpdater.updateLanguageFile(langCode); if (updated) { getLogger().info("Language file " + langCode + ".yml has been updated to v" + PLUGIN_VERSION); } } + + File[] langFiles = langDir.listFiles((dir, name) -> name.endsWith(".yml")); + if (langFiles != null) { + for (File langFile : langFiles) { + String fileName = langFile.getName(); + String langCode = fileName.replace(".yml", ""); + + boolean isBundled = false; + for (String bundled : bundledLanguages) { + if (bundled.equals(langCode)) { + isBundled = true; + break; + } + } + + if (!isBundled) { + getLogger().info("Found custom language file: " + langCode + ".yml"); + } + } + } } @Override @@ -383,7 +401,7 @@ private void displayPluginInfo() { String[] infoLines = { "\n", " ╔═════════════════════════════════════════════════════╗", - " ║ SleepPlugin v1.0.2 ║", + " ║ SleepPlugin v1.0.3 ║", " ╠═════════════════════════════════════════════════════╣", " ║ Author: NovaDAndrew ║", " ║ Modrinth: https://modrinth.com/plugin/sleep-plugin ║", @@ -394,7 +412,7 @@ private void displayPluginInfo() { " ║ • Multiple message modes (normal/minimal/silent) ║", " ║ • Configurable minimum player requirement ║", " ║ • Smooth time transition (day/night) ║", - " ║ • Multi-language support (EN/RU) ║", + " ║ • Multi-language support (EN/RU + custom langs) ║", " ╚═════════════════════════════════════════════════════╝", "" }; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 86cb730..57083de 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,8 +1,8 @@ # SleepPlugin Configuration # Do not change this version number manually -version: "1.0.2" +version: "1.0.3" -language: en_EN # Default language, can be ru_RU or en_EN +language: en_EN # Default language: en_EN, ru_RU, or any custom language code skip-delay: 3 # Delay in seconds before skipping night morning-time: 1000 # Time to set when skipping to morning message-mode: normal # Message mode options: normal, minimal, silent diff --git a/src/main/resources/lang/en_EN.yml b/src/main/resources/lang/en_EN.yml index 12d5019..09f9346 100644 --- a/src/main/resources/lang/en_EN.yml +++ b/src/main/resources/lang/en_EN.yml @@ -1,5 +1,5 @@ # Do not change this version number manually -version: "1.0.2" +version: "1.0.3" plugin_enabled: "SleepPlugin enabled! Now only half of the players are needed to skip the night." plugin_disabled: "SleepPlugin disabled!" diff --git a/src/main/resources/lang/ru_RU.yml b/src/main/resources/lang/ru_RU.yml index 5ec8b77..33a07c3 100644 --- a/src/main/resources/lang/ru_RU.yml +++ b/src/main/resources/lang/ru_RU.yml @@ -1,5 +1,5 @@ # Не изменяйте этот номер версии вручную -version: "1.0.2" +version: "1.0.3" plugin_enabled: "SleepPlugin включен! Теперь для пропуска ночи нужна только половина игроков." plugin_disabled: "SleepPlugin отключен!" diff --git a/src/main/resources/lang/template.yml b/src/main/resources/lang/template.yml new file mode 100644 index 0000000..711cbb4 --- /dev/null +++ b/src/main/resources/lang/template.yml @@ -0,0 +1,35 @@ +# Language Template for SleepPlugin +# Copy this file and rename it to your language code (e.g., de_DE.yml, fr_FR.yml, es_ES.yml) +# Translate all the messages below to your language +# Do not change the keys (text before the colon), only translate the values (text after the colon) +# Use %d for numbers and %s for text placeholders - keep them in your translations + +# Do not change this version number manually +version: "1.0.3" + +# Basic plugin messages +plugin_enabled: "SleepPlugin enabled! Now only half of the players are needed to skip the night." +plugin_disabled: "SleepPlugin disabled!" +config_updated: "Configuration updated from v%s to v%s. Added %d new settings." + +# Sleep progress messages (normal mode) +sleep_progress: "Sleeping %d of %d players required to skip the night" +sleep_countdown: "Skipping night in %d seconds... (%d/%d players sleeping)" +sleep_canceled: "Night skip canceled - player woke up!" +sleep_success: "Night skipped! Good morning!" +sleep_skipping_smooth: "Skipping night..." + +# Sleep messages (minimal mode) +sleep_countdown_minimal: "Skipping night (%d/%d)" +sleep_canceled_minimal: "Skip canceled" +sleep_success_minimal: "Morning!" +sleep_skipping_smooth_minimal: "Skipping..." + +# Storm messages (normal mode) +storm_progress: "Sleeping %d of %d players required to clear the storm" +storm_countdown: "Clearing storm in %d seconds... (%d/%d players sleeping)" +storm_success: "Storm cleared! The skies are clear again!" + +# Storm messages (minimal mode) +storm_countdown_minimal: "Clearing storm (%d/%d)" +storm_success_minimal: "Storm cleared!" From d914638831616d9e2f60c089ca8570ea9c7b85e0 Mon Sep 17 00:00:00 2001 From: Banoffee Date: Tue, 30 Sep 2025 22:52:02 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA?= =?UTF-8?q?=D0=B0=20Spigot=20=D0=B8=20Paper=20=D1=81=D0=B5=D1=80=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D0=BE=D0=B2=20=D0=BE=D0=B4=D0=BD=D0=BE=D0=B2=D1=80?= =?UTF-8?q?=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D0=BE.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 36 ++++++- gradlew | 0 .../java/com/sleapplugin/MessageUtil.java | 93 +++++++++++++++++++ .../java/com/sleapplugin/SleepPlugin.java | 16 ++-- 4 files changed, 134 insertions(+), 11 deletions(-) mode change 100644 => 100755 gradlew create mode 100644 src/main/java/com/sleapplugin/MessageUtil.java diff --git a/build.gradle.kts b/build.gradle.kts index 93c90a0..c347b45 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ plugins { java - id("net.minecrell.plugin-yml.paper") version "0.6.0" + id("net.minecrell.plugin-yml.bukkit") version "0.6.0" + id("com.github.johnrengelman.shadow") version "8.1.1" } group = "com.sleapplugin" @@ -13,17 +14,36 @@ repositories { name = "papermc" url = uri("https://repo.papermc.io/repository/maven-public/") } + maven { + name = "spigotmc" + url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") + } + maven { + name = "sonatype" + url = uri("https://oss.sonatype.org/content/repositories/snapshots") + } + maven { + name = "sonatype-central" + url = uri("https://oss.sonatype.org/content/repositories/central") + } +} + +configurations { + create("paperApi") + create("spigotApi") } dependencies { compileOnly("io.papermc.paper:paper-api:1.21.5-R0.1-SNAPSHOT") + "paperApi"("io.papermc.paper:paper-api:1.21.5-R0.1-SNAPSHOT") + "spigotApi"("org.spigotmc:spigot-api:1.21.5-R0.1-SNAPSHOT") } java { toolchain.languageVersion.set(JavaLanguageVersion.of(21)) } -paper { +bukkit { main = "com.sleapplugin.SleepPlugin" name = "SleepPlugin" version = "1.0.3" @@ -37,4 +57,16 @@ paper { default = net.minecrell.pluginyml.bukkit.BukkitPluginDescription.Permission.Default.OP } } +} + +tasks { + jar { + manifest { + attributes( + "Implementation-Title" to project.name, + "Implementation-Version" to project.version, + "Implementation-Vendor" to "NovaDAndrew" + ) + } + } } \ No newline at end of file diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/java/com/sleapplugin/MessageUtil.java b/src/main/java/com/sleapplugin/MessageUtil.java new file mode 100644 index 0000000..a7a5369 --- /dev/null +++ b/src/main/java/com/sleapplugin/MessageUtil.java @@ -0,0 +1,93 @@ +package com.sleapplugin; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +public class MessageUtil { + + private static Boolean isPaperServer = null; + + private static boolean isPaper() { + if (isPaperServer == null) { + try { + Class.forName("net.kyori.adventure.text.Component"); + isPaperServer = true; + } catch (ClassNotFoundException e) { + isPaperServer = false; + } + } + return isPaperServer; + } + + public static void sendMessage(Player player, String message, MessageColor color) { + if (isPaper()) { + sendPaperMessage(player, message, color); + } else { + sendSpigotMessage(player, message, color); + } + } + + private static void sendPaperMessage(Player player, String message, MessageColor color) { + try { + Class componentClass = Class.forName("net.kyori.adventure.text.Component"); + Class namedTextColorClass = Class.forName("net.kyori.adventure.text.format.NamedTextColor"); + Class textColorClass = Class.forName("net.kyori.adventure.text.format.TextColor"); + + Object textComponent = componentClass.getMethod("text", String.class) + .invoke(null, message); + + Object colorValue = null; + switch (color) { + case YELLOW: + colorValue = namedTextColorClass.getField("YELLOW").get(null); + break; + case GREEN: + colorValue = namedTextColorClass.getField("GREEN").get(null); + break; + case GOLD: + colorValue = namedTextColorClass.getField("GOLD").get(null); + break; + case WHITE: + colorValue = namedTextColorClass.getField("WHITE").get(null); + break; + } + + if (colorValue != null) { + textComponent = componentClass.getMethod("color", textColorClass) + .invoke(textComponent, colorValue); + } + + player.getClass().getMethod("sendMessage", componentClass) + .invoke(player, textComponent); + } catch (Exception e) { + sendSpigotMessage(player, message, color); + } + } + + private static void sendSpigotMessage(Player player, String message, MessageColor color) { + ChatColor chatColor; + switch (color) { + case YELLOW: + chatColor = ChatColor.YELLOW; + break; + case GREEN: + chatColor = ChatColor.GREEN; + break; + case GOLD: + chatColor = ChatColor.GOLD; + break; + case WHITE: + default: + chatColor = ChatColor.WHITE; + break; + } + player.sendMessage(chatColor + message); + } + + public enum MessageColor { + YELLOW, + GREEN, + GOLD, + WHITE + } +} diff --git a/src/main/java/com/sleapplugin/SleepPlugin.java b/src/main/java/com/sleapplugin/SleepPlugin.java index 61762ee..3ac6d3d 100644 --- a/src/main/java/com/sleapplugin/SleepPlugin.java +++ b/src/main/java/com/sleapplugin/SleepPlugin.java @@ -9,8 +9,6 @@ import org.bukkit.event.player.PlayerBedLeaveEvent; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; import java.io.File; import java.util.HashMap; @@ -170,7 +168,7 @@ public void onPlayerBedLeave(PlayerBedLeaveEvent event) { if (!messageMode.equals("silent")) { String messageKey = messageMode.equals("minimal") ? "sleep_canceled_minimal" : "sleep_canceled"; - broadcastToWorld(world, Component.text(lang.getMessage(messageKey), NamedTextColor.YELLOW)); + broadcastToWorld(world, lang.getMessage(messageKey), MessageUtil.MessageColor.YELLOW); } } } @@ -254,7 +252,7 @@ private void startNightSkip(World world, int sleepingCount, int totalCount) { message = lang.getMessage(messageKey, skipDelay, sleepingCount, totalCount); } - broadcastToWorld(world, Component.text(message, NamedTextColor.GREEN)); + broadcastToWorld(world, message, MessageUtil.MessageColor.GREEN); } } @@ -317,7 +315,7 @@ public void run() { baseKey + "_success_minimal" : baseKey + "_success"; } - broadcastToWorld(world, Component.text(lang.getMessage(messageKey), NamedTextColor.GOLD)); + broadcastToWorld(world, lang.getMessage(messageKey), MessageUtil.MessageColor.GOLD); } } } @@ -357,16 +355,15 @@ private boolean isNight(World world) { return time >= 12541 && time <= 23458; } - private void broadcastToWorld(World world, Component message) { + private void broadcastToWorld(World world, String message, MessageUtil.MessageColor color) { for (Player player : world.getPlayers()) { - player.sendMessage(message); + MessageUtil.sendMessage(player, message, color); } } private void sendMessageToWorld(World world, String message) { - Component component = Component.text(message); for (Player player : world.getPlayers()) { - player.sendMessage(component); + MessageUtil.sendMessage(player, message, MessageUtil.MessageColor.WHITE); } } @@ -413,6 +410,7 @@ private void displayPluginInfo() { " ║ • Configurable minimum player requirement ║", " ║ • Smooth time transition (day/night) ║", " ║ • Multi-language support (EN/RU + custom langs) ║", + " ║ • Compatible with both Paper and Spigot servers ║", " ╚═════════════════════════════════════════════════════╝", "" }; From 0a0e90fbb9f45ffe4973aa98c2afcb324d2808fa Mon Sep 17 00:00:00 2001 From: Banoffee Date: Tue, 30 Sep 2025 23:18:49 +0300 Subject: [PATCH 3/4] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=20=D1=82?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D1=82=D0=B0=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sleapplugin/SleepPlugin.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/sleapplugin/SleepPlugin.java b/src/main/java/com/sleapplugin/SleepPlugin.java index 3ac6d3d..fc1fa45 100644 --- a/src/main/java/com/sleapplugin/SleepPlugin.java +++ b/src/main/java/com/sleapplugin/SleepPlugin.java @@ -397,21 +397,21 @@ private void smoothlySetTime(World world, long targetTime) { private void displayPluginInfo() { String[] infoLines = { "\n", - " ╔═════════════════════════════════════════════════════╗", - " ║ SleepPlugin v1.0.3 ║", - " ╠═════════════════════════════════════════════════════╣", - " ║ Author: NovaDAndrew ║", - " ║ Modrinth: https://modrinth.com/plugin/sleep-plugin ║", - " ║ GitHub: https://github.com/NovaDAndrew/sleep-plugin║", - " ╠═════════════════════════════════════════════════════╣", - " ║ Features: ║", - " ║ • Skip night with only half of players sleeping ║", - " ║ • Multiple message modes (normal/minimal/silent) ║", - " ║ • Configurable minimum player requirement ║", - " ║ • Smooth time transition (day/night) ║", - " ║ • Multi-language support (EN/RU + custom langs) ║", - " ║ • Compatible with both Paper and Spigot servers ║", - " ╚═════════════════════════════════════════════════════╝", + " ╔═════════════════════════════════════════════════════════╗", + " ║ SleepPlugin v1.0.3 ║", + " ╠═════════════════════════════════════════════════════════╣", + " ║ Author: NovaDAndrew ║", + " ║ Modrinth: https://modrinth.com/plugin/sleep-plugin ║", + " ║ GitHub: https://github.com/NovaDAndrew/sleep-plugin ║", + " ╠═════════════════════════════════════════════════════════╣", + " ║ Features: ║", + " ║ • Skip night with only half of players sleeping ║", + " ║ • Multiple message modes (normal/minimal/silent) ║", + " ║ • Configurable minimum player requirement ║", + " ║ • Smooth time transition (day/night) ║", + " ║ • Multi-language support (EN/RU + custom langs) ║", + " ║ • Compatible with both Paper and Spigot servers ║", + " ╚═════════════════════════════════════════════════════════╝", "" }; From 60c57fa4f9f8181c2834e221e934f22eeb64e438 Mon Sep 17 00:00:00 2001 From: Banoffee Date: Tue, 30 Sep 2025 23:23:53 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D0=B0=20=D1=8F=D0=B7?= =?UTF-8?q?=D1=8B=D0=BA=D0=B0=20=D0=BF=D1=80=D0=B8=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D1=83=D1=81=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++- modrinth.md | 4 +++- src/main/java/com/sleapplugin/SleepPlugin.java | 10 +++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7f93fc8..f22914b 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ storm-settings: You can create your own language translations by: 1. Navigate to `plugins/SleepPlugin/lang/` -2. Copy `en_EN.yml` or `ru_RU.yml` as a template +2. Copy `template.yml` (automatically created on first run) or `en_EN.yml`/`ru_RU.yml` as a template 3. Rename it to your language code (e.g., `de_DE.yml`, `fr_FR.yml`, `es_ES.yml`) 4. Translate all message strings in the file 5. Set `language: de_DE` (or your language code) in `config.yml` @@ -93,6 +93,8 @@ You can create your own language translations by: The plugin will automatically detect and load any custom language file you create! +**Note:** `template.yml` is created automatically on first plugin startup with helpful comments for translation. + ## Building 1. Install Java 21+ diff --git a/modrinth.md b/modrinth.md index b8e75e1..adf57e5 100644 --- a/modrinth.md +++ b/modrinth.md @@ -68,10 +68,12 @@ storm-settings: You can create your own language translations: 1. Navigate to `plugins/SleepPlugin/lang/` -2. Copy `en_EN.yml` or `ru_RU.yml` as a template +2. Copy `template.yml` as a template 3. Rename to your language code (e.g., `de_DE.yml`, `fr_FR.yml`) 4. Translate all message strings 5. Set `language: de_DE` in `config.yml` 6. Restart server The plugin automatically detects all custom language files! + +**Tip:** Use `template.yml` - it has helpful comments for translators. diff --git a/src/main/java/com/sleapplugin/SleepPlugin.java b/src/main/java/com/sleapplugin/SleepPlugin.java index fc1fa45..a195e17 100644 --- a/src/main/java/com/sleapplugin/SleepPlugin.java +++ b/src/main/java/com/sleapplugin/SleepPlugin.java @@ -79,6 +79,13 @@ private void updateLanguageFiles(ConfigUpdater configUpdater) { if (!langDir.exists()) { langDir.mkdirs(); } + + File templateFile = new File(langDir, "template.yml"); + if (!templateFile.exists()) { + saveResource("lang/template.yml", false); + getLogger().info("Created template.yml for custom translations"); + } + String[] bundledLanguages = {"en_EN", "ru_RU"}; for (String langCode : bundledLanguages) { boolean updated = configUpdater.updateLanguageFile(langCode); @@ -101,7 +108,8 @@ private void updateLanguageFiles(ConfigUpdater configUpdater) { } } - if (!isBundled) { + // Skip template file + if (!isBundled && !langCode.equals("template")) { getLogger().info("Found custom language file: " + langCode + ".yml"); } }