From dcff9c656d2f66f10c11d4e1e7a33adce56ef9f4 Mon Sep 17 00:00:00 2001 From: Adrian Victor Date: Sat, 30 May 2026 20:35:24 -0300 Subject: [PATCH] initial --- .gitattributes | 11 + .gitignore | 21 + build.gradle.kts | 34 ++ gitignroe | 16 + gradle.properties | 6 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 48966 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 248 +++++++++++ gradlew.bat | 93 ++++ settings.gradle.kts | 1 + .../sweetdreams/Configuration.java | 46 ++ .../sweetdreams/EventListener.java | 122 ++++++ .../sweetdreams/PlayerStorage.java | 140 ++++++ .../sweetdreams/SkyIslandsGenerator.java | 398 ++++++++++++++++++ .../sweetdreams/SkylandsBlockPopulator.java | 22 + .../adrianvictor/sweetdreams/SweetDreams.java | 86 ++++ src/main/resources/config.yml | 0 src/main/resources/playerstorage.yml | 0 src/main/resources/plugin.yml | 11 + 19 files changed, 1262 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 build.gradle.kts create mode 100644 gitignroe create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle.kts create mode 100644 src/main/java/org/adrianvictor/sweetdreams/Configuration.java create mode 100644 src/main/java/org/adrianvictor/sweetdreams/EventListener.java create mode 100644 src/main/java/org/adrianvictor/sweetdreams/PlayerStorage.java create mode 100644 src/main/java/org/adrianvictor/sweetdreams/SkyIslandsGenerator.java create mode 100644 src/main/java/org/adrianvictor/sweetdreams/SkylandsBlockPopulator.java create mode 100644 src/main/java/org/adrianvictor/sweetdreams/SweetDreams.java create mode 100644 src/main/resources/config.yml create mode 100644 src/main/resources/playerstorage.yml create mode 100644 src/main/resources/plugin.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a87d264 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + +# Binary files should be left untouched +*.jar binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e4b940 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# MacOS DS_Store files +.DS_Store + +# Gradle cache folder +.gradle + +# Gradle build folder +build + +# IntelliJ +out/ +.idea +*.iml +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Common working directory +run diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..2eecf08 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,34 @@ +plugins { + id("java-library") + id("xyz.jpenilla.run-paper") version "3.0.2" +} + +repositories { + mavenCentral() + maven("https://repo.papermc.io/repository/maven-public/") +} + +dependencies { + compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT") +} + +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks { + runServer { + // Configure the Minecraft version for our task. + // This is the only required configuration besides applying the plugin. + // Your plugin's jar (or shadowJar if present) will be used automatically. + minecraftVersion("1.21.11") + jvmArgs("-Xms2G", "-Xmx2G") + } + + processResources { + val props = mapOf("version" to version, "description" to project.description) + filesMatching("plugin.yml") { + expand(props) + } + } +} diff --git a/gitignroe b/gitignroe new file mode 100644 index 0000000..f0201c9 --- /dev/null +++ b/gitignroe @@ -0,0 +1,16 @@ +bin/ +libs/ +.idea/ +.gradle/ +build/ +out/ + +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + +run/ + +*.log diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..844b80e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,6 @@ +group=org.adrianvictor +version=1.0-SNAPSHOT +description=Take your players to the dreamland when sleeping! +org.gradle.configuration-cache=true +org.gradle.parallel=true +org.gradle.caching=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..d997cfc60f4cff0e7451d19d49a82fa986695d07 GIT binary patch literal 48966 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 Tl?|j_nL(N10jR&X5yS%kg~hF! literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..5dd3c01 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..0262dcb --- /dev/null +++ b/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..c4bdd3a --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,93 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..e8f8129 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "SweetDreams" diff --git a/src/main/java/org/adrianvictor/sweetdreams/Configuration.java b/src/main/java/org/adrianvictor/sweetdreams/Configuration.java new file mode 100644 index 0000000..2a52b89 --- /dev/null +++ b/src/main/java/org/adrianvictor/sweetdreams/Configuration.java @@ -0,0 +1,46 @@ +package org.adrianvictor.sweetdreams; + +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; + +public class Configuration { + private final YamlConfiguration playerStorage = new YamlConfiguration(); + private final File playerStorageFile; + private final YamlConfiguration pluginConfig = new YamlConfiguration(); + private final File pluginConfigFile = new File(""); + private final SweetDreams plugin; + + public Configuration() { + plugin = SweetDreams.getPlugin(); + playerStorageFile = new File(plugin.getDataFolder(), "playerstorage.yml"); + + if (playerStorageFile.exists()) { + try { + playerStorage.load(playerStorageFile); + } catch (IOException | InvalidConfigurationException e) { + plugin.getLogger().severe("Error loading player storage: " + e.getMessage()); + throw new RuntimeException(e); + } + } + } + + public void savePlayerStorage() { + try { + playerStorage.save(playerStorageFile); + } catch (IOException e) { + plugin.getLogger().severe("Could not save to player storage: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + public YamlConfiguration getPlayerStorage() { + return playerStorage; + } + + public YamlConfiguration getPluginConfig() { + return pluginConfig; + } +} diff --git a/src/main/java/org/adrianvictor/sweetdreams/EventListener.java b/src/main/java/org/adrianvictor/sweetdreams/EventListener.java new file mode 100644 index 0000000..be2f9ac --- /dev/null +++ b/src/main/java/org/adrianvictor/sweetdreams/EventListener.java @@ -0,0 +1,122 @@ +package org.adrianvictor.sweetdreams; + +import com.destroystokyo.paper.event.player.PlayerSetSpawnEvent; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityPortalEnterEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerBedEnterEvent; +import org.bukkit.util.Vector; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +public class EventListener implements Listener { + private final PlayerStorage storage; + private final Set teleporting = new HashSet<>(); + + public EventListener() { + this.storage = SweetDreams.getPlugin().getStorage(); + } + + @EventHandler + public void onPlayerBedEnterEvent(PlayerBedEnterEvent event) { + if (event.getPlayer().getWorld() == SweetDreams.getPlugin().getWorld()) { + storage.savePlayerSpawnPoint(event.getPlayer()); + event.getPlayer().sendMessage("Respawn point set."); + event.setCancelled(true); + return; + } + + Long time = event.getPlayer().getWorld().getTime(); + + if (!(time >= 13000 && time <= 23000)) { + event.setCancelled(true); + return; + } + + teleport(event.getPlayer()); + + event.setCancelled(true); + } + + @EventHandler + public void onPlayerSetSpawn(PlayerSetSpawnEvent event) { + if (event.getPlayer().getWorld() != SweetDreams.getPlugin().getWorld()) + return; + + // TODO save player spawn point on dreamlands + + event.setCancelled(true); + } + + @EventHandler + public void onPortalEnter(EntityPortalEnterEvent event) { + if (event.getEntity().getWorld() == SweetDreams.getPlugin().getWorld()) + event.setCancelled(true); + } + + @EventHandler + public void onEntityDamage(EntityDamageEvent event) { + if (event.getEntity().getWorld() != SweetDreams.getPlugin().getWorld()) return; + if (event.getEntity() instanceof Player player) { + if (event.getCause() == EntityDamageEvent.DamageCause.VOID) { + teleport(player); + + player.setVelocity(new Vector(0, 0, 0)); + player.setFallDistance(0); + } + } + } + + @EventHandler + public void onPlayerDeath(PlayerDeathEvent event) { + if (event.getEntity().getWorld() != SweetDreams.getPlugin().getWorld()) return; + Player player = event.getPlayer(); + + teleport(player); + event.setCancelled(true); + } + + private void teleport(Player player) { + UUID uuid = player.getUniqueId(); + if (!teleporting.add(uuid)) return; + + Bukkit.getScheduler().runTask(SweetDreams.getPlugin(), () -> { + try { + World playerWorld = player.getWorld(); + + if (playerWorld == SweetDreams.getPlugin().getWorld()) { + storage.savePlayer(player, PlayerStorage.StorageWorldType.SKYLANDS); + + player.teleport(Objects.requireNonNullElse( + player.getRespawnLocation(), + Bukkit.getWorld("world").getSpawnLocation() + )); + player.getInventory().clear(); + + storage.loadPlayer(player, PlayerStorage.StorageWorldType.OVERWORLD); + + player.sendMessage("You woke up from a bad dream..."); + player.playSound(player.getLocation(), Sound.ENTITY_ENDER_DRAGON_DEATH, 1.0f, 1.0f); + } else { + World world = SweetDreams.getPlugin().getWorld(); + + storage.savePlayer(player, PlayerStorage.StorageWorldType.OVERWORLD); + player.getInventory().clear(); + player.teleport(storage.loadPlayer(player, PlayerStorage.StorageWorldType.SKYLANDS)); + } + } finally { + teleporting.remove(uuid); + } + }); + } +} diff --git a/src/main/java/org/adrianvictor/sweetdreams/PlayerStorage.java b/src/main/java/org/adrianvictor/sweetdreams/PlayerStorage.java new file mode 100644 index 0000000..fdcd206 --- /dev/null +++ b/src/main/java/org/adrianvictor/sweetdreams/PlayerStorage.java @@ -0,0 +1,140 @@ +package org.adrianvictor.sweetdreams; + +import org.bukkit.Location; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.UUID; + +public class PlayerStorage { + private final Configuration config; + private final YamlConfiguration storage; +// Map inventories = new HashMap<>(); + + public enum StorageWorldType { + OVERWORLD("overworld"), + SKYLANDS("skylands"); + + private final String key; + + StorageWorldType(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + } + + public PlayerStorage(Configuration config) { + this.config = config; + this.storage = config.getPlayerStorage(); + } + + public void savePlayer(Player player, StorageWorldType type) { + UUID uuid = player.getUniqueId(); + String base = "players." + uuid + "." + type.getKey(); + + ItemStack[] inv = player.getInventory().getContents(); + storage.set(base + ".inventory", null); + for (int i = 0; i < inv.length; i++) { + storage.set(base + ".inventory." + i, inv[i]); + } + + ItemStack[] armor = player.getInventory().getArmorContents(); + storage.set(base + ".armor", null); + for (int i = 0; i < armor.length; i++) { + storage.set(base + ".armor." + i, armor[i]); + } + + storage.set(base + ".offhand", player.getInventory().getItemInOffHand()); + + ItemStack[] ender = player.getEnderChest().getContents(); + storage.set(base + ".enderchest", null); + for (int i = 0; i < ender.length; i++) { + storage.set(base + ".enderchest." + i, ender[i]); + } + + storage.set(base + ".xp.level", player.getLevel()); + storage.set(base + ".xp.exp", player.getExp()); + storage.set(base + ".xp.total", player.getTotalExperience()); + + storage.set(base + ".stats.health", player.getHealth()); + storage.set(base + ".stats.food", player.getFoodLevel()); + storage.set(base + ".stats.saturation", player.getSaturation()); + + config.savePlayerStorage(); + } + + public Location loadPlayer(Player player, StorageWorldType type) { + UUID uuid = player.getUniqueId(); + String base = "players." + uuid + "." + type.getKey(); + + ItemStack[] inv = new ItemStack[36]; + var invSec = storage.getConfigurationSection(base + ".inventory"); + if (invSec != null) { + for (String key : invSec.getKeys(false)) { + try { + int slot = Integer.parseInt(key); + if (slot >= 0 && slot < inv.length) { + inv[slot] = storage.getItemStack(base + ".inventory." + key); + } + } catch (Exception ignored) {} + } + } + player.getInventory().setContents(inv); + + ItemStack[] armor = new ItemStack[4]; + var armorSec = storage.getConfigurationSection(base + ".armor"); + if (armorSec != null) { + for (String key : armorSec.getKeys(false)) { + try { + int slot = Integer.parseInt(key); + if (slot >= 0 && slot < armor.length) { + armor[slot] = storage.getItemStack(base + ".armor." + key); + } + } catch (Exception ignored) {} + } + } + player.getInventory().setArmorContents(armor); + + ItemStack offhand = storage.getItemStack(base + ".offhand"); + player.getInventory().setItemInOffHand(offhand); + + ItemStack[] ender = new ItemStack[27]; + var enderSec = storage.getConfigurationSection(base + ".enderchest"); + if (enderSec != null) { + for (String key : enderSec.getKeys(false)) { + try { + int slot = Integer.parseInt(key); + if (slot >= 0 && slot < ender.length) { + ender[slot] = storage.getItemStack(base + ".enderchest." + key); + } + } catch (Exception ignored) {} + } + } + player.getEnderChest().setContents(ender); + + player.setTotalExperience(storage.getInt(base + ".xp.total", 0)); + player.setLevel(storage.getInt(base + ".xp.level", 0)); + player.setExp((float) storage.getDouble(base + ".xp.exp", 0.0)); + + player.setHealth(Math.min(storage.getDouble(base + ".stats.health", 20.0), player.getMaxHealth())); + player.setFoodLevel(storage.getInt(base + ".stats.food", 20)); + player.setSaturation((float) storage.getDouble(base + ".stats.saturation", 5.0)); + + Object rawSpawn = storage.get(base + ".spawn"); + if (rawSpawn instanceof Location spawn) { + return spawn; + } else { + return SweetDreams.getPlugin().getWorld().getSpawnLocation(); + } + } + + public void savePlayerSpawnPoint(Player player) { + UUID uuid = player.getUniqueId(); + String base = "players." + uuid + ".skylands"; + storage.set(base + ".spawn", player.getLocation()); + } +} diff --git a/src/main/java/org/adrianvictor/sweetdreams/SkyIslandsGenerator.java b/src/main/java/org/adrianvictor/sweetdreams/SkyIslandsGenerator.java new file mode 100644 index 0000000..c9b3efe --- /dev/null +++ b/src/main/java/org/adrianvictor/sweetdreams/SkyIslandsGenerator.java @@ -0,0 +1,398 @@ +package org.adrianvictor.sweetdreams; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.ChunkGenerator; +import org.bukkit.generator.WorldInfo; +import org.jspecify.annotations.NonNull; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; + +public class SkyIslandsGenerator extends ChunkGenerator { + + private enum IslandType { + ROUND, + LONG, + ARCHIPELAGO, + SPIKY + } + + private static final IslandType[] TYPES = IslandType.values(); + + private record Blob(double x, double y, double z, double rx, double ry, double rz) {} + + private static final int CELL_SIZE = 30; + + private static final int MIN_RADIUS = 6; + private static final int MAX_RADIUS = 16; + + private static final int MIN_Y = 80; + private static final int MAX_Y = 180; + + private record LeafOffset(int dx, int dy, int dz) {} + + private static final LeafOffset[] LEAF_OFFSETS; + + static { + java.util.List offsets = new java.util.ArrayList<>(); + + for (int dx = -2; dx <= 2; dx++) { + for (int dz = -2; dz <= 2; dz++) { + for (int dy = -2; dy <= 0; dy++) { + + if (Math.abs(dx) + Math.abs(dz) <= 3) { + offsets.add(new LeafOffset(dx, dy, dz)); + } + } + } + } + + LEAF_OFFSETS = offsets.toArray(LeafOffset[]::new); + } + + @Override + public @NonNull List getDefaultPopulators(@NonNull World world) { + return Collections.singletonList(new SkylandsBlockPopulator()); + } + + @Override + public void generateSurface(WorldInfo worldInfo, @NonNull Random random, int chunkX, int chunkZ, @NonNull ChunkData chunkData) { + + long seed = worldInfo.getSeed(); + + int chunkWorldX = chunkX * 16; + int chunkWorldZ = chunkZ * 16; + + int cellX = Math.floorDiv(chunkWorldX, CELL_SIZE); + int cellZ = Math.floorDiv(chunkWorldZ, CELL_SIZE); + + short[][] highestY = new short[16][16]; + + AtomicBoolean hasTerrain = new AtomicBoolean(false); + + for (int x = 0; x < 16; x++) { + Arrays.fill(highestY[x], Short.MIN_VALUE); + } + + for (int gx = cellX - 2; gx <= cellX + 2; gx++) { + for (int gz = cellZ - 2; gz <= cellZ + 2; gz++) { + + SplittableRandom r = new SplittableRandom(hash(seed, gx, gz)); + if (r.nextDouble() > 0.8) { + continue; + } + + generateIslandGeometry( + gx, + gz, + r, + blob -> hasTerrain.set(hasTerrain.get() | carveBlob( + chunkData, + chunkX, + chunkZ, + blob, + highestY + )) + ); + + } + } + + if (!hasTerrain.get()) { + return; + } + + decorateTerrain(chunkData, random, highestY); + } + + private boolean carveBlob(ChunkData chunkData, int chunkX, int chunkZ, Blob blob, short[][] highestY) { + boolean touched = false; + + int minHeight = chunkData.getMinHeight(); + int maxHeight = chunkData.getMaxHeight() - 1; + + double invRx = 1.0 / blob.rx(); + double invRy = 1.0 / blob.ry(); + double invRz = 1.0 / blob.rz(); + + int baseX = chunkX * 16; + int baseZ = chunkZ * 16; + + int blobMinX = (int)Math.floor(blob.x() - blob.rx()); + int blobMaxX = (int)Math.ceil(blob.x() + blob.rx()); + + int blobMinZ = (int)Math.floor(blob.z() - blob.rz()); + int blobMaxZ = (int)Math.ceil(blob.z() + blob.rz()); + + int minLocalX = Math.max(0, blobMinX - baseX); + int maxLocalX = Math.min(15, blobMaxX - baseX); + + int minLocalZ = Math.max(0, blobMinZ - baseZ); + int maxLocalZ = Math.min(15, blobMaxZ - baseZ); + + for (int localX = minLocalX; localX <= maxLocalX; localX++) { + for (int localZ = minLocalZ; localZ <= maxLocalZ; localZ++) { + + int worldX = baseX + localX; + int worldZ = baseZ + localZ; + +// int minY = Math.max(chunkData.getMinHeight(), (int)Math.floor(blob.y() - blob.ry())); +// int maxY = Math.min(chunkData.getMaxHeight() -1, (int)Math.ceil(blob.y() + blob.ry())); + + double nx = (worldX - blob.x()) * invRx; + double nz = (worldZ - blob.z()) * invRz; + + double horizontal = nx * nx + nz * nz; + + if (horizontal > 1.0) + continue; + + double remaining = 1.0 - horizontal; + + if (remaining <= 0) + continue; + + double yRadius = Math.sqrt(remaining) * blob.ry(); + + int startY = Math.max( + minHeight, + (int)Math.ceil(blob.y() - yRadius) + ); + + int endY = Math.min( + maxHeight, + (int)Math.floor(blob.y() + yRadius) + ); + + for (int y = startY; y <= endY; y++) { + chunkData.setBlock(localX, y, localZ, Material.STONE); + touched = true; + } + + highestY[localX][localZ] = (short) Math.max(highestY[localX][localZ], endY); + } + } + + return touched; + } + + private void decorateTerrain(ChunkData chunkData, Random random, short[][] highestY) { + generateSurfaceLayers(chunkData, highestY); + generateOres(chunkData, random); + generateTrees(chunkData, random, highestY); + } + + private void generateSurfaceLayers(ChunkData chunkData, short[][] highestY) { + int minHeight = chunkData.getMinHeight(); + int maxHeight = chunkData.getMaxHeight() - 1; + + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + + int highest = highestY[x][z]; + + if (highest == Short.MIN_VALUE) + continue; + + chunkData.setBlock(x, highest, z, Material.GRASS_BLOCK); + + for (int y = highest - 1; y >= highest - 3; y--) { + if (y >= minHeight) { + chunkData.setBlock(x, y, z, Material.DIRT); + } + } + } + } + } + + private void generateOres(ChunkData chunkData, Random random) { + generateOreVeins(chunkData, random, Material.COAL_ORE, 25, 10); + generateOreVeins(chunkData, random, Material.IRON_ORE, 15, 8); + generateOreVeins(chunkData, random, Material.GOLD_ORE, 6, 6); + generateOreVeins(chunkData, random, Material.DIAMOND_ORE, 2, 4); + } + + private void generateOreVeins(ChunkData chunkData, Random random, Material ore, int veins, int size) { + + for (int i = 0; i < veins; i++) { + + int startX = random.nextInt(16); + int startY = chunkData.getMinHeight() + random.nextInt(chunkData.getMaxHeight() - chunkData.getMinHeight()); + + int startZ = random.nextInt(16); + + for (int j = 0; j < size; j++) { + + int x = startX + random.nextInt(5) - 2; + int y = startY + random.nextInt(5) - 2; + int z = startZ + random.nextInt(5) - 2; + + if (x < 0 || x >= 16) continue; + if (z < 0 || z >= 16) continue; + if (y < chunkData.getMinHeight()) continue; + if (y >= chunkData.getMaxHeight()) continue; + + if (chunkData.getType(x, y, z) == Material.STONE) { + chunkData.setBlock(x, y, z, ore); + } + } + } + } + + private void generateTrees(ChunkData chunkData, Random random, short[][] highestY) { + for (int x = 2; x < 14; x++) { + for (int z = 2; z < 14; z++) { + + if (random.nextInt(500) != 0) { + continue; + } + + int y = highestY[x][z]; + + if (y == Short.MIN_VALUE) { + continue; + } + + if (chunkData.getType(x, y, z) != Material.GRASS_BLOCK) { + continue; + } + + placeTree(chunkData, x, y + 1, z, random); + } + } + } + + private void placeTree(ChunkData chunkData, int x, int y, int z, Random random) { + int height = 4 + random.nextInt(3); + + for (int dy = 0; dy < height; dy++) { + chunkData.setBlock(x, y + dy, z, Material.OAK_LOG); + } + + int top = y + height; + + for (LeafOffset o : LEAF_OFFSETS) { + chunkData.setBlock( + x + o.dx(), + top + o.dy(), + z + o.dz(), + Material.OAK_LEAVES + ); + } + + chunkData.setBlock(x, top + 1, z, Material.OAK_LEAVES); + } + + private void generateIslandGeometry( + int cellX, + int cellZ, + SplittableRandom random, + java.util.function.Consumer consumer + ) { + + int centerX = cellX * CELL_SIZE + random.nextInt(CELL_SIZE); + int centerZ = cellZ * CELL_SIZE + random.nextInt(CELL_SIZE); + int centerY = MIN_Y + random.nextInt(MAX_Y - MIN_Y); + + IslandType type = + TYPES[random.nextInt(TYPES.length)]; + + switch (type) { + + case ROUND -> { + + consumer.accept( + new Blob( + centerX, + centerY, + centerZ, + 12 + random.nextInt(10), + 6 + random.nextInt(5), + 12 + random.nextInt(10) + ) + ); + } + + case LONG -> { + + double angle = random.nextDouble() * Math.PI * 2; + + int segments = 3 + random.nextInt(5); + + for (int i = 0; i < segments; i++) { + + consumer.accept( + new Blob( + centerX + Math.cos(angle) * i * 10, + centerY + random.nextInt(5) - 2, + centerZ + Math.sin(angle) * i * 10, + 8 + random.nextInt(4), + 5 + random.nextInt(2), + 8 + random.nextInt(4) + ) + ); + } + } + + case ARCHIPELAGO -> { + + int count = 3 + random.nextInt(5); + + for (int i = 0; i < count; i++) { + + consumer.accept( + new Blob( + centerX + random.nextInt(60) - 30, + centerY, + centerZ + random.nextInt(60) - 30, + 7 + random.nextInt(5), + 4 + random.nextInt(3), + 7 + random.nextInt(5) + ) + ); + } + } + + case SPIKY -> { + + consumer.accept( + new Blob(centerX, centerY, centerZ, 16, 8, 16) + ); + + for (int i = 0; i < 6; i++) { + + consumer.accept( + new Blob( + centerX + random.nextInt(20) - 10, + centerY - random.nextInt(12), + centerZ + random.nextInt(20) - 10, + 2, + 10 + random.nextInt(8), + 2 + ) + ); + } + } + } + } + + private static long hash(long seed, int x, int z) { + long h = seed; + + h ^= (long) x * 0x9E3779B97F4A7C15L; + h ^= (long) z * 0xC2B2AE3D27D4EB4FL; + + h ^= h >>> 30; + h *= 0xBF58476D1CE4E5B9L; + + h ^= h >>> 27; + h *= 0x94D049BB133111EBL; + + h ^= h >>> 31; + + return h; + } + +} \ No newline at end of file diff --git a/src/main/java/org/adrianvictor/sweetdreams/SkylandsBlockPopulator.java b/src/main/java/org/adrianvictor/sweetdreams/SkylandsBlockPopulator.java new file mode 100644 index 0000000..f893c5c --- /dev/null +++ b/src/main/java/org/adrianvictor/sweetdreams/SkylandsBlockPopulator.java @@ -0,0 +1,22 @@ +package org.adrianvictor.sweetdreams; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.LimitedRegion; +import org.bukkit.generator.WorldInfo; +import org.jspecify.annotations.NonNull; + +import java.util.Random; + +public class SkylandsBlockPopulator extends BlockPopulator { + @Override + public void populate( + @NonNull WorldInfo worldInfo, + @NonNull Random random, + int chunkX, + int chunkZ, + @NonNull LimitedRegion region + ) { + } +} diff --git a/src/main/java/org/adrianvictor/sweetdreams/SweetDreams.java b/src/main/java/org/adrianvictor/sweetdreams/SweetDreams.java new file mode 100644 index 0000000..5c95735 --- /dev/null +++ b/src/main/java/org/adrianvictor/sweetdreams/SweetDreams.java @@ -0,0 +1,86 @@ +package org.adrianvictor.sweetdreams; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; + +public final class SweetDreams extends JavaPlugin { + private World world; + private static SweetDreams plugin; + private Configuration configuration; + private PlayerStorage storage; + + @Override + public void onEnable() { + plugin = this; + configuration = new Configuration(); + storage = new PlayerStorage(configuration); + + boolean generated = false; + + for (World world: getServer().getWorlds()) { + if (world.getName().equals("world_sweetdreams")) { + Bukkit.unloadWorld(world, true); + File worldFolder = new File(Bukkit.getWorldContainer(), "world_sweetdreams"); + if (worldFolder.exists()) { + deleteFolder(worldFolder); + } +// this.world = world; +// generated = true; + } + } + + if (!generated) { + world = createSkylandsWorld("world_sweetdreams"); + } + + getServer().getPluginManager().registerEvents(new EventListener(), this); + } + + private void deleteFolder(File folder) { + if (folder.isDirectory()) { + File[] files = folder.listFiles(); + if (files != null) { + for (File file : files) { + deleteFolder(file); + } + } + } + folder.delete(); + } + + @Override + public void onDisable() { + // Plugin shutdown logic + } + + public World getWorld() { + return world; + } + + public static SweetDreams getPlugin() { + return plugin; + } + + public World createSkylandsWorld(String worldName) { + WorldCreator creator = new WorldCreator(worldName); + creator.generator(new SkyIslandsGenerator()); + creator.environment(World.Environment.NORMAL); + + World world = creator.createWorld(); + world.setSpawnFlags(true, true); + + return world; + } + + public Configuration getConfiguration() { + return configuration; + } + + public PlayerStorage getStorage() { + return storage; + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/playerstorage.yml b/src/main/resources/playerstorage.yml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..1e4f95a --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,11 @@ +name: SweetDreams +description: $description +prefix: SweetDreams +version: '${version}' + +main: org.adrianvictor.sweetdreams.SweetDreams +api-version: '1.21.11' +load: POSTWORLD + +authors: [ tenkuma ] +website: https://adrianvic.github.io