mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-03-02 11:12:28 +01:00
Add support for Trial Spawners to Blueprints
This commit is contained in:
parent
8d89d622c9
commit
105549b901
@ -19,6 +19,7 @@ import org.bukkit.block.Block;
|
|||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.block.Sign;
|
import org.bukkit.block.Sign;
|
||||||
|
import org.bukkit.block.TrialSpawner;
|
||||||
import org.bukkit.block.data.Attachable;
|
import org.bukkit.block.data.Attachable;
|
||||||
import org.bukkit.block.sign.Side;
|
import org.bukkit.block.sign.Side;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
@ -38,6 +39,7 @@ import world.bentobox.bentobox.api.user.User;
|
|||||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
|
||||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
|
||||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
|
||||||
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintTrialSpawner;
|
||||||
import world.bentobox.bentobox.hooks.FancyNpcsHook;
|
import world.bentobox.bentobox.hooks.FancyNpcsHook;
|
||||||
import world.bentobox.bentobox.hooks.MythicMobsHook;
|
import world.bentobox.bentobox.hooks.MythicMobsHook;
|
||||||
import world.bentobox.bentobox.hooks.ZNPCsPlusHook;
|
import world.bentobox.bentobox.hooks.ZNPCsPlusHook;
|
||||||
@ -294,6 +296,13 @@ public class BlueprintClipboard {
|
|||||||
if (blockState instanceof CreatureSpawner spawner) {
|
if (blockState instanceof CreatureSpawner spawner) {
|
||||||
b.setCreatureSpawner(getSpawner(spawner));
|
b.setCreatureSpawner(getSpawner(spawner));
|
||||||
}
|
}
|
||||||
|
if (blockState instanceof TrialSpawner spawner) {
|
||||||
|
if (spawner.isOminous()) {
|
||||||
|
b.setTrialSpawner(new BlueprintTrialSpawner(true, spawner.getOminousConfiguration()));
|
||||||
|
} else {
|
||||||
|
b.setTrialSpawner(new BlueprintTrialSpawner(false, spawner.getNormalConfiguration()));
|
||||||
|
}
|
||||||
|
}
|
||||||
// Banners
|
// Banners
|
||||||
if (blockState instanceof Banner banner) {
|
if (blockState instanceof Banner banner) {
|
||||||
b.setBannerPatterns(banner.getPatterns());
|
b.setBannerPatterns(banner.getPatterns());
|
||||||
|
@ -34,6 +34,12 @@ public class BlueprintBlock {
|
|||||||
private Map<Integer, ItemStack> inventory;
|
private Map<Integer, ItemStack> inventory;
|
||||||
@Expose
|
@Expose
|
||||||
private BlueprintCreatureSpawner creatureSpawner;
|
private BlueprintCreatureSpawner creatureSpawner;
|
||||||
|
/**
|
||||||
|
* @since 3.4.2
|
||||||
|
*/
|
||||||
|
@Expose
|
||||||
|
private BlueprintTrialSpawner trialSpawner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Since 1.15.2
|
* Since 1.15.2
|
||||||
*/
|
*/
|
||||||
@ -217,4 +223,18 @@ public class BlueprintBlock {
|
|||||||
this.signLines2 = signLines;
|
this.signLines2 = signLines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the trialSpawner
|
||||||
|
*/
|
||||||
|
public BlueprintTrialSpawner getTrialSpawner() {
|
||||||
|
return trialSpawner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param trialSpawner the trialSpawner to set
|
||||||
|
*/
|
||||||
|
public void setTrialSpawner(BlueprintTrialSpawner trialSpawner) {
|
||||||
|
this.trialSpawner = trialSpawner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,310 @@
|
|||||||
|
package world.bentobox.bentobox.blueprints.dataobjects;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.block.spawner.SpawnRule;
|
||||||
|
import org.bukkit.block.spawner.SpawnerEntry;
|
||||||
|
import org.bukkit.entity.EntitySnapshot;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.loot.LootTable;
|
||||||
|
import org.bukkit.spawner.TrialSpawnerConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tastybento
|
||||||
|
* @since 3.4.2
|
||||||
|
*/
|
||||||
|
public class BlueprintTrialSpawner {
|
||||||
|
|
||||||
|
@Expose
|
||||||
|
private boolean ominous;
|
||||||
|
@Expose
|
||||||
|
private EntityType spawnedType;
|
||||||
|
@Expose
|
||||||
|
private double addSimulEnts;
|
||||||
|
@Expose
|
||||||
|
private double addSpawnsB4Cool;
|
||||||
|
@Expose
|
||||||
|
private double baseSimEnts;
|
||||||
|
@Expose
|
||||||
|
private int delay;
|
||||||
|
@Expose
|
||||||
|
private @NotNull Map<LootTableSerial, Integer> lootTableMap = new HashMap<>();
|
||||||
|
@Expose
|
||||||
|
private int spawnRange;
|
||||||
|
@Expose
|
||||||
|
private int requiredPlayerRange;
|
||||||
|
@Expose
|
||||||
|
private int playerRange;
|
||||||
|
@Expose
|
||||||
|
private double baseSpawnsB4Cool;
|
||||||
|
@Expose
|
||||||
|
private List<PotentialSpawns> potentialSpawns;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record of nameSpace and key
|
||||||
|
*/
|
||||||
|
record LootTableSerial(@Expose String nameSpace, @Expose String key) {
|
||||||
|
}
|
||||||
|
|
||||||
|
record PotentialSpawns(@Expose String snapshot, @Expose Map<String, Object> spawnrule, @Expose int spawnWeight) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlueprintTrialSpawner(boolean ominous, TrialSpawnerConfiguration spawner) {
|
||||||
|
this.ominous = ominous;
|
||||||
|
this.addSimulEnts = spawner.getAdditionalSimultaneousEntities();
|
||||||
|
this.addSpawnsB4Cool = spawner.getAdditionalSpawnsBeforeCooldown();
|
||||||
|
this.baseSimEnts = spawner.getBaseSimultaneousEntities();
|
||||||
|
this.baseSpawnsB4Cool = spawner.getBaseSpawnsBeforeCooldown();
|
||||||
|
this.lootTableMap = convertToLootTableSerial(spawner.getPossibleRewards());
|
||||||
|
this.spawnRange = spawner.getSpawnRange();
|
||||||
|
this.requiredPlayerRange = spawner.getRequiredPlayerRange();
|
||||||
|
// Spawns
|
||||||
|
potentialSpawns = spawner.getPotentialSpawns().stream().map(se -> {
|
||||||
|
EntitySnapshot snapshot = se.getSnapshot();
|
||||||
|
SpawnRule spawnRule = se.getSpawnRule();
|
||||||
|
return new PotentialSpawns(snapshot.getAsString(), spawnRule == null ? null : spawnRule.serialize(),
|
||||||
|
se.getSpawnWeight());
|
||||||
|
// Missing
|
||||||
|
// se.getEquipment().getEquipmentLootTable();
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
if (potentialSpawns.isEmpty()) {
|
||||||
|
potentialSpawns = null;
|
||||||
|
this.spawnedType = spawner.getSpawnedType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<LootTableSerial, Integer> convertToLootTableSerial(Map<LootTable, Integer> possibleRewards) {
|
||||||
|
// Use streams to map entries from LootTable to LootTableSerial
|
||||||
|
return possibleRewards.entrySet().stream().collect(Collectors.toMap(entry -> { // Convert LootTable to LootTableSerial
|
||||||
|
NamespacedKey key = entry.getKey().getKey();
|
||||||
|
return new LootTableSerial(key.getNamespace(), key.getKey());
|
||||||
|
}, Map.Entry::getValue // Keep the Integer value unchanged
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to convert Map<LootTableSerial, Integer> back to Map<LootTable, Integer>
|
||||||
|
private Map<LootTable, Integer> convertToLootTable(Map<LootTableSerial, Integer> serializedRewards) {
|
||||||
|
Map<LootTable, Integer> result = new HashMap<>();
|
||||||
|
for (Map.Entry<LootTableSerial, Integer> entry : serializedRewards.entrySet()) {
|
||||||
|
LootTableSerial lootTableSerial = entry.getKey();
|
||||||
|
Integer value = Math.max(1, entry.getValue()); // weight has to be at least 1
|
||||||
|
|
||||||
|
// Reconstruct the NamespacedKey
|
||||||
|
NamespacedKey key = new NamespacedKey(lootTableSerial.nameSpace(), lootTableSerial.key());
|
||||||
|
|
||||||
|
// Fetch the LootTable using Bukkit
|
||||||
|
LootTable lootTable = Bukkit.getLootTable(key);
|
||||||
|
|
||||||
|
if (lootTable != null) { // Ensure the LootTable exists
|
||||||
|
result.put(lootTable, value);
|
||||||
|
} else {
|
||||||
|
System.err.println("LootTable not found for key: " + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the trial spawner
|
||||||
|
* @param spawner trial spawner config
|
||||||
|
* @return true if trial spawner is ominous, false if normal
|
||||||
|
*/
|
||||||
|
public boolean configTrialSpawner(TrialSpawnerConfiguration spawner) {
|
||||||
|
spawner.setAdditionalSimultaneousEntities((float) addSimulEnts);
|
||||||
|
spawner.setAdditionalSpawnsBeforeCooldown((float) addSpawnsB4Cool);
|
||||||
|
spawner.setBaseSimultaneousEntities((float) baseSimEnts);
|
||||||
|
spawner.setBaseSpawnsBeforeCooldown((float) baseSpawnsB4Cool);
|
||||||
|
spawner.setDelay(delay);
|
||||||
|
spawner.setSpawnRange(spawnRange);
|
||||||
|
spawner.setPossibleRewards(convertToLootTable(lootTableMap)); // Note to future me: if the weight in the map is zero code stops running at this pojnt!
|
||||||
|
spawner.setRequiredPlayerRange(requiredPlayerRange);
|
||||||
|
// Either/or spawned type
|
||||||
|
if (spawnedType != null) {
|
||||||
|
spawner.setSpawnedType(spawnedType);
|
||||||
|
} else {
|
||||||
|
spawner.setPotentialSpawns(this.potentialSpawns.stream().map(ps -> {
|
||||||
|
EntitySnapshot snapshot = Bukkit.getEntityFactory().createEntitySnapshot(ps.snapshot());
|
||||||
|
SpawnRule rule = ps.spawnrule() != null ? SpawnRule.deserialize(ps.spawnrule()) : null;
|
||||||
|
return new SpawnerEntry(snapshot, ps.spawnWeight(), rule);
|
||||||
|
}).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
return this.isOminous();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ominous
|
||||||
|
*/
|
||||||
|
public boolean isOminous() {
|
||||||
|
return ominous;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ominous the ominous to set
|
||||||
|
*/
|
||||||
|
public void setOminous(boolean ominous) {
|
||||||
|
this.ominous = ominous;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the spawnedType
|
||||||
|
*/
|
||||||
|
public EntityType getSpawnedType() {
|
||||||
|
return spawnedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param spawnedType the spawnedType to set
|
||||||
|
*/
|
||||||
|
public void setSpawnedType(EntityType spawnedType) {
|
||||||
|
this.spawnedType = spawnedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the addSimulEnts
|
||||||
|
*/
|
||||||
|
public double getAddSimulEnts() {
|
||||||
|
return addSimulEnts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param addSimulEnts the addSimulEnts to set
|
||||||
|
*/
|
||||||
|
public void setAddSimulEnts(double addSimulEnts) {
|
||||||
|
this.addSimulEnts = addSimulEnts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the addSpawnsB4Cool
|
||||||
|
*/
|
||||||
|
public double getAddSpawnsB4Cool() {
|
||||||
|
return addSpawnsB4Cool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param addSpawnsB4Cool the addSpawnsB4Cool to set
|
||||||
|
*/
|
||||||
|
public void setAddSpawnsB4Cool(double addSpawnsB4Cool) {
|
||||||
|
this.addSpawnsB4Cool = addSpawnsB4Cool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the baseSimEnts
|
||||||
|
*/
|
||||||
|
public double getBaseSimEnts() {
|
||||||
|
return baseSimEnts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param baseSimEnts the baseSimEnts to set
|
||||||
|
*/
|
||||||
|
public void setBaseSimEnts(double baseSimEnts) {
|
||||||
|
this.baseSimEnts = baseSimEnts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the delay
|
||||||
|
*/
|
||||||
|
public int getDelay() {
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param delay the delay to set
|
||||||
|
*/
|
||||||
|
public void setDelay(int delay) {
|
||||||
|
this.delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the lootTableMap
|
||||||
|
*/
|
||||||
|
public Map<LootTableSerial, Integer> getLootTableMap() {
|
||||||
|
return lootTableMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lootTableMap the lootTableMap to set
|
||||||
|
*/
|
||||||
|
public void setLootTableMap(Map<LootTableSerial, Integer> lootTableMap) {
|
||||||
|
this.lootTableMap = lootTableMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the spawnRange
|
||||||
|
*/
|
||||||
|
public int getSpawnRange() {
|
||||||
|
return spawnRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param spawnRange the spawnRange to set
|
||||||
|
*/
|
||||||
|
public void setSpawnRange(int spawnRange) {
|
||||||
|
this.spawnRange = spawnRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the requiredPlayerRange
|
||||||
|
*/
|
||||||
|
public int getRequiredPlayerRange() {
|
||||||
|
return requiredPlayerRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param requiredPlayerRange the requiredPlayerRange to set
|
||||||
|
*/
|
||||||
|
public void setRequiredPlayerRange(int requiredPlayerRange) {
|
||||||
|
this.requiredPlayerRange = requiredPlayerRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the playerRange
|
||||||
|
*/
|
||||||
|
public int getPlayerRange() {
|
||||||
|
return playerRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param playerRange the playerRange to set
|
||||||
|
*/
|
||||||
|
public void setPlayerRange(int playerRange) {
|
||||||
|
this.playerRange = playerRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the baseSpawnsB4Cool
|
||||||
|
*/
|
||||||
|
public double getBaseSpawnsB4Cool() {
|
||||||
|
return baseSpawnsB4Cool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param baseSpawnsB4Cool the baseSpawnsB4Cool to set
|
||||||
|
*/
|
||||||
|
public void setBaseSpawnsB4Cool(double baseSpawnsB4Cool) {
|
||||||
|
this.baseSpawnsB4Cool = baseSpawnsB4Cool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BlueprintTrialSpawner [ominous=" + ominous + ", "
|
||||||
|
+ (spawnedType != null ? "spawnedType=" + spawnedType + ", " : "") + "addSimulEnts=" + addSimulEnts
|
||||||
|
+ ", addSpawnsB4Cool=" + addSpawnsB4Cool + ", baseSimEnts=" + baseSimEnts + ", delay=" + delay + ", "
|
||||||
|
+ (lootTableMap != null ? "lootTableMap=" + lootTableMap + ", " : "") + "spawnRange=" + spawnRange
|
||||||
|
+ ", requiredPlayerRange=" + requiredPlayerRange + ", playerRange=" + playerRange
|
||||||
|
+ ", baseSpawnsB4Cool=" + baseSpawnsB4Cool + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,6 +17,7 @@ import org.bukkit.block.BlockFace;
|
|||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.block.Sign;
|
import org.bukkit.block.Sign;
|
||||||
|
import org.bukkit.block.TrialSpawner;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.block.data.Waterlogged;
|
import org.bukkit.block.data.Waterlogged;
|
||||||
import org.bukkit.block.data.type.WallSign;
|
import org.bukkit.block.data.type.WallSign;
|
||||||
@ -28,6 +29,7 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.spawner.TrialSpawnerConfiguration;
|
import org.bukkit.spawner.TrialSpawnerConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import world.bentobox.bentobox.BentoBox;
|
import world.bentobox.bentobox.BentoBox;
|
||||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||||
@ -143,8 +145,12 @@ public class DefaultPasteUtil {
|
|||||||
else if (bs instanceof CreatureSpawner spawner) {
|
else if (bs instanceof CreatureSpawner spawner) {
|
||||||
setSpawner(spawner, bpBlock.getCreatureSpawner());
|
setSpawner(spawner, bpBlock.getCreatureSpawner());
|
||||||
}
|
}
|
||||||
else if (bs instanceof TrialSpawnerConfiguration spawner) {
|
else if (bs instanceof TrialSpawner ts) {
|
||||||
bpBlock.getTrialSpawner().configTrialSpawner(spawner);
|
TrialSpawnerConfiguration config = ts.getNormalConfiguration();
|
||||||
|
ts.setOminous(bpBlock.getTrialSpawner().configTrialSpawner(config));
|
||||||
|
if (!bs.update(true, false)) {
|
||||||
|
BentoBox.getInstance().logError("Trial Spawner update failed!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Banners
|
// Banners
|
||||||
else if (bs instanceof Banner banner && bpBlock.getBannerPatterns() != null) {
|
else if (bs instanceof Banner banner && bpBlock.getBannerPatterns() != null) {
|
||||||
|
Loading…
Reference in New Issue
Block a user