meow :3
Build / build (push) Failing after 20s

This commit is contained in:
Laura
2026-08-09 19:36:32 +02:00
parent 56514401a1
commit 3493314c3f
15 changed files with 412 additions and 33 deletions
+11 -2
View File
@@ -17,8 +17,8 @@
</repository> </repository>
</distributionManagement> </distributionManagement>
<properties> <properties>
<maven.compiler.source>25</maven.compiler.source> <maven.compiler.source>26</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target> <maven.compiler.target>26</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<repositories> <repositories>
@@ -59,6 +59,15 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version> <version>3.15.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.46</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
@@ -1,7 +1,8 @@
package com.softwarerat.API.data; package com.softwarerat.API;
import java.util.List; import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@@ -34,6 +35,7 @@ public class GameData {
public GameData(GameAPI gameapi) { public GameData(GameAPI gameapi) {
this.gameapi = gameapi; this.gameapi = gameapi;
this.gameStateManager = new GameStateManager(); this.gameStateManager = new GameStateManager();
this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
} }
public String getGameHost(JavaPlugin javaPlugin){ public String getGameHost(JavaPlugin javaPlugin){
@@ -0,0 +1,6 @@
package com.softwarerat.API.data.entity;
import com.softwarerat.API.data.store.Flag;
public interface EntityFlag extends Flag {
}
@@ -0,0 +1,32 @@
package com.softwarerat.API.data.entity;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.entity.Entity;
// Registry of EntityFlagHolders keyed by entity UUID, usable for NPCs and any other entity
public class EntityFlagAPI {
private final Map<UUID, EntityFlagHolder> holders = new ConcurrentHashMap<>();
public EntityFlagHolder get(Entity entity) {
return this.holders.computeIfAbsent(entity.getUniqueId(), id -> new EntityFlagHolder(entity));
}
public void setFlag(Entity entity, EntityFlag flag) {
get(entity).setFlag(flag);
}
public void removeFlag(Entity entity, EntityFlag flag) {
get(entity).removeFlag(flag);
}
public boolean hasFlag(Entity entity, EntityFlag... flags) {
return get(entity).hasFlag(flags);
}
public void clear(Entity entity) {
this.holders.remove(entity.getUniqueId());
}
}
@@ -0,0 +1,52 @@
package com.softwarerat.API.data.entity;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.bukkit.entity.Entity;
import com.softwarerat.API.data.store.CacheManager;
import com.softwarerat.API.data.store.FlagManager;
// Per-entity flag storage. Unlike GamePlayer's single current PlayerFlag, entities
// may carry several flags at once (e.g. NPC + PROTECTED + INTERACTABLE).
public class EntityFlagHolder extends CacheManager implements FlagManager<EntityFlag> {
private static final String FLAGS_KEY = "__flags__";
private final Entity entity;
public EntityFlagHolder(Entity entity) {
this.entity = entity;
addToCache(FLAGS_KEY, new LinkedHashSet<EntityFlag>());
}
public Entity getEntity() {
return this.entity;
}
@SuppressWarnings("unchecked")
private Set<EntityFlag> flags() {
return (Set<EntityFlag>) getValueFromCache(FLAGS_KEY);
}
@Override
public void setFlag(EntityFlag flag) {
flags().add(flag);
}
@Override
public void removeFlag(EntityFlag flag) {
flags().remove(flag);
}
@Override
public boolean hasFlag(EntityFlag... flag) {
return Arrays.stream(flag).anyMatch(flags()::contains);
}
public Set<EntityFlag> getFlags() {
return Collections.unmodifiableSet(flags());
}
}
@@ -0,0 +1,26 @@
package com.softwarerat.API.data.entity;
public enum EntityFlags implements EntityFlag {
NPC("marks the entity as a non-player character", 1),
PROTECTED("entity cannot take damage or be targeted", 2),
INTERACTABLE("entity runs an action when right-clicked", 3);
private final String description;
private final Integer number;
EntityFlags(String description, Integer number) {
this.description = description;
this.number = number;
}
@Override
public String getDescription() {
return this.description;
}
@Override
public Integer getInt() {
return this.number;
}
}
@@ -1,12 +1,14 @@
package com.softwarerat.API.data.location; package com.softwarerat.API.data.location;
import com.softwarerat.API.data.GameData;
import lombok.AllArgsConstructor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.softwarerat.API.GameData;
import lombok.AllArgsConstructor;
// Game related Location building // Game related Location building
@AllArgsConstructor @AllArgsConstructor
public class LocationAPI { public class LocationAPI {
@@ -0,0 +1,59 @@
package com.softwarerat.API.data.npc;
import java.util.Set;
import java.util.UUID;
import org.bukkit.entity.Entity;
import com.softwarerat.API.data.entity.EntityFlag;
import com.softwarerat.API.data.entity.EntityFlagHolder;
public class NPC {
private final String name;
private final Entity entity;
private final NPCAction action;
private final EntityFlagHolder flags;
public NPC(String name, Entity entity, NPCAction action, EntityFlagHolder flags) {
this.name = name;
this.entity = entity;
this.action = action;
this.flags = flags;
}
public UUID getEntityId() {
return this.entity.getUniqueId();
}
public String getName() {
return this.name;
}
public Entity getEntity() {
return this.entity;
}
public NPCAction getAction() {
return this.action;
}
public void setFlag(EntityFlag flag) {
this.flags.setFlag(flag);
}
public void removeFlag(EntityFlag flag) {
this.flags.removeFlag(flag);
}
public boolean hasFlag(EntityFlag... flag) {
return this.flags.hasFlag(flag);
}
public Set<EntityFlag> getFlags() {
return this.flags.getFlags();
}
public void remove() {
this.entity.remove();
}
}
@@ -0,0 +1,73 @@
package com.softwarerat.API.data.npc;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import com.softwarerat.API.data.entity.EntityFlagAPI;
import com.softwarerat.API.data.entity.EntityFlagHolder;
import com.softwarerat.API.data.entity.EntityFlags;
import net.kyori.adventure.text.Component;
// Spawns non-interactive NPC entities and dispatches an NPCAction when a player clicks them
public class NPCAPI {
private final Map<UUID, NPC> npcsByEntityId = new ConcurrentHashMap<>();
private final EntityFlagAPI entityFlagAPI;
public NPCAPI(EntityFlagAPI entityFlagAPI) {
this.entityFlagAPI = entityFlagAPI;
}
public NPC spawnNPC(Location location, EntityType type, String name, NPCAction action) {
Entity entity = location.getWorld().spawnEntity(location, type);
entity.customName(Component.text(name));
entity.setCustomNameVisible(true);
entity.setPersistent(false);
entity.setInvulnerable(true);
if (entity instanceof LivingEntity livingEntity) {
livingEntity.setCollidable(false);
livingEntity.setRemoveWhenFarAway(false);
livingEntity.setCanPickupItems(false);
livingEntity.setAI(false);
}
if (entity instanceof Mob mob) {
mob.setAware(false);
}
EntityFlagHolder flags = this.entityFlagAPI.get(entity);
flags.setFlag(EntityFlags.NPC);
flags.setFlag(EntityFlags.INTERACTABLE);
NPC npc = new NPC(name, entity, action, flags);
this.npcsByEntityId.put(npc.getEntityId(), npc);
return npc;
}
public void removeNPC(NPC npc) {
this.npcsByEntityId.remove(npc.getEntityId());
this.entityFlagAPI.clear(npc.getEntity());
npc.remove();
}
public void removeAll() {
this.npcsByEntityId.values().forEach(NPC::remove);
this.npcsByEntityId.clear();
}
public NPC getNPC(UUID entityId) {
return this.npcsByEntityId.get(entityId);
}
public Collection<NPC> getNPCs() {
return this.npcsByEntityId.values();
}
}
@@ -0,0 +1,9 @@
package com.softwarerat.API.data.npc;
import org.bukkit.entity.Player;
// Callback executed when a player clicks an NPC, e.g. open an interactive inventory
@FunctionalInterface
public interface NPCAction {
void onInteract(Player player, NPC npc);
}
@@ -3,8 +3,8 @@ package com.softwarerat.API.data.player;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import com.softwarerat.API.data.GameData;
import com.softwarerat.GameAPI; import com.softwarerat.GameAPI;
import com.softwarerat.API.GameData;
// Game related PlayerAPI for checking if a player is the GameHost // Game related PlayerAPI for checking if a player is the GameHost
@@ -18,4 +18,5 @@ JavaPlugin javaPlugin = gameAPI.getJavaPlugin();
return p.getName().equals(s); return p.getName().equals(s);
} }
} }
@@ -17,16 +17,21 @@ import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream; import org.bukkit.util.io.BukkitObjectOutputStream;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import com.softwarerat.API.GameData;
public class KitAPI { public class KitAPI {
private final HashMap<String, ItemStack[]> kits; private final GameData gameData;
private final HashMap<String, String> kits;
private final ConcurrentHashMap<UUID, String> playerKit; private final ConcurrentHashMap<UUID, String> playerKit;
private final ArrayList<Player> playersWithKits; private final ArrayList<Player> playersWithKits;
public KitAPI() { public KitAPI(GameData gameData) {
this.kits = (HashMap)new HashMap<>(); this.gameData = gameData;
this.kits = new HashMap<>();
this.playerKit = new ConcurrentHashMap<>(); this.playerKit = new ConcurrentHashMap<>();
this.playersWithKits = new ArrayList<>(); this.playersWithKits = new ArrayList<>();
} }
@@ -44,9 +49,29 @@ public class KitAPI {
return this.playerKit; return this.playerKit;
} }
public void giveKit(Player player, String base64) { public boolean hasKit(String kitName) {
return this.kits.containsKey(kitName);
}
public void giveKit(Player player, String kitName) {
String base64 = this.kits.get(kitName);
if (base64 == null) {
throw new IllegalArgumentException("No kit saved with name: " + kitName);
}
giveKitFromData(player, base64);
this.playerKit.put(player.getUniqueId(), kitName);
}
public void givePrimaryKit(Player player) {
giveKit(player, this.gameData.getPrimaryKit());
}
public void giveSecondaryKit(Player player) {
giveKit(player, this.gameData.getSecondaryKit());
}
public void giveKitFromData(Player player, String base64) {
player.getInventory().clear(); player.getInventory().clear();
System.out.println(this.playerKit);
ItemStack[] kit = loadKit(base64); ItemStack[] kit = loadKit(base64);
for (int i = 0; i < kit.length; i++) { for (int i = 0; i < kit.length; i++) {
ItemStack itemStack = kit[i]; ItemStack itemStack = kit[i];
@@ -122,13 +147,11 @@ public class KitAPI {
public void saveKit(Player player, String name) { public void saveKit(Player player, String name) {
String kitBase64 = itemStackArrayToBase64(player.getInventory().getContents()); String kitBase64 = itemStackArrayToBase64(player.getInventory().getContents());
this.kits.put(name, kitBase64);
this.kits.put(name, player.getInventory().getContents());
} }
public HashMap<String,ItemStack[]> getKits() { public HashMap<String,String> getKits() {
return this.kits; return this.kits;
} }
@@ -1,21 +1,60 @@
package com.softwarerat.API.data.scoreboard; package com.softwarerat.API.data.scoreboard;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scoreboard.Criteria;
import org.bukkit.scoreboard.DisplaySlot; import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective; import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.ScoreboardManager;
import com.softwarerat.API.GameData;
import net.kyori.adventure.text.Component;
// Sidebar scoreboard for the game, built on GameData's shared Scoreboard so it
// coexists with PrefixAPI's teams instead of replacing the player's board.
public class ScoreAPI { public class ScoreAPI {
private final GameData gameData;
private Objective objective;
public ScoreAPI(String minigameName, String mapName,Player player,String localName){ public ScoreAPI(GameData gameData) {
ScoreboardManager manager = Bukkit.getScoreboardManager(); this.gameData = gameData;
Scoreboard board = manager.getNewScoreboard(); }
Objective objective = board.registerNewObjective(localName, "dummy");
objective.setDisplaySlot(DisplaySlot.SIDEBAR); public void createSidebar(String objectiveName, String title) {
objective.setDisplayName(minigameName); Scoreboard board = this.gameData.getScoreboard();
player.setScoreboard(board); Objective existing = board.getObjective(objectiveName);
if (existing != null) {
existing.unregister();
}
this.objective = board.registerNewObjective(objectiveName, Criteria.DUMMY, Component.text(title));
this.objective.setDisplaySlot(DisplaySlot.SIDEBAR);
}
public void showTo(Player player) {
player.setScoreboard(this.gameData.getScoreboard());
}
public void setTitle(String title) {
if (this.objective == null) return;
this.objective.displayName(Component.text(title));
} }
public void setScore(String line, int value) {
if (this.objective == null) return;
this.objective.getScore(line).setScore(value);
}
public void removeScore(String line) {
this.gameData.getScoreboard().resetScores(line);
}
public void clear() {
if (this.objective == null) return;
this.objective.unregister();
this.objective = null;
}
} }
@@ -0,0 +1,30 @@
package com.softwarerat.API.event.listener;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import com.softwarerat.API.data.entity.EntityFlags;
import com.softwarerat.API.data.npc.NPC;
import com.softwarerat.API.data.npc.NPCAPI;
// Dispatches clicks on spawned NPCs to their registered NPCAction
public class NPCInteractListener implements Listener {
private final NPCAPI npcAPI;
public NPCInteractListener(NPCAPI npcAPI) {
this.npcAPI = npcAPI;
}
@EventHandler
public void onPlayerInteractNPC(PlayerInteractEntityEvent event) {
NPC npc = this.npcAPI.getNPC(event.getRightClicked().getUniqueId());
if (npc == null) return;
if (!npc.hasFlag(EntityFlags.INTERACTABLE)) return;
event.setCancelled(true);
Player player = event.getPlayer();
npc.getAction().onInteract(player, npc);
}
}
+17 -1
View File
@@ -5,10 +5,15 @@ import org.bukkit.Bukkit;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import com.softwarerat.API.data.GameData; import com.softwarerat.API.GameData;
import com.softwarerat.API.data.entity.EntityFlagAPI;
import com.softwarerat.API.data.location.LocationAPI; import com.softwarerat.API.data.location.LocationAPI;
import com.softwarerat.API.data.npc.NPCAPI;
import com.softwarerat.API.data.player.kit.KitAPI;
import com.softwarerat.API.data.prefix.PrefixAPI; import com.softwarerat.API.data.prefix.PrefixAPI;
import com.softwarerat.API.data.scoreboard.ScoreAPI;
import com.softwarerat.API.data.world.WorldAPI; import com.softwarerat.API.data.world.WorldAPI;
import com.softwarerat.API.event.listener.NPCInteractListener;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -23,13 +28,24 @@ GameData gameData;
WorldAPI worldAPI; WorldAPI worldAPI;
LocationAPI locationAPI; LocationAPI locationAPI;
PrefixAPI prefixAPI; PrefixAPI prefixAPI;
KitAPI kitAPI;
EntityFlagAPI entityFlagAPI;
NPCAPI npcAPI;
ScoreAPI scoreAPI;
public void enableAPI(JavaPlugin jPlugin){ public void enableAPI(JavaPlugin jPlugin){
javaPlugin = jPlugin; javaPlugin = jPlugin;
gameData = new GameData(this);
worldAPI = new WorldAPI(); worldAPI = new WorldAPI();
System.out.println("Enabled GameAPI"); System.out.println("Enabled GameAPI");
PluginManager pluginManager = Bukkit.getPluginManager(); PluginManager pluginManager = Bukkit.getPluginManager();
locationAPI = new LocationAPI(gameData); locationAPI = new LocationAPI(gameData);
kitAPI = new KitAPI(gameData);
prefixAPI = new PrefixAPI(gameData.getScoreboard());
scoreAPI = new ScoreAPI(gameData);
entityFlagAPI = new EntityFlagAPI();
npcAPI = new NPCAPI(entityFlagAPI);
pluginManager.registerEvents(new NPCInteractListener(npcAPI), jPlugin);
//javaPlugin.getCommand("getNavigator").setExecutor(new Navigator(this)); //javaPlugin.getCommand("getNavigator").setExecutor(new Navigator(this));
//if (gameData.getGameType().equals(GameType.GAME_TYPE_TYPELESS) || gameData.getCurrentGameState().equals(GameState.GAME_STATE_LOBBY)){ //if (gameData.getGameType().equals(GameType.GAME_TYPE_TYPELESS) || gameData.getCurrentGameState().equals(GameState.GAME_STATE_LOBBY)){