mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-19 14:50:30 +00:00
implement world api changes
This commit is contained in:
@@ -25,6 +25,7 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.LimitedRegion;
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -32,6 +33,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.dfsek.terra.api.config.WorldConfig;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
@@ -66,7 +68,12 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener
|
||||
|
||||
@Override
|
||||
public @NotNull List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
|
||||
return Collections.singletonList(new BukkitPopulatorWrapper(delegate));
|
||||
return delegate.getGenerationStages().stream().map(generationStage -> new BlockPopulator() {
|
||||
@Override
|
||||
public void populate(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull LimitedRegion limitedRegion) {
|
||||
generationStage.populate(new BukkitProtoWorld(limitedRegion));
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.bukkit.generator;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.LimitedRegion;
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified;
|
||||
import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
|
||||
|
||||
public class BukkitPopulatorWrapper extends BlockPopulator {
|
||||
private final ChunkGenerator delegate;
|
||||
|
||||
public BukkitPopulatorWrapper(ChunkGenerator delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk source) {
|
||||
delegate.getGenerationStages().forEach(populator -> {
|
||||
if(populator instanceof Chunkified) {
|
||||
populator.populate(BukkitAdapter.adapt(world), BukkitAdapter.adapt(source));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull LimitedRegion limitedRegion) {
|
||||
super.populate(worldInfo, random, x, z, limitedRegion);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.bukkit.population;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
import com.dfsek.terra.bukkit.world.BukkitWorld;
|
||||
|
||||
|
||||
public class ChunkCoordinate implements Serializable {
|
||||
public static final long serialVersionUID = 7102462856296750285L;
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final UUID worldID;
|
||||
|
||||
public ChunkCoordinate(int x, int z, UUID worldID) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.worldID = worldID;
|
||||
}
|
||||
|
||||
public ChunkCoordinate(Chunk c) {
|
||||
this.x = c.getX();
|
||||
this.z = c.getZ();
|
||||
this.worldID = ((BukkitWorld) c.getWorld()).getUID();
|
||||
}
|
||||
|
||||
public UUID getWorldID() {
|
||||
return worldID;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return x * 31 + z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!(obj instanceof ChunkCoordinate other)) return false;
|
||||
return other.getX() == x && other.getZ() == z;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.bukkit.population;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.profiler.ProfileFrame;
|
||||
import com.dfsek.terra.api.world.access.World;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified;
|
||||
import com.dfsek.terra.bukkit.PlatformImpl;
|
||||
import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
import com.dfsek.terra.bukkit.world.BukkitWorld;
|
||||
import com.dfsek.terra.util.FastRandom;
|
||||
|
||||
|
||||
/**
|
||||
* Cursed management class for the horrors of Bukkit population
|
||||
*/
|
||||
public class PopulationManager extends BlockPopulator {
|
||||
private final ChunkGenerator generator;
|
||||
private final HashSet<ChunkCoordinate> needsPop = new HashSet<>();
|
||||
private final Platform platform;
|
||||
|
||||
public PopulationManager(ChunkGenerator generator, Platform platform) {
|
||||
this.generator = generator;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
public static File getDataFolder(World w) {
|
||||
File f = new File(((BukkitWorld) w).getWorldFolder(), "gaea");
|
||||
f.mkdirs();
|
||||
return f;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized void saveBlocks(World w) throws IOException {
|
||||
File f = new File(getDataFolder(w), "chunks.bin");
|
||||
f.createNewFile();
|
||||
SerializationUtil.toFile((HashSet<ChunkCoordinate>) needsPop.clone(), f);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized void loadBlocks(World w) throws IOException, ClassNotFoundException {
|
||||
File f = new File(getDataFolder(w), "chunks.bin");
|
||||
needsPop.addAll((HashSet<ChunkCoordinate>) SerializationUtil.fromFile(f));
|
||||
}
|
||||
|
||||
// Synchronize to prevent chunks from being queued for population multiple times.
|
||||
public synchronized void checkNeighbors(int x, int z, World world) {
|
||||
BukkitWorld w = (BukkitWorld) world;
|
||||
ChunkCoordinate c = new ChunkCoordinate(x, z, (w).getUID());
|
||||
if(w.isChunkGenerated(x + 1, z)
|
||||
&& w.isChunkGenerated(x - 1, z)
|
||||
&& w.isChunkGenerated(x, z + 1)
|
||||
&& w.isChunkGenerated(x, z - 1) && needsPop.contains(c)) {
|
||||
Random random = new FastRandom(w.getSeed());
|
||||
long xRand = (random.nextLong() / 2L << 1L) + 1L;
|
||||
long zRand = (random.nextLong() / 2L << 1L) + 1L;
|
||||
random.setSeed((long) x * xRand + (long) z * zRand ^ w.getSeed());
|
||||
Chunk currentChunk = w.getChunkAt(x, z);
|
||||
generator.getGenerationStages().forEach(populator -> {
|
||||
if(!(populator instanceof Chunkified)) {
|
||||
populator.populate(w, currentChunk);
|
||||
}
|
||||
});
|
||||
needsPop.remove(c);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public void populate(org.bukkit.@NotNull World world, @NotNull Random random, org.bukkit.@NotNull Chunk source) {
|
||||
try(ProfileFrame ignore = platform.getProfiler().profile("popman")) {
|
||||
Chunk chunk = BukkitAdapter.adapt(source);
|
||||
needsPop.add(new ChunkCoordinate(chunk));
|
||||
int x = chunk.getX();
|
||||
int z = chunk.getZ();
|
||||
if(((PlatformImpl) platform).getPlugin().isEnabled()) {
|
||||
for(int xi = -1; xi <= 1; xi++) {
|
||||
for(int zi = -1; zi <= 1; zi++) {
|
||||
if(xi == 0 && zi == 0) continue;
|
||||
if(world.isChunkGenerated(xi + x, zi + z)) checkNeighbors(xi + x, zi + z, BukkitAdapter.adapt(world));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.bukkit.population;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
|
||||
public final class SerializationUtil {
|
||||
public static Object fromFile(File f) throws IOException, ClassNotFoundException {
|
||||
ObjectInputStream ois = new MovedObjectInputStream(new FileInputStream(f), "com.dfsek.terra.api.world.generation.population",
|
||||
"com.dfsek.terra.bukkit.population"); // Backwards compat with old Gaea location
|
||||
Object o = ois.readObject();
|
||||
ois.close();
|
||||
return o;
|
||||
}
|
||||
|
||||
public static void toFile(Serializable o, File f) throws IOException {
|
||||
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
|
||||
oos.writeObject(o);
|
||||
oos.close();
|
||||
}
|
||||
|
||||
public static class MovedObjectInputStream extends ObjectInputStream {
|
||||
private final String oldNameSpace;
|
||||
private final String newNameSpace;
|
||||
|
||||
public MovedObjectInputStream(InputStream in, String oldNameSpace, String newNameSpace) throws IOException {
|
||||
super(in);
|
||||
this.oldNameSpace = oldNameSpace;
|
||||
this.newNameSpace = newNameSpace;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
||||
if(desc.getName().contains(oldNameSpace)) {
|
||||
String newClassName = desc.getName().replace(oldNameSpace, newNameSpace);
|
||||
return Class.forName(newClassName);
|
||||
}
|
||||
return super.resolveClass(desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
|
||||
ObjectStreamClass result = super.readClassDescriptor();
|
||||
try {
|
||||
if(result.getName().contains(oldNameSpace)) {
|
||||
String newClassName = result.getName().replace(oldNameSpace, newNameSpace);
|
||||
Class<?> localClass = Class.forName(newClassName);
|
||||
|
||||
Field nameField = ObjectStreamClass.class.getDeclaredField("name");
|
||||
nameField.setAccessible(true);
|
||||
nameField.set(result, newClassName);
|
||||
|
||||
ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
|
||||
Field suidField = ObjectStreamClass.class.getDeclaredField("suid");
|
||||
suidField.setAccessible(true);
|
||||
suidField.set(result, localClassDescriptor.getSerialVersionUID());
|
||||
}
|
||||
} catch(Exception e) {
|
||||
throw new IOException("Exception when trying to replace namespace", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user