Complete Stage 0: Project scaffold
- Fix build.gradle.kts: Java 21, Paper 1.20.6, ProtocolLib 5.3.0 - Add permissions to paper-plugin.yml - Add ConfigManager with safe yaml loading (no overwrite) - Add LocationsConfig for all game object coordinates - Add GameConfig with all balance values - Update mdbd.java with onEnable/onDisable + ConfigManager - Mark Stage 0 complete in PLAN.md
This commit is contained in:
parent
32da611c63
commit
53f3f6e9da
7 changed files with 443 additions and 15 deletions
12
PLAN.md
12
PLAN.md
|
|
@ -167,12 +167,12 @@ src/main/java/com/dbd/plugin/
|
|||
## TODO (по порядку)
|
||||
|
||||
### Этап 0: Скелет проекта
|
||||
- [ ] Создать `build.gradle` (Paper 1.20.6, Java 17, ProtocolLib)
|
||||
- [ ] `plugin.yml` с пермишнами
|
||||
- [ ] `DBDPlugin.java` — onEnable/onDisable
|
||||
- [ ] `ConfigManager` — загрузка yaml без перезаписи
|
||||
- [ ] `LocationsConfig` — структура для всех координат
|
||||
- [ ] `GameConfig` — балансные цифры
|
||||
- [x] Создать `build.gradle` (Paper 1.20.6, Java 21, ProtocolLib)
|
||||
- [x] `plugin.yml` с пермишнами
|
||||
- [x] `DBDPlugin.java` — onEnable/onDisable
|
||||
- [x] `ConfigManager` — загрузка yaml без перезаписи
|
||||
- [x] `LocationsConfig` — структура для всех координат
|
||||
- [x] `GameConfig` — балансные цифры
|
||||
|
||||
### Этап 1: Core Game Loop
|
||||
- [ ] `GameState` enum
|
||||
|
|
|
|||
|
|
@ -6,22 +6,21 @@ plugins {
|
|||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
maven("https://repo.dmulloy2.net/repository/public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("io.papermc.paper:paper-api:26.1.2.build.+")
|
||||
compileOnly("io.papermc.paper:paper-api:1.20.6-R0.1-SNAPSHOT")
|
||||
compileOnly("com.comphenix.protocol:ProtocolLib:5.3.0")
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(25)
|
||||
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("26.1.2")
|
||||
minecraftVersion("1.20.6")
|
||||
jvmArgs("-Xms2G", "-Xmx2G")
|
||||
}
|
||||
|
||||
|
|
|
|||
68
src/main/java/dev/loki/config/ConfigManager.java
Normal file
68
src/main/java/dev/loki/config/ConfigManager.java
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package dev.loki.config;
|
||||
|
||||
import dev.loki.mdbd;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
|
||||
public class ConfigManager {
|
||||
private final mdbd plugin;
|
||||
private final File dataFolder;
|
||||
|
||||
private LocationsConfig locationsConfig;
|
||||
private GameConfig gameConfig;
|
||||
|
||||
public ConfigManager(mdbd plugin) {
|
||||
this.plugin = plugin;
|
||||
this.dataFolder = plugin.getDataFolder();
|
||||
if (!dataFolder.exists()) {
|
||||
dataFolder.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadConfigs() {
|
||||
this.locationsConfig = new LocationsConfig(loadConfig("locations.yml"));
|
||||
this.gameConfig = new GameConfig(loadConfig("game.yml"));
|
||||
plugin.getLogger().info("Configs loaded successfully");
|
||||
}
|
||||
|
||||
private FileConfiguration loadConfig(String fileName) {
|
||||
File file = new File(dataFolder, fileName);
|
||||
if (!file.exists()) {
|
||||
createDefaultConfig(fileName, file);
|
||||
}
|
||||
return YamlConfiguration.loadConfiguration(file);
|
||||
}
|
||||
|
||||
private void createDefaultConfig(String resourceName, File targetFile) {
|
||||
try (InputStream is = plugin.getResource(resourceName)) {
|
||||
if (is != null) {
|
||||
Files.copy(is, targetFile.toPath());
|
||||
} else {
|
||||
targetFile.createNewFile();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().warning("Could not create config: " + resourceName);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveConfig(String fileName, FileConfiguration config) {
|
||||
try {
|
||||
config.save(new File(dataFolder, fileName));
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().warning("Could not save config: " + fileName);
|
||||
}
|
||||
}
|
||||
|
||||
public LocationsConfig getLocations() {
|
||||
return locationsConfig;
|
||||
}
|
||||
|
||||
public GameConfig getGame() {
|
||||
return gameConfig;
|
||||
}
|
||||
}
|
||||
176
src/main/java/dev/loki/config/GameConfig.java
Normal file
176
src/main/java/dev/loki/config/GameConfig.java
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
package dev.loki.config;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class GameConfig {
|
||||
private final FileConfiguration config;
|
||||
|
||||
public GameConfig(FileConfiguration config) {
|
||||
this.config = config;
|
||||
setDefaults();
|
||||
}
|
||||
|
||||
private void setDefaults() {
|
||||
// Lobby settings
|
||||
setDefault("lobby.min-players", 5);
|
||||
setDefault("lobby.max-players", 5);
|
||||
setDefault("lobby.countdown-seconds", 60);
|
||||
setDefault("lobby.role-assign-delay", 5);
|
||||
|
||||
// Generator settings
|
||||
setDefault("generators.total-count", 7);
|
||||
setDefault("generators.required-count", 5);
|
||||
setDefault("generators.repair-seconds", 80);
|
||||
setDefault("generators.regression-rate", 0.25);
|
||||
setDefault("generators.kick-regression-rate", 2.5);
|
||||
setDefault("generators.kick-duration-seconds", 30);
|
||||
|
||||
// Skill check settings
|
||||
setDefault("skillcheck.zone-size", 0.15);
|
||||
setDefault("skillcheck.rotation-speed", 3.0);
|
||||
setDefault("skillcheck.success-bonus", 5.0);
|
||||
setDefault("skillcheck.fail-penalty", 10.0);
|
||||
|
||||
// Hook settings
|
||||
setDefault("hooks.stage1-seconds", 60);
|
||||
setDefault("hooks.stage2-seconds", 60);
|
||||
setDefault("hooks.struggle-interval", 2);
|
||||
setDefault("hooks.max-hooks", 3);
|
||||
|
||||
// Movement speeds (% of normal)
|
||||
setDefault("movement.killer", 115);
|
||||
setDefault("movement.killer-carry", 92);
|
||||
setDefault("movement.survivor-walk", 100);
|
||||
setDefault("movement.survivor-sprint", 150);
|
||||
setDefault("movement.survivor-crawl", 30);
|
||||
setDefault("movement.exhaustion-duration", 3);
|
||||
setDefault("movement.exhaustion-cooldown", 5);
|
||||
|
||||
// Healing settings
|
||||
setDefault("healing.self-heal-seconds", 30);
|
||||
setDefault("healing.other-heal-seconds", 16);
|
||||
setDefault("healing.medkit-bonus", 0.5);
|
||||
|
||||
// Killer settings
|
||||
setDefault("killer.attack-cooldown", 2.5);
|
||||
setDefault("killer.attack-range", 3.0);
|
||||
setDefault("killer.pallet-stun-seconds", 2.5);
|
||||
setDefault("killer.pallet-break-seconds", 3.0);
|
||||
setDefault("killer.terror-radius", 32);
|
||||
|
||||
// Window vault
|
||||
setDefault("window.vault-survivor-fast", 1.0);
|
||||
setDefault("window.vault-survivor-slow", 1.5);
|
||||
setDefault("window.vault-killer", 1.5);
|
||||
|
||||
// Endgame
|
||||
setDefault("endgame.gate-open-seconds", 20);
|
||||
setDefault("endgame.collapse-seconds", 120);
|
||||
setDefault("endgame.chest-open-seconds", 3);
|
||||
|
||||
// Hatch
|
||||
setDefault("hatch.min-survivors-for-open", 1);
|
||||
}
|
||||
|
||||
private void setDefault(String path, Object value) {
|
||||
if (!config.contains(path)) {
|
||||
config.set(path, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMinPlayers() {
|
||||
return config.getInt("lobby.min-players", 5);
|
||||
}
|
||||
|
||||
public int getMaxPlayers() {
|
||||
return config.getInt("lobby.max-players", 5);
|
||||
}
|
||||
|
||||
public int getLobbyCountdown() {
|
||||
return config.getInt("lobby.countdown-seconds", 60);
|
||||
}
|
||||
|
||||
public int getRoleAssignDelay() {
|
||||
return config.getInt("lobby.role-assign-delay", 5);
|
||||
}
|
||||
|
||||
public int getGeneratorTotal() {
|
||||
return config.getInt("generators.total-count", 7);
|
||||
}
|
||||
|
||||
public int getGeneratorRequired() {
|
||||
return config.getInt("generators.required-count", 5);
|
||||
}
|
||||
|
||||
public int getGeneratorRepairSeconds() {
|
||||
return config.getInt("generators.repair-seconds", 80);
|
||||
}
|
||||
|
||||
public double getRegressionRate() {
|
||||
return config.getDouble("generators.regression-rate", 0.25);
|
||||
}
|
||||
|
||||
public double getKickRegressionRate() {
|
||||
return config.getDouble("generators.kick-regression-rate", 2.5);
|
||||
}
|
||||
|
||||
public int getKickDuration() {
|
||||
return config.getInt("generators.kick-duration-seconds", 30);
|
||||
}
|
||||
|
||||
public int getStage1Seconds() {
|
||||
return config.getInt("hooks.stage1-seconds", 60);
|
||||
}
|
||||
|
||||
public int getStage2Seconds() {
|
||||
return config.getInt("hooks.stage2-seconds", 60);
|
||||
}
|
||||
|
||||
public int getMaxHooks() {
|
||||
return config.getInt("hooks.max-hooks", 3);
|
||||
}
|
||||
|
||||
public double getKillerSpeed() {
|
||||
return config.getDouble("movement.killer", 115) / 100.0;
|
||||
}
|
||||
|
||||
public double getKillerCarrySpeed() {
|
||||
return config.getDouble("movement.killer-carry", 92) / 100.0;
|
||||
}
|
||||
|
||||
public double getSurvivorWalkSpeed() {
|
||||
return config.getDouble("movement.survivor-walk", 100) / 100.0;
|
||||
}
|
||||
|
||||
public double getSurvivorSprintSpeed() {
|
||||
return config.getDouble("movement.survivor-sprint", 150) / 100.0;
|
||||
}
|
||||
|
||||
public double getSurvivorCrawlSpeed() {
|
||||
return config.getDouble("movement.survivor-crawl", 30) / 100.0;
|
||||
}
|
||||
|
||||
public int getAttackCooldown() {
|
||||
return (int) (config.getDouble("killer.attack-cooldown", 2.5) * 20);
|
||||
}
|
||||
|
||||
public double getAttackRange() {
|
||||
return config.getDouble("killer.attack-range", 3.0);
|
||||
}
|
||||
|
||||
public int getPalletStunTicks() {
|
||||
return (int) (config.getDouble("killer.pallet-stun-seconds", 2.5) * 20);
|
||||
}
|
||||
|
||||
public int getPalletBreakTicks() {
|
||||
return (int) (config.getDouble("killer.pallet-break-seconds", 3.0) * 20);
|
||||
}
|
||||
|
||||
public int getTerrorRadius() {
|
||||
return config.getInt("killer.terror-radius", 32);
|
||||
}
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
159
src/main/java/dev/loki/config/LocationsConfig.java
Normal file
159
src/main/java/dev/loki/config/LocationsConfig.java
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
package dev.loki.config;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LocationsConfig {
|
||||
private final FileConfiguration config;
|
||||
|
||||
public LocationsConfig(FileConfiguration config) {
|
||||
this.config = config;
|
||||
setDefaults();
|
||||
}
|
||||
|
||||
private void setDefaults() {
|
||||
if (!config.contains("lobby")) {
|
||||
config.set("lobby.world", "world");
|
||||
config.set("lobby.x", 0.0);
|
||||
config.set("lobby.y", 100.0);
|
||||
config.set("lobby.z", 0.0);
|
||||
config.set("lobby.yaw", 0.0);
|
||||
config.set("lobby.pitch", 0.0);
|
||||
}
|
||||
if (!config.contains("generators")) {
|
||||
config.set("generators", new ArrayList<>());
|
||||
}
|
||||
if (!config.contains("hooks")) {
|
||||
config.set("hooks", new ArrayList<>());
|
||||
}
|
||||
if (!config.contains("pallets")) {
|
||||
config.set("pallets", new ArrayList<>());
|
||||
}
|
||||
if (!config.contains("windows")) {
|
||||
config.set("windows", new ArrayList<>());
|
||||
}
|
||||
if (!config.contains("chests")) {
|
||||
config.set("chests", new ArrayList<>());
|
||||
}
|
||||
if (!config.contains("totems")) {
|
||||
config.set("totems", new ArrayList<>());
|
||||
}
|
||||
if (!config.contains("exitgates")) {
|
||||
config.set("exitgates", new ArrayList<>());
|
||||
}
|
||||
if (!config.contains("killer-spawn")) {
|
||||
config.set("killer-spawn", new ArrayList<>());
|
||||
}
|
||||
if (!config.contains("survivor-spawns")) {
|
||||
config.set("survivor-spawns", new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
public Location getLobby() {
|
||||
World world = Bukkit.getWorld(config.getString("lobby.world", "world"));
|
||||
if (world == null) return null;
|
||||
return new Location(
|
||||
world,
|
||||
config.getDouble("lobby.x", 0.0),
|
||||
config.getDouble("lobby.y", 100.0),
|
||||
config.getDouble("lobby.z", 0.0),
|
||||
(float) config.getDouble("lobby.yaw", 0.0),
|
||||
(float) config.getDouble("lobby.pitch", 0.0)
|
||||
);
|
||||
}
|
||||
|
||||
public void setLobby(Location loc) {
|
||||
config.set("lobby.world", loc.getWorld().getName());
|
||||
config.set("lobby.x", loc.getX());
|
||||
config.set("lobby.y", loc.getY());
|
||||
config.set("lobby.z", loc.getZ());
|
||||
config.set("lobby.yaw", loc.getYaw());
|
||||
config.set("lobby.pitch", loc.getPitch());
|
||||
}
|
||||
|
||||
public List<Location> getGenerators() {
|
||||
return loadLocationList("generators");
|
||||
}
|
||||
|
||||
public List<Location> getHooks() {
|
||||
return loadLocationList("hooks");
|
||||
}
|
||||
|
||||
public List<Location> getPallets() {
|
||||
return loadLocationList("pallets");
|
||||
}
|
||||
|
||||
public List<Location> getWindows() {
|
||||
return loadLocationList("windows");
|
||||
}
|
||||
|
||||
public List<Location> getChests() {
|
||||
return loadLocationList("chests");
|
||||
}
|
||||
|
||||
public List<Location> getTotems() {
|
||||
return loadLocationList("totems");
|
||||
}
|
||||
|
||||
public List<Location> getExitGates() {
|
||||
return loadLocationList("exitgates");
|
||||
}
|
||||
|
||||
public Location getKillerSpawn() {
|
||||
List<Location> spawns = loadLocationList("killer-spawn");
|
||||
return spawns.isEmpty() ? null : spawns.get(0);
|
||||
}
|
||||
|
||||
public List<Location> getSurvivorSpawns() {
|
||||
return loadLocationList("survivor-spawns");
|
||||
}
|
||||
|
||||
private List<Location> loadLocationList(String path) {
|
||||
List<Location> locations = new ArrayList<>();
|
||||
List<?> list = config.getList(path);
|
||||
if (list == null) return locations;
|
||||
|
||||
for (Object obj : list) {
|
||||
if (obj instanceof String) {
|
||||
Location loc = parseLocation((String) obj);
|
||||
if (loc != null) locations.add(loc);
|
||||
}
|
||||
}
|
||||
return locations;
|
||||
}
|
||||
|
||||
private Location parseLocation(String str) {
|
||||
String[] parts = str.split(",");
|
||||
if (parts.length < 4) return null;
|
||||
World world = Bukkit.getWorld(parts[0].trim());
|
||||
if (world == null) return null;
|
||||
try {
|
||||
double x = Double.parseDouble(parts[1].trim());
|
||||
double y = Double.parseDouble(parts[2].trim());
|
||||
double z = Double.parseDouble(parts[3].trim());
|
||||
float yaw = parts.length > 4 ? Float.parseFloat(parts[4].trim()) : 0f;
|
||||
float pitch = parts.length > 5 ? Float.parseFloat(parts[5].trim()) : 0f;
|
||||
return new Location(world, x, y, z, yaw, pitch);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void addLocation(String path, Location loc) {
|
||||
List<String> list = config.getStringList(path);
|
||||
list.add(String.format("%s,%.2f,%.2f,%.2f,%.1f,%.1f",
|
||||
loc.getWorld().getName(),
|
||||
loc.getX(), loc.getY(), loc.getZ(),
|
||||
loc.getYaw(), loc.getPitch()));
|
||||
config.set(path, list);
|
||||
}
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,34 @@
|
|||
package dev.loki;
|
||||
|
||||
import dev.loki.config.ConfigManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public final class mdbd extends JavaPlugin {
|
||||
private static mdbd instance;
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Plugin startup logic
|
||||
instance = this;
|
||||
getLogger().info("Mdbd Plugin enabling...");
|
||||
|
||||
this.configManager = new ConfigManager(this);
|
||||
this.configManager.loadConfigs();
|
||||
|
||||
getLogger().info("Mdbd Plugin enabled successfully!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Plugin shutdown logic
|
||||
getLogger().info("Mdbd Plugin disabling...");
|
||||
instance = null;
|
||||
}
|
||||
|
||||
public static mdbd getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ConfigManager getConfigManager() {
|
||||
return configManager;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,15 @@ version: '${version}'
|
|||
main: dev.loki.mdbd
|
||||
bootstrapper: dev.loki.mdbdBootstrap
|
||||
loader: dev.loki.mdbdLoader
|
||||
api-version: '26.1.2'
|
||||
api-version: '1.20.6'
|
||||
load: POSTWORLD
|
||||
|
||||
authors: [ loki ]
|
||||
|
||||
permissions:
|
||||
mdbd.admin:
|
||||
description: "Полный доступ к админ-командам плагина"
|
||||
default: op
|
||||
mdbd.player:
|
||||
description: "Базовые команды для игроков"
|
||||
default: true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue