mirror of
https://github.com/BentoBoxWorld/Boxed.git
synced 2024-11-17 10:45:42 +01:00
commit
48568e8312
6
pom.xml
6
pom.xml
@ -58,14 +58,14 @@
|
|||||||
<!-- Non-minecraft related dependencies -->
|
<!-- Non-minecraft related dependencies -->
|
||||||
<powermock.version>2.0.9</powermock.version>
|
<powermock.version>2.0.9</powermock.version>
|
||||||
<!-- More visible way how to change dependency versions -->
|
<!-- More visible way how to change dependency versions -->
|
||||||
<spigot.version>1.20.1-R0.1-SNAPSHOT</spigot.version>
|
<spigot.version>1.20.2-R0.1-SNAPSHOT</spigot.version>
|
||||||
<bentobox.version>1.24.0</bentobox.version>
|
<bentobox.version>2.0.0-SNAPSHOT</bentobox.version>
|
||||||
<!-- Revision variable removes warning about dynamic version -->
|
<!-- Revision variable removes warning about dynamic version -->
|
||||||
<revision>${build.version}-SNAPSHOT</revision>
|
<revision>${build.version}-SNAPSHOT</revision>
|
||||||
<!-- Do not change unless you want different name for local builds. -->
|
<!-- Do not change unless you want different name for local builds. -->
|
||||||
<build.number>-LOCAL</build.number>
|
<build.number>-LOCAL</build.number>
|
||||||
<!-- This allows to change between versions. -->
|
<!-- This allows to change between versions. -->
|
||||||
<build.version>2.3.0</build.version>
|
<build.version>2.3.1</build.version>
|
||||||
|
|
||||||
<sonar.projectKey>BentoBoxWorld_Boxed</sonar.projectKey>
|
<sonar.projectKey>BentoBoxWorld_Boxed</sonar.projectKey>
|
||||||
<sonar.organization>bentobox-world</sonar.organization>
|
<sonar.organization>bentobox-world</sonar.organization>
|
||||||
|
@ -52,6 +52,11 @@ public class Settings implements WorldSettings {
|
|||||||
private String defaultPlayerAction = "go";
|
private String defaultPlayerAction = "go";
|
||||||
|
|
||||||
/* Boxed */
|
/* Boxed */
|
||||||
|
@ConfigComment("Ignore advancements.")
|
||||||
|
@ConfigComment("If this is true, advancements will not change the size of the box.")
|
||||||
|
@ConfigEntry(path = "boxed.ignore-advancements")
|
||||||
|
private boolean ignoreAdvancements = false;
|
||||||
|
|
||||||
@ConfigComment("Announce advancements. We recommend you set the game rule `/gamerule announceAdvancements false`")
|
@ConfigComment("Announce advancements. We recommend you set the game rule `/gamerule announceAdvancements false`")
|
||||||
@ConfigComment("but that blocks all new advancement announcements. This setting tells Boxed to broadcast new advancements.")
|
@ConfigComment("but that blocks all new advancement announcements. This setting tells Boxed to broadcast new advancements.")
|
||||||
@ConfigEntry(path = "boxed.broadcast-advancements")
|
@ConfigEntry(path = "boxed.broadcast-advancements")
|
||||||
@ -125,7 +130,7 @@ public class Settings implements WorldSettings {
|
|||||||
@ConfigComment("If the number of areas is greater than this number, it will stop players from joining the world.")
|
@ConfigComment("If the number of areas is greater than this number, it will stop players from joining the world.")
|
||||||
@ConfigEntry(path = "world.max-areas")
|
@ConfigEntry(path = "world.max-areas")
|
||||||
private int maxIslands = -1;
|
private int maxIslands = -1;
|
||||||
|
|
||||||
@ConfigComment("Area height - Lowest is 5.")
|
@ConfigComment("Area height - Lowest is 5.")
|
||||||
@ConfigComment("It is the y coordinate of the bedrock block in the blueprint.")
|
@ConfigComment("It is the y coordinate of the bedrock block in the blueprint.")
|
||||||
@ConfigEntry(path = "world.area-height")
|
@ConfigEntry(path = "world.area-height")
|
||||||
@ -317,7 +322,7 @@ public class Settings implements WorldSettings {
|
|||||||
@ConfigComment("Grant these advancements")
|
@ConfigComment("Grant these advancements")
|
||||||
@ConfigEntry(path = "area.reset.on-leave.grant-advancements")
|
@ConfigEntry(path = "area.reset.on-leave.grant-advancements")
|
||||||
private List<String> onLeaveGrantAdvancements = new ArrayList<>();
|
private List<String> onLeaveGrantAdvancements = new ArrayList<>();
|
||||||
|
|
||||||
@ConfigComment("Toggles the automatic area creation upon the player's first login on your server.")
|
@ConfigComment("Toggles the automatic area creation upon the player's first login on your server.")
|
||||||
@ConfigComment("If set to true,")
|
@ConfigComment("If set to true,")
|
||||||
@ConfigComment(" * Upon connecting to your server for the first time, the player will be told that")
|
@ConfigComment(" * Upon connecting to your server for the first time, the player will be told that")
|
||||||
@ -1735,4 +1740,18 @@ public class Settings implements WorldSettings {
|
|||||||
this.islandHeight = islandHeight;
|
this.islandHeight = islandHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ignoreAdvancements
|
||||||
|
*/
|
||||||
|
public boolean isIgnoreAdvancements() {
|
||||||
|
return ignoreAdvancements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ignoreAdvancements the ignoreAdvancements to set
|
||||||
|
*/
|
||||||
|
public void setIgnoreAdvancements(boolean ignoreAdvancements) {
|
||||||
|
this.ignoreAdvancements = ignoreAdvancements;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -84,8 +84,8 @@ public class AdvancementListener implements Listener {
|
|||||||
*/
|
*/
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
public void onAdvancement(PlayerAdvancementDoneEvent e) {
|
public void onAdvancement(PlayerAdvancementDoneEvent e) {
|
||||||
// Ignore if player is not in survival
|
// Ignore if player is not in survival or if advancements are being ignored
|
||||||
if (!e.getPlayer().getGameMode().equals(GameMode.SURVIVAL)) {
|
if (!e.getPlayer().getGameMode().equals(GameMode.SURVIVAL) || addon.getSettings().isIgnoreAdvancements()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Check if player is in the Boxed worlds
|
// Check if player is in the Boxed worlds
|
||||||
@ -137,6 +137,7 @@ public class AdvancementListener implements Listener {
|
|||||||
* @param user - user
|
* @param user - user
|
||||||
*/
|
*/
|
||||||
public void syncAdvancements(User user) {
|
public void syncAdvancements(User user) {
|
||||||
|
if (addon.getSettings().isIgnoreAdvancements()) return;
|
||||||
Island box = addon.getIslands().getIsland(addon.getOverWorld(), user);
|
Island box = addon.getIslands().getIsland(addon.getOverWorld(), user);
|
||||||
if (box != null) {
|
if (box != null) {
|
||||||
grantAdv(user, addon.getAdvManager().getIsland(box).getAdvancements());
|
grantAdv(user, addon.getAdvManager().getIsland(box).getAdvancements());
|
||||||
@ -174,7 +175,8 @@ public class AdvancementListener implements Listener {
|
|||||||
*/
|
*/
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
public void onPortal(PlayerPortalEvent e) {
|
public void onPortal(PlayerPortalEvent e) {
|
||||||
if (!addon.inWorld(e.getPlayer().getWorld()) || !e.getPlayer().getGameMode().equals(GameMode.SURVIVAL)) {
|
if (!addon.inWorld(e.getPlayer().getWorld()) || !e.getPlayer().getGameMode().equals(GameMode.SURVIVAL)
|
||||||
|
|| addon.getSettings().isIgnoreAdvancements()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.getCause().equals(TeleportCause.NETHER_PORTAL)) {
|
if (e.getCause().equals(TeleportCause.NETHER_PORTAL)) {
|
||||||
@ -194,7 +196,8 @@ public class AdvancementListener implements Listener {
|
|||||||
*/
|
*/
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
public void onMove(PlayerMoveEvent e) {
|
public void onMove(PlayerMoveEvent e) {
|
||||||
if (!addon.getSettings().isNetherGenerate() || !Util.sameWorld(e.getPlayer().getWorld(), addon.getNetherWorld())) {
|
if (!addon.getSettings().isNetherGenerate() || !Util.sameWorld(e.getPlayer().getWorld(), addon.getNetherWorld())
|
||||||
|
|| addon.getSettings().isIgnoreAdvancements()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Nether fortress advancement
|
// Nether fortress advancement
|
||||||
@ -263,6 +266,7 @@ public class AdvancementListener implements Listener {
|
|||||||
*/
|
*/
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
public void onTeamLeaveTime(TeamLeaveEvent e) {
|
public void onTeamLeaveTime(TeamLeaveEvent e) {
|
||||||
|
if (addon.getSettings().isIgnoreAdvancements()) return;
|
||||||
User user = User.getInstance(e.getPlayerUUID());
|
User user = User.getInstance(e.getPlayerUUID());
|
||||||
if (user != null && addon.getSettings().isOnJoinResetAdvancements() && user.isOnline()
|
if (user != null && addon.getSettings().isOnJoinResetAdvancements() && user.isOnline()
|
||||||
&& addon.getOverWorld().equals(Util.getWorld(user.getWorld()))) {
|
&& addon.getOverWorld().equals(Util.getWorld(user.getWorld()))) {
|
||||||
@ -278,6 +282,7 @@ public class AdvancementListener implements Listener {
|
|||||||
*/
|
*/
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
public void onFirstTime(IslandNewIslandEvent e) {
|
public void onFirstTime(IslandNewIslandEvent e) {
|
||||||
|
if (addon.getSettings().isIgnoreAdvancements()) return;
|
||||||
User user = User.getInstance(e.getPlayerUUID());
|
User user = User.getInstance(e.getPlayerUUID());
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
clearAndSetAdv(user, addon.getSettings().isOnJoinResetAdvancements(), addon.getSettings().getOnJoinGrantAdvancements());
|
clearAndSetAdv(user, addon.getSettings().isOnJoinResetAdvancements(), addon.getSettings().getOnJoinGrantAdvancements());
|
||||||
|
@ -3,7 +3,14 @@ package world.bentobox.boxed.listeners;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.*;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@ -20,7 +27,7 @@ import org.bukkit.block.structure.Mirror;
|
|||||||
import org.bukkit.block.structure.StructureRotation;
|
import org.bukkit.block.structure.StructureRotation;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -54,34 +61,39 @@ import world.bentobox.boxed.objects.BoxedStructureBlock;
|
|||||||
import world.bentobox.boxed.objects.IslandStructures;
|
import world.bentobox.boxed.objects.IslandStructures;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author tastybento
|
* @author tastybento Place structures in areas after they are created
|
||||||
* Place structures in areas after they are created
|
|
||||||
*/
|
*/
|
||||||
public class NewAreaListener implements Listener {
|
public class NewAreaListener implements Listener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Structure record contains the name of the structure, the structure itself, where it was placed and
|
* Structure record contains the name of the structure, the structure itself,
|
||||||
* enums for rotation, mirror, and a flag to paste mobs or not.
|
* where it was placed and enums for rotation, mirror, and a flag to paste mobs
|
||||||
* @param name - name of structure
|
* or not.
|
||||||
|
*
|
||||||
|
* @param name - name of structure
|
||||||
* @param structure - Structure object
|
* @param structure - Structure object
|
||||||
* @param location - location where it has been placed
|
* @param location - location where it has been placed
|
||||||
* @param rot - rotation
|
* @param rot - rotation
|
||||||
* @param mirror - mirror setting
|
* @param mirror - mirror setting
|
||||||
* @param noMobs - if false, mobs not pasted
|
* @param noMobs - if false, mobs not pasted
|
||||||
*/
|
*/
|
||||||
public record StructureRecord(String name, Structure structure, Location location, StructureRotation rot, Mirror mirror, Boolean noMobs) {}
|
public record StructureRecord(String name, Structure structure, Location location, StructureRotation rot,
|
||||||
|
Mirror mirror, Boolean noMobs) {
|
||||||
|
}
|
||||||
|
|
||||||
private static final Map<Integer, EntityType> BUTCHER_ANIMALS = Map.of(0, EntityType.COW, 1, EntityType.SHEEP, 2, EntityType.PIG);
|
private static final Map<Integer, EntityType> BUTCHER_ANIMALS = Map.of(0, EntityType.COW, 1, EntityType.SHEEP, 2,
|
||||||
private static final List<BlockFace> CARDINALS = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST);
|
EntityType.PIG);
|
||||||
private static final List<String> JAR_STRUCTURES = List.of("bee", "pillager", "polar_bear", "axolotl", "allay", "parrot", "frog");
|
private static final List<BlockFace> CARDINALS = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST,
|
||||||
private static final List<String> STRUCTURES = List.of("ancient_city", "bastion_remnant", "bastion",
|
BlockFace.WEST);
|
||||||
"buried_treasure", "desert_pyramid", "end_city",
|
private static final List<String> JAR_STRUCTURES = List.of("bee", "pillager", "polar_bear", "axolotl", "allay",
|
||||||
"fortress", "igloo", "jungle_pyramid", "mansion", "mineshaft", "mineshaft_mesa",
|
"parrot", "frog");
|
||||||
"monument", "nether_fossil", "ocean_ruin_cold", "ocean_ruin_warm", "pillager_outpost",
|
private static final List<String> STRUCTURES = List.of("ancient_city", "bastion_remnant", "bastion",
|
||||||
"ruined_portal_desert", "ruined_portal_jungle", "ruined_portal_mountain", "ruined_portal_nether",
|
"buried_treasure", "desert_pyramid", "end_city", "fortress", "igloo", "jungle_pyramid", "mansion",
|
||||||
"ruined_portal_ocean", "ruined_portal_swamp", "ruined_portal", "shipwreck_beached",
|
"mineshaft", "mineshaft_mesa", "monument", "nether_fossil", "ocean_ruin_cold", "ocean_ruin_warm",
|
||||||
"shipwreck", "stronghold", "swamp_hut", "village_desert", "village_plains",
|
"pillager_outpost", "ruined_portal_desert", "ruined_portal_jungle", "ruined_portal_mountain",
|
||||||
"village_savanna", "village_snowy", "village_taiga");
|
"ruined_portal_nether", "ruined_portal_ocean", "ruined_portal_swamp", "ruined_portal", "shipwreck_beached",
|
||||||
|
"shipwreck", "stronghold", "swamp_hut", "village_desert", "village_plains", "village_savanna",
|
||||||
|
"village_snowy", "village_taiga");
|
||||||
private final Boxed addon;
|
private final Boxed addon;
|
||||||
private final File structureFile;
|
private final File structureFile;
|
||||||
private final Queue<StructureRecord> itemsToBuild = new LinkedList<>();
|
private final Queue<StructureRecord> itemsToBuild = new LinkedList<>();
|
||||||
@ -94,37 +106,35 @@ public class NewAreaListener implements Listener {
|
|||||||
private final Database<IslandStructures> handler;
|
private final Database<IslandStructures> handler;
|
||||||
private final Map<String, IslandStructures> islandStructureCache = new HashMap<>();
|
private final Map<String, IslandStructures> islandStructureCache = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param addon addon
|
* @param addon addon
|
||||||
*/
|
*/
|
||||||
public NewAreaListener(Boxed addon) {
|
public NewAreaListener(Boxed addon) {
|
||||||
this.addon = addon;
|
this.addon = addon;
|
||||||
// Save the default structures file from the jar
|
// Save the default structures file from the jar
|
||||||
addon.saveResource("structures.yml", false);
|
addon.saveResource("structures.yml", false);
|
||||||
// Load the config
|
// Load the config
|
||||||
structureFile = new File(addon.getDataFolder(), "structures.yml");
|
structureFile = new File(addon.getDataFolder(), "structures.yml");
|
||||||
// Get database ready
|
// Get database ready
|
||||||
handler = new Database<>(addon, IslandStructures.class);
|
handler = new Database<>(addon, IslandStructures.class);
|
||||||
// Try to build something every second
|
// Try to build something every second
|
||||||
runStructurePrinter(addon);
|
runStructurePrinter(addon);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runStructurePrinter(Boxed addon2) {
|
private void runStructurePrinter(Boxed addon2) {
|
||||||
Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), this::buildStructure, 20, 20);
|
Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), this::buildStructure, 20, 20);
|
||||||
for (String js : JAR_STRUCTURES) {
|
for (String js : JAR_STRUCTURES) {
|
||||||
addon.saveResource("structures/" + js + ".nbt", false);
|
addon.saveResource("structures/" + js + ".nbt", false);
|
||||||
File structureFile = new File(addon.getDataFolder(), "structures/" + js + ".nbt");
|
File structureFile = new File(addon.getDataFolder(), "structures/" + js + ".nbt");
|
||||||
try {
|
try {
|
||||||
Structure s = Bukkit.getStructureManager().loadStructure(structureFile);
|
Structure s = Bukkit.getStructureManager().loadStructure(structureFile);
|
||||||
Bukkit.getStructureManager().registerStructure(NamespacedKey.fromString("minecraft:boxed/" + js), s);
|
Bukkit.getStructureManager().registerStructure(NamespacedKey.fromString("minecraft:boxed/" + js), s);
|
||||||
addon.log("Loaded " + js + ".nbt");
|
addon.log("Loaded " + js + ".nbt");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
addon.logError("Error trying to load " + structureFile.getAbsolutePath());
|
addon.logError("Error trying to load " + structureFile.getAbsolutePath());
|
||||||
addon.getPlugin().logStacktrace(e);
|
addon.getPlugin().logStacktrace(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,398 +142,427 @@ public class NewAreaListener implements Listener {
|
|||||||
* Build something in the queue
|
* Build something in the queue
|
||||||
*/
|
*/
|
||||||
private void buildStructure() {
|
private void buildStructure() {
|
||||||
// Only kick off a build if there is something to build and something isn't already being built
|
// Only kick off a build if there is something to build and something isn't
|
||||||
if (!pasting && !itemsToBuild.isEmpty()) {
|
// already being built
|
||||||
// Build item
|
if (!pasting && !itemsToBuild.isEmpty()) {
|
||||||
StructureRecord item = itemsToBuild.poll();
|
// Build item
|
||||||
placeStructure(item);
|
StructureRecord item = itemsToBuild.poll();
|
||||||
}
|
placeStructure(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load known structures from the templates file.
|
* Load known structures from the templates file. This makes them available for
|
||||||
* This makes them available for admins to use in the boxed place file.
|
* admins to use in the boxed place file. If this is not done, then no
|
||||||
* If this is not done, then no structures (templates) will be available.
|
* structures (templates) will be available.
|
||||||
|
*
|
||||||
* @param event BentoBoxReadyEvent
|
* @param event BentoBoxReadyEvent
|
||||||
*/
|
*/
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
public void onBentoBoxReady(BentoBoxReadyEvent event) {
|
public void onBentoBoxReady(BentoBoxReadyEvent event) {
|
||||||
addon.saveResource("templates.yml", false);
|
addon.saveResource("templates.yml", false);
|
||||||
File templateFile = new File(addon.getDataFolder(), "templates.yml");
|
File templateFile = new File(addon.getDataFolder(), "templates.yml");
|
||||||
if (templateFile.exists()) {
|
if (templateFile.exists()) {
|
||||||
YamlConfiguration loader = YamlConfiguration.loadConfiguration(templateFile);
|
YamlConfiguration loader = YamlConfiguration.loadConfiguration(templateFile);
|
||||||
List<String> list = loader.getStringList("templates");
|
List<String> list = loader.getStringList("templates");
|
||||||
for (String struct : list) {
|
for (String struct : list) {
|
||||||
if (!struct.endsWith("/")) {
|
if (!struct.endsWith("/")) {
|
||||||
Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString(struct));
|
Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString(struct));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Track if a place has entered a structure.
|
* Track if a place has entered a structure.
|
||||||
|
*
|
||||||
* @param e PlayerMoveEvent
|
* @param e PlayerMoveEvent
|
||||||
*/
|
*/
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
public void onPlayerMove(PlayerMoveEvent e) {
|
public void onPlayerMove(PlayerMoveEvent e) {
|
||||||
// Ignore head movements
|
// Ignore head movements
|
||||||
if (!addon.inWorld(e.getFrom().getWorld()) || e.getFrom().toVector().equals(e.getTo().toVector())) {
|
if (!addon.inWorld(e.getFrom().getWorld()) || e.getFrom().toVector().equals(e.getTo().toVector())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Check where the player is
|
// Check where the player is
|
||||||
addon.getIslands().getIslandAt(e.getTo()).ifPresent(island -> {
|
addon.getIslands().getIslandAt(e.getTo()).ifPresent(island -> {
|
||||||
// See if island is in cache
|
// See if island is in cache
|
||||||
final String islandId = island.getUniqueId();
|
final String islandId = island.getUniqueId();
|
||||||
IslandStructures is = getIslandStructData(islandId);
|
IslandStructures is = getIslandStructData(islandId);
|
||||||
// Check if player is in any of the structures
|
// Check if player is in any of the structures
|
||||||
Map<BoundingBox, String> structures = e.getTo().getWorld().getEnvironment().equals(Environment.NETHER) ?
|
Map<BoundingBox, String> structures = e.getTo().getWorld().getEnvironment().equals(Environment.NETHER)
|
||||||
is.getNetherStructureBoundingBoxMap():is.getStructureBoundingBoxMap();
|
? is.getNetherStructureBoundingBoxMap()
|
||||||
for (Map.Entry<BoundingBox, String> en:structures.entrySet()) {
|
: is.getStructureBoundingBoxMap();
|
||||||
if (en.getKey().contains(e.getTo().toVector())) {
|
for (Map.Entry<BoundingBox, String> en : structures.entrySet()) {
|
||||||
for (String s: STRUCTURES) {
|
if (en.getKey().contains(e.getTo().toVector())) {
|
||||||
if (en.getValue().startsWith(s)) {
|
for (String s : STRUCTURES) {
|
||||||
giveAdvFromCriteria(e.getPlayer(), s);
|
if (en.getValue().startsWith(s)) {
|
||||||
}
|
giveAdvFromCriteria(e.getPlayer(), s);
|
||||||
}
|
}
|
||||||
//STRUCTURES.stream().filter(en.getValue()::startsWith).forEach(s -> giveAdvFromCriteria(e.getPlayer(), s));
|
}
|
||||||
}
|
// STRUCTURES.stream().filter(en.getValue()::startsWith).forEach(s ->
|
||||||
}
|
// giveAdvFromCriteria(e.getPlayer(), s));
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives a player all the advancements that have string as a named criteria
|
* Gives a player all the advancements that have string as a named criteria
|
||||||
|
*
|
||||||
* @param player - player
|
* @param player - player
|
||||||
* @param string - criteria
|
* @param string - criteria
|
||||||
*/
|
*/
|
||||||
private void giveAdvFromCriteria(Player player, String string) {
|
private void giveAdvFromCriteria(Player player, String string) {
|
||||||
// Give every advancement that requires a bastion
|
// Give every advancement that requires a bastion
|
||||||
Bukkit.advancementIterator().forEachRemaining(ad -> {
|
Bukkit.advancementIterator().forEachRemaining(ad -> {
|
||||||
if (!player.getAdvancementProgress(ad).isDone()) {
|
if (!player.getAdvancementProgress(ad).isDone()) {
|
||||||
for (String crit: ad.getCriteria()) {
|
for (String crit : ad.getCriteria()) {
|
||||||
if (crit.equals(string)) {
|
if (crit.equals(string)) {
|
||||||
// Set the criteria (it may not complete the advancement completely
|
// Set the criteria (it may not complete the advancement completely
|
||||||
player.getAdvancementProgress(ad).awardCriteria(crit);
|
player.getAdvancementProgress(ad).awardCriteria(crit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all the known island structures for this island
|
* Get all the known island structures for this island
|
||||||
|
*
|
||||||
* @param islandId - island ID
|
* @param islandId - island ID
|
||||||
* @return IslandStructures
|
* @return IslandStructures
|
||||||
*/
|
*/
|
||||||
private IslandStructures getIslandStructData(String islandId) {
|
private IslandStructures getIslandStructData(String islandId) {
|
||||||
// Return from cache if it exists
|
// Return from cache if it exists
|
||||||
if (islandStructureCache.containsKey(islandId)) {
|
if (islandStructureCache.containsKey(islandId)) {
|
||||||
return islandStructureCache.get(islandId);
|
return islandStructureCache.get(islandId);
|
||||||
}
|
}
|
||||||
// Get from database
|
// Get from database
|
||||||
IslandStructures struct = handler.objectExists(islandId) ? handler.loadObject(islandId) : new IslandStructures(islandId);
|
IslandStructures struct = handler.objectExists(islandId) ? handler.loadObject(islandId)
|
||||||
this.islandStructureCache.put(islandId, struct);
|
: new IslandStructures(islandId);
|
||||||
return struct;
|
this.islandStructureCache.put(islandId, struct);
|
||||||
|
return struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
public void onIslandCreated(IslandCreatedEvent event) {
|
public void onIslandCreated(IslandCreatedEvent event) {
|
||||||
setUpIsland(event.getIsland());
|
setUpIsland(event.getIsland());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
public void onIslandReset(IslandResettedEvent event) {
|
public void onIslandReset(IslandResettedEvent event) {
|
||||||
setUpIsland(event.getIsland());
|
setUpIsland(event.getIsland());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpIsland(Island island) {
|
private void setUpIsland(Island island) {
|
||||||
// Check if this island is in this game
|
// Check if this island is in this game
|
||||||
if (!(addon.inWorld(island.getWorld()))) {
|
if (!(addon.inWorld(island.getWorld()))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Load the latest config so that admins can change it on the fly without reloading
|
// Load the latest config so that admins can change it on the fly without
|
||||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(structureFile);
|
// reloading
|
||||||
Location center = island.getProtectionCenter();
|
YamlConfiguration config = YamlConfiguration.loadConfiguration(structureFile);
|
||||||
for (String env : config.getKeys(false)) {
|
Location center = island.getProtectionCenter();
|
||||||
Environment e = Enums.getIfPresent(Environment.class, env.toUpperCase(Locale.ENGLISH)).orNull();
|
for (String env : config.getKeys(false)) {
|
||||||
if (e == null) {
|
Environment e = Enums.getIfPresent(Environment.class, env.toUpperCase(Locale.ENGLISH)).orNull();
|
||||||
addon.logError("Error in structures.yml - unknown environment " + env);
|
if (e == null) {
|
||||||
} else {
|
addon.logError("Error in structures.yml - unknown environment " + env);
|
||||||
place(config.getConfigurationSection(env), center, e);
|
} else {
|
||||||
}
|
place(config.getConfigurationSection(env), center, e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void place(ConfigurationSection section, Location center, Environment env) {
|
private void place(ConfigurationSection section, Location center, Environment env) {
|
||||||
World world = env.equals(Environment.NORMAL) ? addon.getOverWorld() : addon.getNetherWorld();
|
World world = env.equals(Environment.NORMAL) ? addon.getOverWorld() : addon.getNetherWorld();
|
||||||
// Loop through the structures in the file - there could be more than one
|
if (world == null) {
|
||||||
for (String vector : section.getKeys(false)) {
|
return;
|
||||||
StructureRotation rot = StructureRotation.NONE;
|
}
|
||||||
Mirror mirror = Mirror.NONE;
|
// Loop through the structures in the file - there could be more than one
|
||||||
boolean noMobs = false;
|
for (String vector : section.getKeys(false)) {
|
||||||
String name = section.getString(vector);
|
StructureRotation rot = StructureRotation.NONE;
|
||||||
// Check for rotation
|
Mirror mirror = Mirror.NONE;
|
||||||
String[] split = name.split(",");
|
boolean noMobs = false;
|
||||||
if (split.length > 1) {
|
String name = section.getString(vector);
|
||||||
// Rotation
|
// Check for rotation
|
||||||
rot = Enums.getIfPresent(StructureRotation.class, split[1].strip().toUpperCase(Locale.ENGLISH)).or(StructureRotation.NONE);
|
String[] split = name.split(",");
|
||||||
name = split[0];
|
if (split.length > 1) {
|
||||||
}
|
// Rotation
|
||||||
if (split.length == 3) {
|
rot = Enums.getIfPresent(StructureRotation.class, split[1].strip().toUpperCase(Locale.ENGLISH))
|
||||||
// Mirror
|
.or(StructureRotation.NONE);
|
||||||
mirror = Enums.getIfPresent(Mirror.class, split[2].strip().toUpperCase(Locale.ENGLISH)).or(Mirror.NONE);
|
name = split[0];
|
||||||
}
|
}
|
||||||
if (split.length == 4) {
|
if (split.length == 3) {
|
||||||
noMobs = split[3].strip().toUpperCase(Locale.ENGLISH).equals("NO_MOBS");
|
// Mirror
|
||||||
}
|
mirror = Enums.getIfPresent(Mirror.class, split[2].strip().toUpperCase(Locale.ENGLISH)).or(Mirror.NONE);
|
||||||
// Load Structure
|
}
|
||||||
Structure s = Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString("minecraft:" + name));
|
if (split.length == 4) {
|
||||||
if (s == null) {
|
noMobs = split[3].strip().toUpperCase(Locale.ENGLISH).equals("NO_MOBS");
|
||||||
BentoBox.getInstance().logError("Could not load " + name);
|
}
|
||||||
return;
|
// Load Structure
|
||||||
}
|
Structure s = Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString("minecraft:" + name));
|
||||||
// Extract coords
|
if (s == null) {
|
||||||
String[] value = vector.split(",");
|
BentoBox.getInstance().logError("Could not load " + name);
|
||||||
if (value.length > 2) {
|
return;
|
||||||
int x = Integer.parseInt(value[0].strip()) + center.getBlockX();
|
}
|
||||||
int y = Integer.parseInt(value[1].strip());
|
// Extract coords
|
||||||
int z = Integer.parseInt(value[2].strip()) + center.getBlockZ();
|
String[] value = vector.split(",");
|
||||||
Location l = new Location(world, x, y, z);
|
if (value.length > 2) {
|
||||||
itemsToBuild.add(new StructureRecord(name, s, l, rot, mirror, noMobs));
|
int x = Integer.parseInt(value[0].strip()) + center.getBlockX();
|
||||||
} else {
|
int y = Integer.parseInt(value[1].strip());
|
||||||
addon.logError("Structure file syntax error: " + vector + ": " + Arrays.toString(value));
|
int z = Integer.parseInt(value[2].strip()) + center.getBlockZ();
|
||||||
}
|
Location l = new Location(world, x, y, z);
|
||||||
}
|
itemsToBuild.add(new StructureRecord(name, s, l, rot, mirror, noMobs));
|
||||||
|
} else {
|
||||||
|
addon.logError("Structure file syntax error: " + vector + ": " + Arrays.toString(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void placeStructure(StructureRecord item) {
|
private void placeStructure(StructureRecord item) {
|
||||||
// Set the semaphore - only paste one at a time
|
// Set the semaphore - only paste one at a time
|
||||||
pasting = true;
|
pasting = true;
|
||||||
// Place the structure
|
// Place the structure
|
||||||
item.structure().place(item.location(), true, item.rot(), item.mirror(), -1, 1, rand);
|
item.structure().place(item.location(), true, item.rot(), item.mirror(), -1, 1, rand);
|
||||||
addon.log(item.name() + " placed at " + item.location().getWorld().getName() + " " + Util.xyz(item.location().toVector()));
|
addon.log(item.name() + " placed at " + item.location().getWorld().getName() + " "
|
||||||
// Remove any jigsaw artifacts
|
+ Util.xyz(item.location().toVector()));
|
||||||
BoundingBox bb = removeJigsaw(item);
|
// Remove any jigsaw artifacts
|
||||||
// Store it for future reference
|
BoundingBox bb = removeJigsaw(item);
|
||||||
addon.getIslands().getIslandAt(item.location()).map(Island::getUniqueId).ifPresent(id -> {
|
// Store it for future reference
|
||||||
addon.log("Saved " + item.name());
|
addon.getIslands().getIslandAt(item.location()).map(Island::getUniqueId).ifPresent(id -> {
|
||||||
if (item.location().getWorld().getEnvironment().equals(Environment.NETHER)) {
|
addon.log("Saved " + item.name());
|
||||||
getIslandStructData(id).addNetherStructure(bb, item.name());
|
if (item.location().getWorld().getEnvironment().equals(Environment.NETHER)) {
|
||||||
} else {
|
getIslandStructData(id).addNetherStructure(bb, item.name());
|
||||||
getIslandStructData(id).addStructure(bb, item.name());
|
} else {
|
||||||
}
|
getIslandStructData(id).addStructure(bb, item.name());
|
||||||
handler.saveObjectAsync(getIslandStructData(id));
|
}
|
||||||
});
|
handler.saveObjectAsync(getIslandStructData(id));
|
||||||
// Clear the semaphore
|
});
|
||||||
pasting = false;
|
// Clear the semaphore
|
||||||
|
pasting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes Jigsaw blocks from a placed structure. Fills underwater ruins with water.
|
* Removes Jigsaw blocks from a placed structure. Fills underwater ruins with
|
||||||
|
* water.
|
||||||
|
*
|
||||||
* @param item - record of what's required
|
* @param item - record of what's required
|
||||||
* @return the resulting bounding box of the structure
|
* @return the resulting bounding box of the structure
|
||||||
*/
|
*/
|
||||||
public static BoundingBox removeJigsaw(StructureRecord item) {
|
public static BoundingBox removeJigsaw(StructureRecord item) {
|
||||||
Location loc = item.location();
|
Location loc = item.location();
|
||||||
Structure structure = item.structure();
|
Structure structure = item.structure();
|
||||||
StructureRotation structureRotation = item.rot();
|
StructureRotation structureRotation = item.rot();
|
||||||
String key = item.name();
|
String key = item.name();
|
||||||
|
|
||||||
Location otherCorner = switch (structureRotation) {
|
Location otherCorner = switch (structureRotation) {
|
||||||
|
|
||||||
case CLOCKWISE_180 -> loc.clone().add(new Vector(-structure.getSize().getX(), structure.getSize().getY(), -structure.getSize().getZ()));
|
case CLOCKWISE_180 -> loc.clone()
|
||||||
|
.add(new Vector(-structure.getSize().getX(), structure.getSize().getY(), -structure.getSize().getZ()));
|
||||||
|
|
||||||
case CLOCKWISE_90 -> loc.clone().add(new Vector(-structure.getSize().getZ(), structure.getSize().getY(), structure.getSize().getX()));
|
case CLOCKWISE_90 -> loc.clone()
|
||||||
|
.add(new Vector(-structure.getSize().getZ(), structure.getSize().getY(), structure.getSize().getX()));
|
||||||
|
|
||||||
case COUNTERCLOCKWISE_90 -> loc.clone().add(new Vector(structure.getSize().getZ(), structure.getSize().getY(), -structure.getSize().getX()));
|
case COUNTERCLOCKWISE_90 -> loc.clone()
|
||||||
|
.add(new Vector(structure.getSize().getZ(), structure.getSize().getY(), -structure.getSize().getX()));
|
||||||
|
|
||||||
case NONE -> loc.clone().add(new Vector(structure.getSize().getX(), structure.getSize().getY(), structure.getSize().getZ()));
|
case NONE -> loc.clone()
|
||||||
|
.add(new Vector(structure.getSize().getX(), structure.getSize().getY(), structure.getSize().getZ()));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BoundingBox bb = BoundingBox.of(loc, otherCorner);
|
BoundingBox bb = BoundingBox.of(loc, otherCorner);
|
||||||
for (int x = (int) bb.getMinX(); x <= bb.getMaxX(); x++) {
|
for (int x = (int) bb.getMinX(); x <= bb.getMaxX(); x++) {
|
||||||
for (int y = (int) bb.getMinY(); y <= bb.getMaxY(); y++) {
|
for (int y = (int) bb.getMinY(); y <= bb.getMaxY(); y++) {
|
||||||
for (int z = (int) bb.getMinZ(); z <= bb.getMaxZ(); z++) {
|
for (int z = (int) bb.getMinZ(); z <= bb.getMaxZ(); z++) {
|
||||||
Block b = loc.getWorld().getBlockAt(x, y, z);
|
Block b = loc.getWorld().getBlockAt(x, y, z);
|
||||||
if (b.getType().equals(Material.JIGSAW)) {
|
if (b.getType().equals(Material.JIGSAW)) {
|
||||||
// I would like to read the data from the block and do something with it!
|
// I would like to read the data from the block and do something with it!
|
||||||
processJigsaw(b, structureRotation, !item.noMobs());
|
processJigsaw(b, structureRotation, !item.noMobs());
|
||||||
} else if (b.getType().equals(Material.STRUCTURE_BLOCK)) {
|
} else if (b.getType().equals(Material.STRUCTURE_BLOCK)) {
|
||||||
processStructureBlock(b);
|
processStructureBlock(b);
|
||||||
}
|
}
|
||||||
// Set water blocks for underwater ruins
|
// Set water blocks for underwater ruins
|
||||||
if (key.contains("underwater_ruin") && b.getType().equals(Material.AIR)) {
|
if (key.contains("underwater_ruin") && b.getType().equals(Material.AIR)) {
|
||||||
b.setType(Material.WATER);
|
b.setType(Material.WATER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a structure block. Sets it to a structure void at a minimum.
|
* Process a structure block. Sets it to a structure void at a minimum. If the
|
||||||
* If the structure block has metadata indicating it is a chest, then it will fill
|
* structure block has metadata indicating it is a chest, then it will fill the
|
||||||
* the chest with a buried treasure loot. If it is waterlogged, then it will change
|
* chest with a buried treasure loot. If it is waterlogged, then it will change
|
||||||
* the void to water.
|
* the void to water.
|
||||||
|
*
|
||||||
* @param b structure block
|
* @param b structure block
|
||||||
*/
|
*/
|
||||||
private static void processStructureBlock(Block b) {
|
private static void processStructureBlock(Block b) {
|
||||||
// I would like to read the data from the block and do something with it!
|
// I would like to read the data from the block and do something with it!
|
||||||
String data = nmsData(b);
|
String data = nmsData(b);
|
||||||
BoxedStructureBlock bsb = gson.fromJson(data, BoxedStructureBlock.class);
|
BoxedStructureBlock bsb = gson.fromJson(data, BoxedStructureBlock.class);
|
||||||
b.setType(Material.STRUCTURE_VOID);
|
b.setType(Material.STRUCTURE_VOID);
|
||||||
Enums.getIfPresent(EntityType.class, bsb.getMetadata().toUpperCase(Locale.ENGLISH)).toJavaUtil()
|
Enums.getIfPresent(EntityType.class, bsb.getMetadata().toUpperCase(Locale.ENGLISH)).toJavaUtil()
|
||||||
.ifPresent(type -> b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type));
|
.ifPresent(type -> b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type));
|
||||||
if (bsb.getMetadata().contains("chest")) {
|
if (bsb.getMetadata().contains("chest")) {
|
||||||
Block downBlock = b.getRelative(BlockFace.DOWN);
|
Block downBlock = b.getRelative(BlockFace.DOWN);
|
||||||
if (downBlock.getType().equals(Material.CHEST)) {
|
if (downBlock.getType().equals(Material.CHEST)) {
|
||||||
Chest chest = (Chest)downBlock.getState();
|
Chest chest = (Chest) downBlock.getState();
|
||||||
// TODO: for now just give treasure
|
// TODO: for now just give treasure
|
||||||
chest.setLootTable(LootTables.BURIED_TREASURE.getLootTable());
|
chest.setLootTable(LootTables.BURIED_TREASURE.getLootTable());
|
||||||
chest.update();
|
chest.update();
|
||||||
if (chest.getBlockData() instanceof Waterlogged wl) {
|
if (chest.getBlockData() instanceof Waterlogged wl) {
|
||||||
if (wl.isWaterlogged()) {
|
if (wl.isWaterlogged()) {
|
||||||
b.setType(Material.WATER);
|
b.setType(Material.WATER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processJigsaw(Block b, StructureRotation structureRotation, boolean pasteMobs) {
|
private static void processJigsaw(Block b, StructureRotation structureRotation, boolean pasteMobs) {
|
||||||
String data = nmsData(b);
|
String data = nmsData(b);
|
||||||
BoxedJigsawBlock bjb = gson.fromJson(data, BoxedJigsawBlock.class);
|
BoxedJigsawBlock bjb = gson.fromJson(data, BoxedJigsawBlock.class);
|
||||||
String finalState = correctDirection(bjb.getFinal_state(), structureRotation);
|
String finalState = correctDirection(bjb.getFinal_state(), structureRotation);
|
||||||
BlockData bd = Bukkit.createBlockData(finalState);
|
BlockData bd = Bukkit.createBlockData(finalState);
|
||||||
b.setBlockData(bd);
|
b.setBlockData(bd);
|
||||||
if (!bjb.getPool().equalsIgnoreCase("minecraft:empty") && pasteMobs) {
|
if (!bjb.getPool().equalsIgnoreCase("minecraft:empty") && pasteMobs) {
|
||||||
spawnMob(b, bjb);
|
spawnMob(b, bjb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void spawnMob(Block b, BoxedJigsawBlock bjb) {
|
private static void spawnMob(Block b, BoxedJigsawBlock bjb) {
|
||||||
// bjb.getPool contains a lot more than just mobs, so we have to filter it to see if any mobs are in there. This list may need to grow in the future
|
// bjb.getPool contains a lot more than just mobs, so we have to filter it to
|
||||||
EntityType type =
|
// see if any mobs are in there. This list may need to grow in the future
|
||||||
switch (bjb.getPool()) {
|
EntityType type = switch (bjb.getPool()) {
|
||||||
case "minecraft:bastion/mobs/piglin" -> EntityType.PIGLIN;
|
case "minecraft:bastion/mobs/piglin" -> EntityType.PIGLIN;
|
||||||
case "minecraft:bastion/mobs/hoglin" -> EntityType.HOGLIN;
|
case "minecraft:bastion/mobs/hoglin" -> EntityType.HOGLIN;
|
||||||
case "minecraft:bastion/mobs/piglin_melee" -> EntityType.PIGLIN_BRUTE;
|
case "minecraft:bastion/mobs/piglin_melee" -> EntityType.PIGLIN_BRUTE;
|
||||||
case "minecraft:village/common/cats" -> EntityType.CAT;
|
case "minecraft:village/common/cats" -> EntityType.CAT;
|
||||||
case "minecraft:village/common/horses" -> EntityType.HORSE;
|
case "minecraft:village/common/horses" -> EntityType.HORSE;
|
||||||
case "minecraft:village/common/sheep" -> EntityType.SHEEP;
|
case "minecraft:village/common/sheep" -> EntityType.SHEEP;
|
||||||
case "minecraft:village/common/pigs" -> EntityType.PIG;
|
case "minecraft:village/common/pigs" -> EntityType.PIG;
|
||||||
case "minecraft:village/common/cows" -> EntityType.COW;
|
case "minecraft:village/common/cows" -> EntityType.COW;
|
||||||
case "minecraft:village/common/iron_golem" -> EntityType.IRON_GOLEM;
|
case "minecraft:village/common/iron_golem" -> EntityType.IRON_GOLEM;
|
||||||
case "minecraft:village/common/butcher_animals", "minecraft:village/common/animals" -> BUTCHER_ANIMALS.get(rand.nextInt(3));
|
case "minecraft:village/common/butcher_animals", "minecraft:village/common/animals" ->
|
||||||
default -> null;
|
BUTCHER_ANIMALS.get(rand.nextInt(3));
|
||||||
};
|
default -> null;
|
||||||
// Boxed
|
};
|
||||||
if (type == null && bjb.getPool().startsWith("minecraft:boxed/")) {
|
// Boxed
|
||||||
String entString = bjb.getPool().toUpperCase(Locale.ENGLISH).substring(16, bjb.getPool().length());
|
if (type == null && bjb.getPool().startsWith("minecraft:boxed/")) {
|
||||||
type = Enums.getIfPresent(EntityType.class, entString).orNull();
|
String entString = bjb.getPool().toUpperCase(Locale.ENGLISH).substring(16, bjb.getPool().length());
|
||||||
}
|
type = Enums.getIfPresent(EntityType.class, entString).orNull();
|
||||||
// Villagers
|
}
|
||||||
if (bjb.getPool().contains("zombie/villagers")) {
|
// Villagers
|
||||||
type = EntityType.ZOMBIE_VILLAGER;
|
if (bjb.getPool().contains("zombie/villagers")) {
|
||||||
} else if (bjb.getPool().contains("villagers")) {
|
type = EntityType.ZOMBIE_VILLAGER;
|
||||||
type = EntityType.VILLAGER;
|
} else if (bjb.getPool().contains("villagers")) {
|
||||||
}
|
type = EntityType.VILLAGER;
|
||||||
//if (type == null) {
|
}
|
||||||
// BentoBox.getInstance().logDebug(bjb.getPool());
|
// if (type == null) {
|
||||||
//}
|
// BentoBox.getInstance().logDebug(bjb.getPool());
|
||||||
// Spawn it
|
// }
|
||||||
if (type != null) {
|
// Spawn it
|
||||||
Entity e = b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type);
|
if (type != null) {
|
||||||
if (e != null) {
|
Entity e = b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type);
|
||||||
e.setPersistent(true);
|
if (e != null) {
|
||||||
}
|
e.setPersistent(true);
|
||||||
//BentoBox.getInstance().logDebug("Spawned a " + type + " at " + b.getRelative(BlockFace.UP).getLocation());
|
}
|
||||||
}
|
// BentoBox.getInstance().logDebug("Spawned a " + type + " at " +
|
||||||
|
// b.getRelative(BlockFace.UP).getLocation());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Corrects the direction of a block based on the structure's rotation
|
* Corrects the direction of a block based on the structure's rotation
|
||||||
* @param finalState - the final block state of the block, which may include a facing: direction
|
*
|
||||||
* @param sr - the structure's rotation
|
* @param finalState - the final block state of the block, which may include a
|
||||||
|
* facing: direction
|
||||||
|
* @param sr - the structure's rotation
|
||||||
* @return a rewritten blockstate with the updated direction, if required
|
* @return a rewritten blockstate with the updated direction, if required
|
||||||
*/
|
*/
|
||||||
private static String correctDirection(String finalState, StructureRotation sr) {
|
private static String correctDirection(String finalState, StructureRotation sr) {
|
||||||
if (sr.equals(StructureRotation.NONE)) {
|
if (sr.equals(StructureRotation.NONE)) {
|
||||||
// No change
|
// No change
|
||||||
return finalState;
|
return finalState;
|
||||||
}
|
}
|
||||||
BlockFace oldDirection = getDirection(finalState);
|
BlockFace oldDirection = getDirection(finalState);
|
||||||
BlockFace newDirection = getNewDirection(oldDirection, sr);
|
BlockFace newDirection = getNewDirection(oldDirection, sr);
|
||||||
if (newDirection.equals(BlockFace.SELF)) {
|
if (newDirection.equals(BlockFace.SELF)) {
|
||||||
// No change - shouldn't happen, but just in case
|
// No change - shouldn't happen, but just in case
|
||||||
return finalState;
|
return finalState;
|
||||||
}
|
}
|
||||||
return finalState.replace(oldDirection.name().toLowerCase(Locale.ENGLISH), newDirection.name().toLowerCase(Locale.ENGLISH));
|
return finalState.replace(oldDirection.name().toLowerCase(Locale.ENGLISH),
|
||||||
|
newDirection.name().toLowerCase(Locale.ENGLISH));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjusts the direction based on the StructureRotation
|
* Adjusts the direction based on the StructureRotation
|
||||||
|
*
|
||||||
* @param oldDirection the old direction to adjust
|
* @param oldDirection the old direction to adjust
|
||||||
* @param sr the structure rotation
|
* @param sr the structure rotation
|
||||||
* @return the new direction, or SELF if something weird happens
|
* @return the new direction, or SELF if something weird happens
|
||||||
*/
|
*/
|
||||||
private static BlockFace getNewDirection(BlockFace oldDirection, StructureRotation sr) {
|
private static BlockFace getNewDirection(BlockFace oldDirection, StructureRotation sr) {
|
||||||
if (sr.equals(StructureRotation.CLOCKWISE_180)) {
|
if (sr.equals(StructureRotation.CLOCKWISE_180)) {
|
||||||
return oldDirection.getOppositeFace();
|
return oldDirection.getOppositeFace();
|
||||||
} else if (sr.equals(StructureRotation.CLOCKWISE_90)) {
|
} else if (sr.equals(StructureRotation.CLOCKWISE_90)) {
|
||||||
return switch(oldDirection) {
|
return switch (oldDirection) {
|
||||||
case EAST -> BlockFace.SOUTH;
|
case EAST -> BlockFace.SOUTH;
|
||||||
case NORTH -> BlockFace.EAST;
|
case NORTH -> BlockFace.EAST;
|
||||||
case SOUTH -> BlockFace.WEST;
|
case SOUTH -> BlockFace.WEST;
|
||||||
case WEST -> BlockFace.NORTH;
|
case WEST -> BlockFace.NORTH;
|
||||||
default -> BlockFace.SELF;
|
default -> BlockFace.SELF;
|
||||||
};
|
};
|
||||||
} else if (sr.equals(StructureRotation.COUNTERCLOCKWISE_90)) {
|
} else if (sr.equals(StructureRotation.COUNTERCLOCKWISE_90)) {
|
||||||
return switch(oldDirection) {
|
return switch (oldDirection) {
|
||||||
case EAST -> BlockFace.NORTH;
|
case EAST -> BlockFace.NORTH;
|
||||||
case NORTH -> BlockFace.WEST;
|
case NORTH -> BlockFace.WEST;
|
||||||
case SOUTH -> BlockFace.EAST;
|
case SOUTH -> BlockFace.EAST;
|
||||||
case WEST -> BlockFace.SOUTH;
|
case WEST -> BlockFace.SOUTH;
|
||||||
default -> BlockFace.SELF;
|
default -> BlockFace.SELF;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return BlockFace.SELF;
|
return BlockFace.SELF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks for north, south, east, west in the blockstate.
|
* Looks for north, south, east, west in the blockstate.
|
||||||
|
*
|
||||||
* @param finalState - the final block state of the block
|
* @param finalState - the final block state of the block
|
||||||
* @return direction, if found, otherwise SELF
|
* @return direction, if found, otherwise SELF
|
||||||
*/
|
*/
|
||||||
private static BlockFace getDirection(String finalState) {
|
private static BlockFace getDirection(String finalState) {
|
||||||
return CARDINALS.stream().filter(bf -> finalState.contains(bf.name().toLowerCase(Locale.ENGLISH))).findFirst().orElse(BlockFace.SELF);
|
return CARDINALS.stream().filter(bf -> finalState.contains(bf.name().toLowerCase(Locale.ENGLISH))).findFirst()
|
||||||
|
.orElse(BlockFace.SELF);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String nmsData(Block block) {
|
private static String nmsData(Block block) {
|
||||||
Location w = block.getLocation();
|
Location w = block.getLocation();
|
||||||
CraftWorld cw = (CraftWorld) w.getWorld(); // CraftWorld is NMS one
|
CraftWorld cw = (CraftWorld) w.getWorld(); // CraftWorld is NMS one
|
||||||
// for 1.13+ (we have use WorldServer)
|
// for 1.13+ (we have use WorldServer)
|
||||||
TileEntity te = cw.getHandle().c_(new BlockPosition(w.getBlockX(), w.getBlockY(), w.getBlockZ()));
|
TileEntity te = cw.getHandle().c_(new BlockPosition(w.getBlockX(), w.getBlockY(), w.getBlockZ()));
|
||||||
try {
|
try {
|
||||||
PacketPlayOutTileEntityData packet = ((PacketPlayOutTileEntityData) te.h()); // get update packet from NMS object
|
PacketPlayOutTileEntityData packet = ((PacketPlayOutTileEntityData) te.h()); // get update packet from NMS
|
||||||
// here we should use reflection because "c" field isn't accessible
|
// object
|
||||||
Field f = packet.getClass().getDeclaredField("c"); // get field
|
// here we should use reflection because "c" field isn't accessible
|
||||||
f.setAccessible(true); // make it available
|
Field f = packet.getClass().getDeclaredField("c"); // get field
|
||||||
NBTTagCompound nbtTag = (NBTTagCompound) f.get(packet);
|
f.setAccessible(true); // make it available
|
||||||
return nbtTag.toString(); // this will show what you want
|
NBTTagCompound nbtTag = (NBTTagCompound) f.get(packet);
|
||||||
} catch (Exception exc) {
|
return nbtTag.toString(); // this will show what you want
|
||||||
exc.printStackTrace();
|
} catch (Exception exc) {
|
||||||
}
|
exc.printStackTrace();
|
||||||
return "Nothing";
|
}
|
||||||
|
return "Nothing";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,9 @@ boxed:
|
|||||||
# Sub-command of main player command that will be run on each player command call.
|
# Sub-command of main player command that will be run on each player command call.
|
||||||
# By default, it is sub-command 'go'.
|
# By default, it is sub-command 'go'.
|
||||||
default-action: go
|
default-action: go
|
||||||
|
# Ignore advancements
|
||||||
|
# If this is true, advancements will not change the size of the box.
|
||||||
|
ignore-advancements: false
|
||||||
# Announce advancements. We recommend you set the game rule `/gamerule announceAdvancements false`
|
# Announce advancements. We recommend you set the game rule `/gamerule announceAdvancements false`
|
||||||
# but that blocks all new advancement announcements. This setting tells Boxed to broadcast new advancements.
|
# but that blocks all new advancement announcements. This setting tells Boxed to broadcast new advancements.
|
||||||
broadcast-advancements: false
|
broadcast-advancements: false
|
||||||
|
Loading…
Reference in New Issue
Block a user