mirror of
https://github.com/BentoBoxWorld/Boxed.git
synced 2024-10-02 04:37:56 +02:00
commit
bc56090f46
75
pom.xml
75
pom.xml
@ -65,7 +65,7 @@
|
|||||||
<!-- 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.0.3</build.version>
|
<build.version>2.1.0</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>
|
||||||
@ -150,7 +150,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-core</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
<version>4.8.0</version>
|
<version>3.11.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -199,6 +199,14 @@
|
|||||||
<directory>src/main/resources</directory>
|
<directory>src/main/resources</directory>
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources/structures</directory>
|
||||||
|
<targetPath>./structures</targetPath>
|
||||||
|
<filtering>false</filtering>
|
||||||
|
<includes>
|
||||||
|
<include>*.nbt</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
<resource>
|
<resource>
|
||||||
<directory>src/main/resources/locales</directory>
|
<directory>src/main/resources/locales</directory>
|
||||||
<targetPath>./locales</targetPath>
|
<targetPath>./locales</targetPath>
|
||||||
@ -230,13 +238,14 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<nonFilteredFileExtensions>
|
<nonFilteredFileExtensions>
|
||||||
<nonFilteredFileExtension>blu</nonFilteredFileExtension>
|
<nonFilteredFileExtension>blu</nonFilteredFileExtension>
|
||||||
|
<nonFilteredFileExtension>nbt</nonFilteredFileExtension>
|
||||||
</nonFilteredFileExtensions>
|
</nonFilteredFileExtensions>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.8.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<release>${java.version}</release>
|
<release>${java.version}</release>
|
||||||
</configuration>
|
</configuration>
|
||||||
@ -247,7 +256,34 @@
|
|||||||
<version>3.0.0-M5</version>
|
<version>3.0.0-M5</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<argLine>
|
<argLine>
|
||||||
--illegal-access=permit
|
${argLine}
|
||||||
|
--add-opens java.base/java.lang=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.math=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.io=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.util=ALL-UNNAMED
|
||||||
|
--add-opens
|
||||||
|
java.base/java.util.stream=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.text=ALL-UNNAMED
|
||||||
|
--add-opens
|
||||||
|
java.base/java.util.regex=ALL-UNNAMED
|
||||||
|
--add-opens
|
||||||
|
java.base/java.nio.channels.spi=ALL-UNNAMED
|
||||||
|
--add-opens java.base/sun.nio.ch=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.net=ALL-UNNAMED
|
||||||
|
--add-opens
|
||||||
|
java.base/java.util.concurrent=ALL-UNNAMED
|
||||||
|
--add-opens java.base/sun.nio.fs=ALL-UNNAMED
|
||||||
|
--add-opens java.base/sun.nio.cs=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.nio.file=ALL-UNNAMED
|
||||||
|
--add-opens
|
||||||
|
java.base/java.nio.charset=ALL-UNNAMED
|
||||||
|
--add-opens
|
||||||
|
java.base/java.lang.reflect=ALL-UNNAMED
|
||||||
|
--add-opens
|
||||||
|
java.logging/java.util.logging=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.lang.ref=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.util.jar=ALL-UNNAMED
|
||||||
|
--add-opens java.base/java.util.zip=ALL-UNNAMED
|
||||||
</argLine>
|
</argLine>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
@ -256,6 +292,26 @@
|
|||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<version>3.1.0</version>
|
<version>3.1.0</version>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
<configuration>
|
||||||
|
<failOnError>false</failOnError>
|
||||||
|
<additionalJOption>-Xdoclint:none</additionalJOption>
|
||||||
|
<!-- To compile with Java 11, this tag may be required -->
|
||||||
|
<javadocExecutable>${java.home}/bin/javadoc</javadocExecutable>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
@ -282,7 +338,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.jacoco</groupId>
|
<groupId>org.jacoco</groupId>
|
||||||
<artifactId>jacoco-maven-plugin</artifactId>
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
<version>0.8.3</version>
|
<version>0.8.7</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<append>true</append>
|
<append>true</append>
|
||||||
<excludes>
|
<excludes>
|
||||||
@ -293,16 +349,21 @@
|
|||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>pre-unit-test</id>
|
<id>prepare-agent</id>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>prepare-agent</goal>
|
<goal>prepare-agent</goal>
|
||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
<execution>
|
||||||
<id>post-unit-test</id>
|
<id>report</id>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>report</goal>
|
<goal>report</goal>
|
||||||
</goals>
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<formats>
|
||||||
|
<format>XML</format>
|
||||||
|
</formats>
|
||||||
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
1
src/.gitignore
vendored
Normal file
1
src/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/.DS_Store
|
@ -280,7 +280,7 @@ public class Boxed extends GameModeAddon {
|
|||||||
int p = (int) (count / percent * 100);
|
int p = (int) (count / percent * 100);
|
||||||
if (p % 10 == 0 && p != last) {
|
if (p % 10 == 0 && p != last) {
|
||||||
last = p;
|
last = p;
|
||||||
this.log("Storing seed chunks for " + world.getEnvironment() + " " + p + "% done");
|
this.log("Pregenrating seed chunks for " + world.getName() + "'s " + world.getEnvironment() + " " + p + "% done");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -293,10 +293,7 @@ public class Boxed extends GameModeAddon {
|
|||||||
* @return the chunkGenerator for the environment
|
* @return the chunkGenerator for the environment
|
||||||
*/
|
*/
|
||||||
public AbstractBoxedChunkGenerator getChunkGenerator(Environment env) {
|
public AbstractBoxedChunkGenerator getChunkGenerator(Environment env) {
|
||||||
if (env.equals(Environment.NORMAL)) {
|
return env.equals(Environment.NORMAL) ? chunkGenerator : netherChunkGenerator;
|
||||||
return chunkGenerator;
|
|
||||||
}
|
|
||||||
return netherChunkGenerator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,10 +21,12 @@ import org.bukkit.structure.Structure;
|
|||||||
import com.google.common.base.Enums;
|
import com.google.common.base.Enums;
|
||||||
|
|
||||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||||
|
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.util.Util;
|
import world.bentobox.bentobox.util.Util;
|
||||||
import world.bentobox.boxed.Boxed;
|
import world.bentobox.boxed.Boxed;
|
||||||
import world.bentobox.boxed.listeners.NewAreaListener;
|
import world.bentobox.boxed.listeners.NewAreaListener;
|
||||||
|
import world.bentobox.boxed.listeners.NewAreaListener.Item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author tastybento
|
* @author tastybento
|
||||||
@ -32,8 +34,22 @@ import world.bentobox.boxed.listeners.NewAreaListener;
|
|||||||
*/
|
*/
|
||||||
public class AdminPlaceStructureCommand extends CompositeCommand {
|
public class AdminPlaceStructureCommand extends CompositeCommand {
|
||||||
|
|
||||||
|
private static final String STRUCTURE_FILE = "structures.yml";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integrity determines how damaged the building should look by randomly skipping blocks to place.
|
||||||
|
* This value can range from 0 to 1. With 0 removing all blocks and 1 spawning the structure in pristine condition.
|
||||||
|
*/
|
||||||
|
private static final float INTEGRITY = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The palette index of the structure to use, starting at 0, or -1 to pick a random palette.
|
||||||
|
*/
|
||||||
|
private static final int PALETTE = -1;
|
||||||
|
|
||||||
private StructureRotation sr = StructureRotation.NONE;
|
private StructureRotation sr = StructureRotation.NONE;
|
||||||
private Mirror mirror = Mirror.NONE;
|
private Mirror mirror = Mirror.NONE;
|
||||||
|
private boolean noMobs;
|
||||||
|
|
||||||
public AdminPlaceStructureCommand(CompositeCommand parent) {
|
public AdminPlaceStructureCommand(CompositeCommand parent) {
|
||||||
super(parent, "place");
|
super(parent, "place");
|
||||||
@ -41,10 +57,10 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setup() {
|
public void setup() {
|
||||||
this.setPermission("boxed.admin.place");
|
this.setPermission("boxed.commands.boxadmin.place");
|
||||||
this.setOnlyPlayer(false);
|
this.setOnlyPlayer(false);
|
||||||
this.setParametersHelp("boxed.admin.place.parameters");
|
this.setParametersHelp("boxed.commands.boxadmin.place.parameters");
|
||||||
this.setDescription("boxed.admin.place.description");
|
this.setDescription("boxed.commands.boxadmin.place.description");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -57,7 +73,7 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
|
|||||||
|
|
||||||
// Check world
|
// Check world
|
||||||
if (!((Boxed)getAddon()).inWorld(getWorld())) {
|
if (!((Boxed)getAddon()).inWorld(getWorld())) {
|
||||||
user.sendMessage("boxed.admin.place.wrong-world");
|
user.sendMessage("boxed.commands.boxadmin.place.wrong-world");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -66,6 +82,7 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
|
|||||||
* 4. place <structure> ~ ~ ~
|
* 4. place <structure> ~ ~ ~
|
||||||
* 5. place <structure> ~ ~ ~ ROTATION
|
* 5. place <structure> ~ ~ ~ ROTATION
|
||||||
* 6. place <structure> ~ ~ ~ ROTATION MIRROR
|
* 6. place <structure> ~ ~ ~ ROTATION MIRROR
|
||||||
|
* 7. place <structure> ~ ~ ~ ROTATION MIRROR NO_MOBS
|
||||||
*/
|
*/
|
||||||
// Format is place <structure> ~ ~ ~ or coords
|
// Format is place <structure> ~ ~ ~ or coords
|
||||||
if (args.isEmpty() || args.size() == 2 || args.size() == 3 || args.size() > 6) {
|
if (args.isEmpty() || args.size() == 2 || args.size() == 3 || args.size() > 6) {
|
||||||
@ -75,7 +92,7 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
|
|||||||
// First arg must always be the structure name
|
// First arg must always be the structure name
|
||||||
List<String> options = Bukkit.getStructureManager().getStructures().keySet().stream().map(k -> k.getKey()).toList();
|
List<String> options = Bukkit.getStructureManager().getStructures().keySet().stream().map(k -> k.getKey()).toList();
|
||||||
if (!options.contains(args.get(0).toLowerCase(Locale.ENGLISH))) {
|
if (!options.contains(args.get(0).toLowerCase(Locale.ENGLISH))) {
|
||||||
user.sendMessage("boxed.admin.place.unknown-structure");
|
user.sendMessage("boxed.commands.boxadmin.place.unknown-structure");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// If that is all we have, we're done
|
// If that is all we have, we're done
|
||||||
@ -86,7 +103,7 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
|
|||||||
if ((!args.get(1).equals("~") && !Util.isInteger(args.get(1), true))
|
if ((!args.get(1).equals("~") && !Util.isInteger(args.get(1), true))
|
||||||
|| (!args.get(2).equals("~") && !Util.isInteger(args.get(2), true))
|
|| (!args.get(2).equals("~") && !Util.isInteger(args.get(2), true))
|
||||||
|| (!args.get(3).equals("~") && !Util.isInteger(args.get(3), true))) {
|
|| (!args.get(3).equals("~") && !Util.isInteger(args.get(3), true))) {
|
||||||
user.sendMessage("boxed.admin.place.use-integers");
|
user.sendMessage("boxed.commands.boxadmin.place.use-integers");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// If that is all we have, we're done
|
// If that is all we have, we're done
|
||||||
@ -96,7 +113,7 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
|
|||||||
// But there is more!
|
// But there is more!
|
||||||
sr = Enums.getIfPresent(StructureRotation.class, args.get(4).toUpperCase(Locale.ENGLISH)).orNull();
|
sr = Enums.getIfPresent(StructureRotation.class, args.get(4).toUpperCase(Locale.ENGLISH)).orNull();
|
||||||
if (sr == null) {
|
if (sr == null) {
|
||||||
user.sendMessage("boxed.admin.place.unknown-rotation");
|
user.sendMessage("boxed.commands.boxadmin.place.unknown-rotation");
|
||||||
Arrays.stream(StructureRotation.values()).map(StructureRotation::name).forEach(user::sendRawMessage);
|
Arrays.stream(StructureRotation.values()).map(StructureRotation::name).forEach(user::sendRawMessage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -106,10 +123,18 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
|
|||||||
// But there is more!
|
// But there is more!
|
||||||
mirror = Enums.getIfPresent(Mirror.class, args.get(5).toUpperCase(Locale.ENGLISH)).orNull();
|
mirror = Enums.getIfPresent(Mirror.class, args.get(5).toUpperCase(Locale.ENGLISH)).orNull();
|
||||||
if (mirror == null) {
|
if (mirror == null) {
|
||||||
user.sendMessage("boxed.admin.place.unknown-mirror");
|
user.sendMessage("boxed.commands.boxadmin.place.unknown-mirror");
|
||||||
Arrays.stream(Mirror.values()).map(Mirror::name).forEach(user::sendRawMessage);
|
Arrays.stream(Mirror.values()).map(Mirror::name).forEach(user::sendRawMessage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (args.size() == 7) {
|
||||||
|
if (args.get(6).toUpperCase(Locale.ENGLISH).equals("NO_MOBS")) {
|
||||||
|
noMobs = true;
|
||||||
|
} else {
|
||||||
|
user.sendMessage("boxed.commands.boxadmin.place.unknown", TextVariables.LABEL, args.get(6).toUpperCase(Locale.ENGLISH));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Syntax is okay
|
// Syntax is okay
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -122,28 +147,39 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
|
|||||||
int y = args.size() == 1 || args.get(2).equals("~") ? user.getLocation().getBlockY() : Integer.valueOf(args.get(2).trim());
|
int y = args.size() == 1 || args.get(2).equals("~") ? user.getLocation().getBlockY() : Integer.valueOf(args.get(2).trim());
|
||||||
int z = args.size() == 1 || args.get(3).equals("~") ? user.getLocation().getBlockZ() : Integer.valueOf(args.get(3).trim());
|
int z = args.size() == 1 || args.get(3).equals("~") ? user.getLocation().getBlockZ() : Integer.valueOf(args.get(3).trim());
|
||||||
Location spot = new Location(user.getWorld(), x, y, z);
|
Location spot = new Location(user.getWorld(), x, y, z);
|
||||||
s.place(spot, true, sr, mirror, -1, 1, new Random());
|
s.place(spot, true, sr, mirror, PALETTE, INTEGRITY, new Random());
|
||||||
NewAreaListener.removeJigsaw(spot, s, sr, tag.getKey());
|
NewAreaListener.removeJigsaw(new Item(tag.getKey(), s, spot, sr, mirror, noMobs));
|
||||||
saveStructure(spot, tag, user, sr, mirror);
|
boolean result = saveStructure(spot, tag, user, sr, mirror);
|
||||||
return true;
|
if (result) {
|
||||||
|
user.sendMessage("boxed.commands.boxadmin.place.saved");
|
||||||
|
} else {
|
||||||
|
user.sendMessage("boxed.commands.boxadmin.place.failed");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveStructure(Location spot, NamespacedKey tag, User user, StructureRotation sr2, Mirror mirror2) {
|
private boolean saveStructure(Location spot, NamespacedKey tag, User user, StructureRotation sr2, Mirror mirror2) {
|
||||||
getAddon().getIslands().getIslandAt(spot).ifPresent(i -> {
|
return getAddon().getIslands().getIslandAt(spot).map(i -> {
|
||||||
int xx = spot.getBlockX() - i.getCenter().getBlockX();
|
int xx = spot.getBlockX() - i.getCenter().getBlockX();
|
||||||
int zz = spot.getBlockZ() - i.getCenter().getBlockZ();
|
int zz = spot.getBlockZ() - i.getCenter().getBlockZ();
|
||||||
File structures = new File(getAddon().getDataFolder(), "structures.yml");
|
File structures = new File(getAddon().getDataFolder(), STRUCTURE_FILE);
|
||||||
YamlConfiguration config = new YamlConfiguration();
|
YamlConfiguration config = new YamlConfiguration();
|
||||||
try {
|
try {
|
||||||
config.load(structures);
|
config.load(structures);
|
||||||
String value = tag.getKey() + "," + sr2.name() + "," + mirror2.name();
|
StringBuilder v = new StringBuilder();
|
||||||
config.set(spot.getWorld().getEnvironment().name().toLowerCase(Locale.ENGLISH) + "." + xx + "," + spot.getBlockY() + "," + zz, value);
|
v.append(tag.getKey() + "," + sr2.name() + "," + mirror2.name());
|
||||||
|
if (noMobs) {
|
||||||
|
v.append(" NO_MOBS");
|
||||||
|
}
|
||||||
|
config.set(spot.getWorld().getEnvironment().name().toLowerCase(Locale.ENGLISH) + "." + xx + "," + spot.getBlockY() + "," + zz, v.toString());
|
||||||
config.save(structures);
|
config.save(structures);
|
||||||
} catch (IOException | InvalidConfigurationException e) {
|
} catch (IOException | InvalidConfigurationException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
});
|
return true;
|
||||||
|
}).orElse(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,6 +199,8 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
|
|||||||
return Optional.of(Arrays.stream(StructureRotation.values()).map(StructureRotation::name).toList());
|
return Optional.of(Arrays.stream(StructureRotation.values()).map(StructureRotation::name).toList());
|
||||||
} else if (args.size() == 7) {
|
} else if (args.size() == 7) {
|
||||||
return Optional.of(Arrays.stream(Mirror.values()).map(Mirror::name).toList());
|
return Optional.of(Arrays.stream(Mirror.values()).map(Mirror::name).toList());
|
||||||
|
}else if (args.size() == 8) {
|
||||||
|
return Optional.of(List.of("NO_MOBS"));
|
||||||
}
|
}
|
||||||
return Optional.of(Collections.emptyList());
|
return Optional.of(Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
@ -53,12 +53,12 @@ public abstract class AbstractBoxedChunkGenerator extends ChunkGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunks.put(new Pair<>(x, z), new ChunkStore(chunk.getChunkSnapshot(), getEnts(chunk), getChests(chunk), chunkBiomes));
|
chunks.put(new Pair<>(x, z), new ChunkStore(chunk.getChunkSnapshot(), getEnts(chunk), getTileEnts(chunk), chunkBiomes));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract List<EntityData> getEnts(Chunk chunk);
|
protected abstract List<EntityData> getEnts(Chunk chunk);
|
||||||
|
|
||||||
protected abstract List<ChestData> getChests(Chunk chunk);
|
protected abstract List<ChestData> getTileEnts(Chunk chunk);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the chunk store for these chunk coords or null if there is none.
|
* Get the chunk store for these chunk coords or null if there is none.
|
||||||
@ -84,13 +84,15 @@ public abstract class AbstractBoxedChunkGenerator extends ChunkGenerator {
|
|||||||
* @return mapped chunk coord
|
* @return mapped chunk coord
|
||||||
*/
|
*/
|
||||||
public static int repeatCalc(int chunkCoord) {
|
public static int repeatCalc(int chunkCoord) {
|
||||||
|
return Math.floorMod(chunkCoord + size, size*2) - size;
|
||||||
|
/*
|
||||||
int xx;
|
int xx;
|
||||||
if (chunkCoord > 0) {
|
if (chunkCoord > 0) {
|
||||||
xx = Math.floorMod(chunkCoord + size, size*2) - size;
|
xx = Math.floorMod(chunkCoord + size, size*2) - size;
|
||||||
} else {
|
} else {
|
||||||
xx = Math.floorMod(chunkCoord - size, -size*2) + size;
|
xx = Math.floorMod(chunkCoord - size, -size*2) + size;
|
||||||
}
|
}
|
||||||
return xx;
|
return xx;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,7 +52,6 @@ public class BoxedBlockPopulator extends BlockPopulator {
|
|||||||
ChunkStore data = chunks.get(coords);
|
ChunkStore data = chunks.get(coords);
|
||||||
// Paste entities
|
// Paste entities
|
||||||
data.bpEnts().forEach(e -> {
|
data.bpEnts().forEach(e -> {
|
||||||
|
|
||||||
Location l = getLoc(world, e.relativeLoc().clone(), chunkX, chunkZ);
|
Location l = getLoc(world, e.relativeLoc().clone(), chunkX, chunkZ);
|
||||||
if (limitedRegion.isInRegion(l)) {
|
if (limitedRegion.isInRegion(l)) {
|
||||||
Entity ent = limitedRegion.spawnEntity(l, e.entity().getType());
|
Entity ent = limitedRegion.spawnEntity(l, e.entity().getType());
|
||||||
@ -61,12 +60,16 @@ public class BoxedBlockPopulator extends BlockPopulator {
|
|||||||
});
|
});
|
||||||
// Fill chests
|
// Fill chests
|
||||||
limitedRegion.getTileEntities().forEach(te -> {
|
limitedRegion.getTileEntities().forEach(te -> {
|
||||||
|
int teX = BoxedChunkGenerator.repeatCalc(te.getX() >> 4);
|
||||||
|
int teZ = BoxedChunkGenerator.repeatCalc(te.getZ() >> 4);
|
||||||
|
if (teX == xx && teZ == zz) {
|
||||||
for (ChestData cd : data.chests()) {
|
for (ChestData cd : data.chests()) {
|
||||||
Location chestLoc = getLoc(world, cd.relativeLoc().clone(), chunkX, chunkZ);
|
Location chestLoc = getLoc(world, cd.relativeLoc().clone(), chunkX, chunkZ);
|
||||||
if (limitedRegion.isInRegion(chestLoc) && te.getLocation().equals(chestLoc)) {
|
if (limitedRegion.isInRegion(chestLoc) && te.getLocation().equals(chestLoc)) {
|
||||||
this.setBlockState(te, cd.chest());
|
this.setBlockState(te, cd.chest());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ public class BoxedChunkGenerator extends AbstractBoxedChunkGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<ChestData> getChests(Chunk chunk) {
|
protected List<ChestData> getTileEnts(Chunk chunk) {
|
||||||
return Arrays.stream(chunk.getTileEntities()).map(t -> new ChestData(getLocInChunk(t.getLocation()), this.getBluePrintBlock(t.getBlock()))).toList();
|
return Arrays.stream(chunk.getTileEntities()).map(t -> new ChestData(getLocInChunk(t.getLocation()), this.getBluePrintBlock(t.getBlock()))).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,8 +120,10 @@ public class BoxedChunkGenerator extends AbstractBoxedChunkGenerator {
|
|||||||
return bpEnts;
|
return bpEnts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the location in the chunk
|
||||||
private Vector getLocInChunk(Location l) {
|
private Vector getLocInChunk(Location l) {
|
||||||
return new Vector(l.getBlockX() % 16, l.getBlockY(), l.getBlockZ() % 16);
|
// Have to use Math function because java % doesn't work correctly IMO with negatives
|
||||||
|
return new Vector(Math.floorMod(l.getBlockX(),16), l.getBlockY(), Math.floorMod(l.getBlockZ(), 16));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ public class BoxedSeedChunkGenerator extends AbstractBoxedChunkGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<ChestData> getChests(Chunk chunk) {
|
protected List<ChestData> getTileEnts(Chunk chunk) {
|
||||||
// These won't be stored
|
// These won't be stored
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ public class AdvancementListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Advancement getAdvancement(String string) {
|
public static Advancement getAdvancement(String string) {
|
||||||
return StreamSupport.stream(
|
return StreamSupport.stream(
|
||||||
Spliterators.spliteratorUnknownSize(Bukkit.advancementIterator(), Spliterator.ORDERED), false)
|
Spliterators.spliteratorUnknownSize(Bukkit.advancementIterator(), Spliterator.ORDERED), false)
|
||||||
.filter(a -> a.getKey().toString().equals(string))
|
.filter(a -> a.getKey().toString().equals(string))
|
||||||
@ -191,7 +191,8 @@ public class AdvancementListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void giveAdv(Player player, Advancement adv) {
|
public static void giveAdv(Player player, Advancement adv) {
|
||||||
|
//BentoBox.getInstance().logDebug("Give Adv " + adv.getKey() + " done status " + player.getAdvancementProgress(adv).isDone());
|
||||||
if (adv != null && !player.getAdvancementProgress(adv).isDone()) {
|
if (adv != null && !player.getAdvancementProgress(adv).isDone()) {
|
||||||
adv.getCriteria().forEach(player.getAdvancementProgress(adv)::awardCriteria);
|
adv.getCriteria().forEach(player.getAdvancementProgress(adv)::awardCriteria);
|
||||||
}
|
}
|
||||||
@ -199,6 +200,17 @@ public class AdvancementListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
public void onPlayerJoin(PlayerJoinEvent e) {
|
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||||
|
/*
|
||||||
|
StreamSupport.stream(
|
||||||
|
Spliterators.spliteratorUnknownSize(Bukkit.advancementIterator(), Spliterator.ORDERED), false).forEach(a-> {
|
||||||
|
AdvancementProgress progress = e.getPlayer().getAdvancementProgress(a);
|
||||||
|
BentoBox.getInstance().logDebug(a.getKey() + " " + progress.isDone());
|
||||||
|
BentoBox.getInstance().logDebug("Awarded");
|
||||||
|
progress.getAwardedCriteria().forEach(c -> BentoBox.getInstance().logDebug(c));
|
||||||
|
BentoBox.getInstance().logDebug("Remaining");
|
||||||
|
progress.getRemainingCriteria().forEach(c -> BentoBox.getInstance().logDebug(c));
|
||||||
|
});
|
||||||
|
*/
|
||||||
User user = User.getInstance(e.getPlayer());
|
User user = User.getInstance(e.getPlayer());
|
||||||
if (Util.sameWorld(addon.getOverWorld(), e.getPlayer().getWorld())) {
|
if (Util.sameWorld(addon.getOverWorld(), e.getPlayer().getWorld())) {
|
||||||
// Set advancements to same as island
|
// Set advancements to same as island
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package world.bentobox.boxed.listeners;
|
package world.bentobox.boxed.listeners;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -25,10 +27,13 @@ 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_19_R3.CraftWorld;
|
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
import org.bukkit.loot.LootTables;
|
import org.bukkit.loot.LootTables;
|
||||||
import org.bukkit.structure.Structure;
|
import org.bukkit.structure.Structure;
|
||||||
import org.bukkit.util.BoundingBox;
|
import org.bukkit.util.BoundingBox;
|
||||||
@ -45,12 +50,14 @@ import world.bentobox.bentobox.BentoBox;
|
|||||||
import world.bentobox.bentobox.api.events.BentoBoxReadyEvent;
|
import world.bentobox.bentobox.api.events.BentoBoxReadyEvent;
|
||||||
import world.bentobox.bentobox.api.events.island.IslandCreatedEvent;
|
import world.bentobox.bentobox.api.events.island.IslandCreatedEvent;
|
||||||
import world.bentobox.bentobox.api.events.island.IslandResettedEvent;
|
import world.bentobox.bentobox.api.events.island.IslandResettedEvent;
|
||||||
|
import world.bentobox.bentobox.database.Database;
|
||||||
import world.bentobox.bentobox.database.objects.Island;
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
import world.bentobox.bentobox.util.Pair;
|
import world.bentobox.bentobox.util.Pair;
|
||||||
import world.bentobox.bentobox.util.Util;
|
import world.bentobox.bentobox.util.Util;
|
||||||
import world.bentobox.boxed.Boxed;
|
import world.bentobox.boxed.Boxed;
|
||||||
import world.bentobox.boxed.objects.BoxedJigsawBlock;
|
import world.bentobox.boxed.objects.BoxedJigsawBlock;
|
||||||
import world.bentobox.boxed.objects.BoxedStructureBlock;
|
import world.bentobox.boxed.objects.BoxedStructureBlock;
|
||||||
|
import world.bentobox.boxed.objects.IslandStructures;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author tastybento
|
* @author tastybento
|
||||||
@ -59,15 +66,28 @@ import world.bentobox.boxed.objects.BoxedStructureBlock;
|
|||||||
public class NewAreaListener implements Listener {
|
public class NewAreaListener implements Listener {
|
||||||
|
|
||||||
private static final List<BlockFace> CARDINALS = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST);
|
private static final List<BlockFace> CARDINALS = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST);
|
||||||
|
private static final List<String> JAR_STRUCTURES = List.of("bee", "pillager", "polar_bear", "axolotl", "allay", "parrot", "frog");
|
||||||
|
private static final List<String> STRUCTURES = List.of("ancient_city", "bastion_remnant", "bastion",
|
||||||
|
"buried_treasure", "desert_pyramid", "end_city",
|
||||||
|
"fortress", "igloo", "jungle_pyramid", "mansion", "mineshaft", "mineshaft_mesa",
|
||||||
|
"monument", "nether_fossil", "ocean_ruin_cold", "ocean_ruin_warm", "pillager_outpost",
|
||||||
|
"ruined_portal_desert", "ruined_portal_jungle", "ruined_portal_mountain", "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 File structureFile;
|
private File structureFile;
|
||||||
private Queue<Item> itemsToBuild = new LinkedList<>();
|
private Queue<Item> itemsToBuild = new LinkedList<>();
|
||||||
private static Random rand = new Random();
|
private static Random rand = new Random();
|
||||||
private boolean pasting;
|
private boolean pasting;
|
||||||
private static Gson gson = new Gson();
|
private static Gson gson = new Gson();
|
||||||
private record Item(String name, Structure structure, Location location, StructureRotation rot, Mirror mirror) {};
|
public record Item(String name, Structure structure, Location location, StructureRotation rot, Mirror mirror, Boolean noMobs) {};
|
||||||
Pair<Integer, Integer> min = new Pair<Integer, Integer>(0,0);
|
Pair<Integer, Integer> min = new Pair<Integer, Integer>(0,0);
|
||||||
Pair<Integer, Integer> max = new Pair<Integer, Integer>(0,0);
|
Pair<Integer, Integer> max = new Pair<Integer, Integer>(0,0);
|
||||||
|
// Database handler for structure data
|
||||||
|
private final Database<IslandStructures> handler;
|
||||||
|
private Map<String, IslandStructures> islandStructureCache = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,9 +98,24 @@ public class NewAreaListener implements Listener {
|
|||||||
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
|
||||||
|
handler = new Database<>(addon, IslandStructures.class);
|
||||||
// Try to build something every second
|
// Try to build something every second
|
||||||
Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> BuildItem(), 20, 20);
|
Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> BuildItem(), 20, 20);
|
||||||
|
// Experiment: TODO: read all files in from the structure folder including the ones saved from the jar file
|
||||||
|
for (String js : JAR_STRUCTURES) {
|
||||||
|
addon.saveResource("structures/" + js + ".nbt", false);
|
||||||
|
File structureFile = new File(addon.getDataFolder(), "structures/" + js + ".nbt");
|
||||||
|
try {
|
||||||
|
Structure s = Bukkit.getStructureManager().loadStructure(structureFile);
|
||||||
|
Bukkit.getStructureManager().registerStructure(NamespacedKey.fromString("minecraft:boxed/" + js), s);
|
||||||
|
addon.log("Loaded " + js + ".nbt");
|
||||||
|
} catch (IOException e) {
|
||||||
|
addon.logError("Error trying to load " + structureFile.getAbsolutePath());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildItem() {
|
private void BuildItem() {
|
||||||
@ -96,7 +131,7 @@ public class NewAreaListener implements Listener {
|
|||||||
* Build a list of structures
|
* Build a list of structures
|
||||||
* @param event event
|
* @param event event
|
||||||
*/
|
*/
|
||||||
@EventHandler()
|
@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");
|
||||||
@ -104,15 +139,73 @@ public class NewAreaListener implements Listener {
|
|||||||
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) {
|
||||||
Structure s = Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString(struct));
|
if (!struct.endsWith("/")) {
|
||||||
if (s == null) {
|
Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString(struct));
|
||||||
//addon.log("Now loading group from: " + struct);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
|
public void onPlayerMove(PlayerMoveEvent e) {
|
||||||
|
// Ignore head movements
|
||||||
|
if (!addon.inWorld(e.getFrom().getWorld()) || e.getFrom().toVector().equals(e.getTo().toVector())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check where the player is
|
||||||
|
addon.getIslands().getIslandAt(e.getTo()).ifPresent(island -> {
|
||||||
|
// See if island is in cache
|
||||||
|
final String islandId = island.getUniqueId();
|
||||||
|
IslandStructures is = getIslandStructData(islandId);
|
||||||
|
// Check if player is in any of the structures
|
||||||
|
Map<BoundingBox, String> structures = e.getTo().getWorld().getEnvironment().equals(Environment.NETHER) ?
|
||||||
|
is.getNetherStructureBoundingBoxMap():is.getStructureBoundingBoxMap();
|
||||||
|
for (Map.Entry<BoundingBox, String> en:structures.entrySet()) {
|
||||||
|
if (en.getKey().contains(e.getTo().toVector())) {
|
||||||
|
for (String s: STRUCTURES) {
|
||||||
|
if (en.getValue().startsWith(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
|
||||||
|
* @param player - player
|
||||||
|
* @param string - criteria
|
||||||
|
*/
|
||||||
|
private void giveAdvFromCriteria(Player player, String string) {
|
||||||
|
// Give every advancement that requires a bastion
|
||||||
|
Bukkit.advancementIterator().forEachRemaining(ad -> {
|
||||||
|
if (!player.getAdvancementProgress(ad).isDone()) {
|
||||||
|
for (String crit: ad.getCriteria()) {
|
||||||
|
if (crit.equals(string)) {
|
||||||
|
// Set the criteria (it may not complete the advancement completely
|
||||||
|
player.getAdvancementProgress(ad).awardCriteria(crit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private IslandStructures getIslandStructData(String islandId) {
|
||||||
|
// Return from cache if it exists
|
||||||
|
if (islandStructureCache.containsKey(islandId)) {
|
||||||
|
return islandStructureCache.get(islandId);
|
||||||
|
}
|
||||||
|
// Get from database
|
||||||
|
IslandStructures struct = handler.objectExists(islandId) ? handler.loadObject(islandId) : new IslandStructures(islandId);
|
||||||
|
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());
|
||||||
@ -148,6 +241,7 @@ public class NewAreaListener implements Listener {
|
|||||||
for (String vector : section.getKeys(false)) {
|
for (String vector : section.getKeys(false)) {
|
||||||
StructureRotation rot = StructureRotation.NONE;
|
StructureRotation rot = StructureRotation.NONE;
|
||||||
Mirror mirror = Mirror.NONE;
|
Mirror mirror = Mirror.NONE;
|
||||||
|
boolean noMobs = false;
|
||||||
String name = section.getString(vector);
|
String name = section.getString(vector);
|
||||||
// Check for rotation
|
// Check for rotation
|
||||||
String[] split = name.split(",");
|
String[] split = name.split(",");
|
||||||
@ -158,7 +252,10 @@ public class NewAreaListener implements Listener {
|
|||||||
}
|
}
|
||||||
if (split.length == 3) {
|
if (split.length == 3) {
|
||||||
// Mirror
|
// Mirror
|
||||||
mirror = Enums.getIfPresent(Mirror.class, split[1].strip().toUpperCase(Locale.ENGLISH)).or(Mirror.NONE);
|
mirror = Enums.getIfPresent(Mirror.class, split[2].strip().toUpperCase(Locale.ENGLISH)).or(Mirror.NONE);
|
||||||
|
}
|
||||||
|
if (split.length == 4) {
|
||||||
|
noMobs = split[3].strip().toUpperCase(Locale.ENGLISH).equals("NO_MOBS");
|
||||||
}
|
}
|
||||||
// Load Structure
|
// Load Structure
|
||||||
Structure s = Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString("minecraft:" + name));
|
Structure s = Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString("minecraft:" + name));
|
||||||
@ -173,7 +270,7 @@ public class NewAreaListener implements Listener {
|
|||||||
int y = Integer.valueOf(value[1].strip());
|
int y = Integer.valueOf(value[1].strip());
|
||||||
int z = Integer.valueOf(value[2].strip()) + center.getBlockZ();
|
int z = Integer.valueOf(value[2].strip()) + center.getBlockZ();
|
||||||
Location l = new Location(world, x, y, z);
|
Location l = new Location(world, x, y, z);
|
||||||
itemsToBuild.add(new Item(name, s, l, rot, mirror));
|
itemsToBuild.add(new Item(name, s, l, rot, mirror, noMobs));
|
||||||
} else {
|
} else {
|
||||||
addon.logError("Structure file syntax error: " + vector + ": " + value);
|
addon.logError("Structure file syntax error: " + vector + ": " + value);
|
||||||
}
|
}
|
||||||
@ -185,18 +282,32 @@ public class NewAreaListener implements Listener {
|
|||||||
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() + " " + Util.xyz(item.location().toVector()));
|
||||||
// Find it
|
// Find it
|
||||||
removeJigsaw(item.location(), item.structure(), item.rot(), item.name());
|
BoundingBox bb = removeJigsaw(item);
|
||||||
|
// Store it
|
||||||
|
addon.getIslands().getIslandAt(item.location()).map(Island::getUniqueId).ifPresent(id -> {
|
||||||
|
addon.log("Saved " + item.name());
|
||||||
|
if (item.location().getWorld().getEnvironment().equals(Environment.NETHER)) {
|
||||||
|
getIslandStructData(id).addNetherStructure(bb, item.name());
|
||||||
|
} else {
|
||||||
|
getIslandStructData(id).addStructure(bb, item.name());
|
||||||
|
}
|
||||||
|
handler.saveObjectAsync(getIslandStructData(id));
|
||||||
|
});
|
||||||
|
|
||||||
pasting = false;
|
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 loc - location where the structure was placed
|
* @param item - record of what's required
|
||||||
* @param structure - structure that was placed
|
* @return the resulting bounding box of the structure
|
||||||
* @param structureRotation - rotation of structure
|
|
||||||
* @param key
|
|
||||||
*/
|
*/
|
||||||
public static void removeJigsaw(Location loc, Structure structure, StructureRotation structureRotation, String key) {
|
public static BoundingBox removeJigsaw(Item item) {
|
||||||
|
Location loc = item.location();
|
||||||
|
Structure structure = item.structure();
|
||||||
|
StructureRotation structureRotation = item.rot();
|
||||||
|
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()));
|
||||||
@ -216,7 +327,7 @@ public class NewAreaListener implements Listener {
|
|||||||
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);
|
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);
|
||||||
}
|
}
|
||||||
@ -227,7 +338,7 @@ public class NewAreaListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -255,15 +366,19 @@ public class NewAreaListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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, EntityType.PIG);
|
||||||
private static void processJigsaw(Block b, StructureRotation structureRotation) {
|
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);
|
||||||
//BentoBox.getInstance().logDebug("Jigsaw: " + bjb);
|
|
||||||
//BentoBox.getInstance().logDebug("FinalState: " + bjb.getFinal_state());
|
|
||||||
String finalState = correctDirection(bjb.getFinal_state(), structureRotation);
|
String finalState = correctDirection(bjb.getFinal_state(), structureRotation);
|
||||||
//BentoBox.getInstance().logDebug("FinalState after rotation: " + finalState);
|
|
||||||
BlockData bd = Bukkit.createBlockData(finalState);
|
BlockData bd = Bukkit.createBlockData(finalState);
|
||||||
b.setBlockData(bd);
|
b.setBlockData(bd);
|
||||||
|
if (!bjb.getPool().equalsIgnoreCase("minecraft:empty") && pasteMobs) {
|
||||||
|
spawnMob(b, 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
|
||||||
EntityType type =
|
EntityType type =
|
||||||
switch (bjb.getPool()) {
|
switch (bjb.getPool()) {
|
||||||
case "minecraft:bastion/mobs/piglin" -> EntityType.PIGLIN;
|
case "minecraft:bastion/mobs/piglin" -> EntityType.PIGLIN;
|
||||||
@ -279,16 +394,28 @@ public class NewAreaListener implements Listener {
|
|||||||
case "minecraft:village/common/animals" -> BUTCHER_ANIMALS.get(rand.nextInt(3));
|
case "minecraft:village/common/animals" -> BUTCHER_ANIMALS.get(rand.nextInt(3));
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
|
// Boxed
|
||||||
|
if (type == null && bjb.getPool().startsWith("minecraft:boxed/")) {
|
||||||
|
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")) {
|
if (bjb.getPool().contains("zombie/villagers")) {
|
||||||
type = EntityType.ZOMBIE_VILLAGER;
|
type = EntityType.ZOMBIE_VILLAGER;
|
||||||
} else if (bjb.getPool().contains("villagers")) {
|
} else if (bjb.getPool().contains("villagers")) {
|
||||||
type = EntityType.VILLAGER;
|
type = EntityType.VILLAGER;
|
||||||
}
|
}
|
||||||
|
//if (type == null) {
|
||||||
|
// BentoBox.getInstance().logDebug(bjb.getPool());
|
||||||
|
//}
|
||||||
// Spawn it
|
// Spawn it
|
||||||
if (type != null && b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type) != null) {
|
if (type != null) {
|
||||||
|
Entity e = b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type);
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
package world.bentobox.boxed.objects;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.database.objects.DataObject;
|
||||||
|
import world.bentobox.bentobox.database.objects.Table;
|
||||||
|
|
||||||
|
@Table(name = "IslandStructures")
|
||||||
|
public class IslandStructures implements DataObject {
|
||||||
|
|
||||||
|
@Expose
|
||||||
|
String uniqueId;
|
||||||
|
@Expose
|
||||||
|
Map<BoundingBox, String> structureBoundingBoxMap = new HashMap<>();
|
||||||
|
@Expose
|
||||||
|
Map<BoundingBox, String> netherStructureBoundingBoxMap = new HashMap<>();
|
||||||
|
|
||||||
|
public IslandStructures(String islandId) {
|
||||||
|
this.uniqueId = islandId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUniqueId() {
|
||||||
|
return uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUniqueId(String uniqueId) {
|
||||||
|
this.uniqueId = uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a structure for this island
|
||||||
|
* @param bb - bounding box of the structure
|
||||||
|
* @param key - structure namespace key
|
||||||
|
*/
|
||||||
|
public void addStructure(BoundingBox bb, String key) {
|
||||||
|
getStructureBoundingBoxMap().put(bb, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<BoundingBox, String> getStructureBoundingBoxMap() {
|
||||||
|
if (structureBoundingBoxMap == null) {
|
||||||
|
structureBoundingBoxMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
return structureBoundingBoxMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStructureBoundingBoxMap(Map<BoundingBox, String> structureBoundingBoxMap) {
|
||||||
|
this.structureBoundingBoxMap = structureBoundingBoxMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a structure for this island
|
||||||
|
* @param bb - bounding box of the structure
|
||||||
|
* @param key - structure namespace key
|
||||||
|
*/
|
||||||
|
public void addNetherStructure(BoundingBox bb, String key) {
|
||||||
|
getNetherStructureBoundingBoxMap().put(bb, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<BoundingBox, String> getNetherStructureBoundingBoxMap() {
|
||||||
|
if (netherStructureBoundingBoxMap == null) {
|
||||||
|
netherStructureBoundingBoxMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
return netherStructureBoundingBoxMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNetherStructureBoundingBoxMap(Map<BoundingBox, String> netherStructureBoundingBoxMap) {
|
||||||
|
this.netherStructureBoundingBoxMap = netherStructureBoundingBoxMap;
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ advancements:
|
|||||||
'exploration/jungle_in': 0
|
'exploration/jungle_in': 0
|
||||||
'exploration/write_book': 0
|
'exploration/write_book': 0
|
||||||
'forestry/sapling' : 0
|
'forestry/sapling' : 0
|
||||||
'adventure/adventuring_time': 13
|
'adventure/adventuring_time': 13
|
||||||
'adventure/arbalistic': 11
|
'adventure/arbalistic': 11
|
||||||
'adventure/avoid_vibration': 13
|
'adventure/avoid_vibration': 13
|
||||||
'adventure/bullseye': 5
|
'adventure/bullseye': 5
|
||||||
|
@ -23,6 +23,18 @@ boxed:
|
|||||||
parameters: '[home number]'
|
parameters: '[home number]'
|
||||||
sethome:
|
sethome:
|
||||||
parameters: '[home number]'
|
parameters: '[home number]'
|
||||||
|
boxadmin:
|
||||||
|
place:
|
||||||
|
description: Place an area structure
|
||||||
|
parameters: <x> <y> <z> <rotation> <mirror> <no mobs>
|
||||||
|
use-integers: '&c Coordinated must be integers'
|
||||||
|
wrong-world: '&c This command can only be used in a Boxed world'
|
||||||
|
unknown-structure: '&c Cannot place: Unknown structure'
|
||||||
|
unknown-rotation: '&c Cannot place: Unknown rotation type'
|
||||||
|
unknown-mirror: '&c Cannot place: Unknown mirror type'
|
||||||
|
saved: '&a Placed and saved to structures.yml'
|
||||||
|
failed: '&c Could not be saved to structures.yml. Check console for error'
|
||||||
|
unknown: '&c Unknown parameter: [label]'
|
||||||
island:
|
island:
|
||||||
go:
|
go:
|
||||||
parameters: '[home number]'
|
parameters: '[home number]'
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# This file is written by the /boxadmin place command
|
||||||
normal:
|
normal:
|
||||||
0,64,80: village/plains/houses/plains_masons_house_1,CLOCKWISE_90
|
0,64,80: village/plains/houses/plains_masons_house_1,CLOCKWISE_90
|
||||||
-38,63,20: ruined_portal/portal_5
|
-38,63,20: ruined_portal/portal_5
|
||||||
@ -15,6 +16,8 @@ normal:
|
|||||||
34,69,-29: village/common/iron_golem
|
34,69,-29: village/common/iron_golem
|
||||||
41,69,-26: village/common/animals/cat_calico
|
41,69,-26: village/common/animals/cat_calico
|
||||||
35,69,-22: village/common/animals/cat_calico
|
35,69,-22: village/common/animals/cat_calico
|
||||||
|
32,70,65: village/savanna/houses/savanna_temple_1,NONE,NONE
|
||||||
|
25,70,72: village/savanna/houses/savanna_small_house_7,COUNTERCLOCKWISE_90,NONE,NO_MOBS
|
||||||
99,72,118: pillager_outpost/feature_cage1
|
99,72,118: pillager_outpost/feature_cage1
|
||||||
33,72,100: village/desert/houses/desert_farm_1
|
33,72,100: village/desert/houses/desert_farm_1
|
||||||
26,72,100: village/desert/houses/desert_medium_house_1
|
26,72,100: village/desert/houses/desert_medium_house_1
|
||||||
@ -33,7 +36,36 @@ normal:
|
|||||||
-52,72,33: village/snowy/houses/snowy_farm_1,COUNTERCLOCKWISE_90,NONE
|
-52,72,33: village/snowy/houses/snowy_farm_1,COUNTERCLOCKWISE_90,NONE
|
||||||
-28,63,47: village/snowy/snowy_lamp_post_01,COUNTERCLOCKWISE_90,NONE
|
-28,63,47: village/snowy/snowy_lamp_post_01,COUNTERCLOCKWISE_90,NONE
|
||||||
-6,64,52: village/snowy/houses/snowy_small_house_3,COUNTERCLOCKWISE_90,NONE
|
-6,64,52: village/snowy/houses/snowy_small_house_3,COUNTERCLOCKWISE_90,NONE
|
||||||
40,73,-3: village/savanna/houses/savanna_small_house_1,CLOCKWISE_180
|
60,81,88: village/desert/camel_spawn,NONE,NONE
|
||||||
|
64,81,93: village/desert/houses/desert_animal_pen_1,NONE,NONE
|
||||||
|
49,81,94: village/desert/houses/desert_large_farm_1,NONE,NONE
|
||||||
|
-106,45,68: underwater_ruin/big_brick_1,NONE,NONE
|
||||||
|
-117,45,88: underwater_ruin/big_brick_2,NONE,NONE
|
||||||
|
64,78,49: village/common/animals/horses_1,NONE,NONE
|
||||||
|
65,78,51: village/common/animals/horses_2,NONE,NONE
|
||||||
|
67,78,52: village/common/animals/horses_3,NONE,NONE
|
||||||
|
57,70,-90: village/common/animals/horses_5,NONE,NONE
|
||||||
|
62,70,-88: village/common/animals/horses_5,NONE,NONE
|
||||||
|
-2,66,10: boxed/frog,NONE,NONE
|
||||||
|
87,85,120: boxed/pillager,NONE,NONE
|
||||||
|
85,85,122: boxed/pillager,NONE,NONE
|
||||||
|
87,85,118: boxed/pillager,NONE,NONE
|
||||||
|
87,85,123: boxed/pillager,NONE,NONE
|
||||||
|
89,81,122: boxed/pillager,NONE,NONE
|
||||||
|
87,77,120: boxed/pillager,NONE,NONE
|
||||||
|
94,71,111: boxed/pillager,NONE,NONE
|
||||||
|
90,71,111: boxed/pillager,NONE,NONE
|
||||||
|
100,72,110: pillager_outpost/feature_tent1,NONE,NONE
|
||||||
|
-20,63,-24: boxed/parrot,NONE,NONE
|
||||||
|
-21,65,-21: boxed/parrot,NONE,NONE
|
||||||
|
1,69,-12: boxed/frog,NONE,NONE
|
||||||
|
2,67,10: boxed/parrot,NONE,NONE
|
||||||
|
-58,64,13: boxed/polar_bear,NONE,NONE
|
||||||
|
-90,63,57: boxed/polar_bear,NONE,NONE
|
||||||
|
-87,63,63: boxed/polar_bear,NONE,NONE
|
||||||
|
-33,69,58: boxed/polar_bear,NONE,NONE
|
||||||
|
137,-8,11: boxed/axolotl,NONE,NONE
|
||||||
|
137,-8,9: boxed/axolotl,NONE,NONE
|
||||||
|
|
||||||
nether:
|
nether:
|
||||||
16,32,0: bastion/bridge/starting_pieces/entrance
|
16,32,0: bastion/bridge/starting_pieces/entrance
|
||||||
|
BIN
src/main/resources/structures/allay.nbt
Normal file
BIN
src/main/resources/structures/allay.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/structures/axolotl.nbt
Normal file
BIN
src/main/resources/structures/axolotl.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/structures/bee.nbt
Normal file
BIN
src/main/resources/structures/bee.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/structures/frog.nbt
Normal file
BIN
src/main/resources/structures/frog.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/structures/parrot.nbt
Normal file
BIN
src/main/resources/structures/parrot.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/structures/pillager.nbt
Normal file
BIN
src/main/resources/structures/pillager.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/structures/polar_bear.nbt
Normal file
BIN
src/main/resources/structures/polar_bear.nbt
Normal file
Binary file not shown.
@ -1,4 +1,11 @@
|
|||||||
templates:
|
templates:
|
||||||
|
- boxed/frog
|
||||||
|
- boxed/allay
|
||||||
|
- boxed/bee
|
||||||
|
- boxed/axolotl
|
||||||
|
- boxed/pillager
|
||||||
|
- boxed/polar_bear
|
||||||
|
- boxed/parrot
|
||||||
- ancient_city/city/entrance/entrance_connector
|
- ancient_city/city/entrance/entrance_connector
|
||||||
- ancient_city/city/entrance/entrance_path_1
|
- ancient_city/city/entrance/entrance_path_1
|
||||||
- ancient_city/city/entrance/entrance_path_2
|
- ancient_city/city/entrance/entrance_path_2
|
||||||
|
Loading…
Reference in New Issue
Block a user