9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-29 12:09:07 +00:00

Merge branch 'fix_maps' into v3.4.3

# Conflicts:
#	core/src/main/java/com/volmit/iris/core/nms/v1X/NMSBinding1X.java
#	nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java
#	nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java
#	nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java
#	nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java
#	nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java
#	nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java
This commit is contained in:
Julian Krings
2024-08-17 12:25:23 +02:00
31 changed files with 2336 additions and 369 deletions

View File

@@ -35,6 +35,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.structure.Structure;
import org.bukkit.inventory.ItemStack;
import java.awt.*;
@@ -107,8 +108,6 @@ public interface INMSBinding {
ItemStack applyCustomNbt(ItemStack itemStack, KMap<String, Object> customNbt) throws IllegalArgumentException;
void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos);
void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException;
Vector3d getBoundingbox(org.bukkit.entity.EntityType entity);
@@ -124,4 +123,6 @@ public interface INMSBinding {
default int getSpawnChunkCount(World world) {
return 441;
}
KList<String> getStructureKeys();
}

View File

@@ -30,19 +30,18 @@ import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.structure.Structure;
import org.bukkit.inventory.ItemStack;
import java.awt.*;
import java.awt.Color;
public class NMSBinding1X implements INMSBinding {
private static final boolean supportsCustomHeight = testCustomHeight();
@@ -93,11 +92,6 @@ public class NMSBinding1X implements INMSBinding {
return itemStack;
}
@Override
public void setTreasurePos(Dolphin dolphin, BlockPos pos) {
}
@Override
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
@@ -117,6 +111,15 @@ public class NMSBinding1X implements INMSBinding {
return Color.GREEN;
}
@Override
public KList<String> getStructureKeys() {
var list = Registry.STRUCTURE.stream()
.map(Structure::getKey)
.map(NamespacedKey::toString)
.toList();
return new KList<>(list);
}
@Override
public CompoundTag serializeEntity(Entity location) {
return null;

View File

@@ -22,6 +22,7 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.core.loader.ResourceLoader;
import com.volmit.iris.engine.framework.ListFunction;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
@@ -309,6 +310,24 @@ public class SchemaBuilder {
fancyType = "Enchantment Type";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
} else if (k.isAnnotationPresent(RegistryListFunction.class)) {
var functionClass = k.getDeclaredAnnotation(RegistryListFunction.class).value();
try {
var instance = functionClass.getDeclaredConstructor().newInstance();
String key = instance.key();
fancyType = instance.fancyName();
if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject();
j.put("enum", instance.apply(data));
definitions.put(key, j);
}
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid " + fancyType + " (use ctrl+space for auto complete!)");
} catch (Throwable e) {
Iris.error("Could not execute apply method in " + functionClass.getName());
}
} else if (k.getType().equals(PotionEffectType.class)) {
String key = "enum-potion-effect-type";

View File

@@ -1,93 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.service;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.container.BlockPos;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.function.Consumer4;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.matter.MatterStructurePOI;
import com.volmit.iris.util.plugin.IrisService;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.generator.structure.StructureType;
import java.util.concurrent.atomic.AtomicReference;
public class DolphinSVC implements IrisService {
@Override
public void onEnable() {
}
@Override
public void onDisable() {
}
@EventHandler
public void on(PlayerInteractEntityEvent event) {
if (!IrisToolbelt.isIrisWorld(event.getPlayer().getWorld())) {
return;
}
Material hand = event.getPlayer().getInventory().getItem(event.getHand()).getType();
if (event.getRightClicked().getType().equals(EntityType.DOLPHIN) && (hand.equals(Material.TROPICAL_FISH) || hand.equals(Material.PUFFERFISH) || hand.equals(Material.COD) || hand.equals(Material.SALMON))) {
Engine e = IrisToolbelt.access(event.getPlayer().getWorld()).getEngine();
searchNearestTreasure(e, event.getPlayer().getLocation().getBlockX() >> 4, event.getPlayer().getLocation().getBlockZ() >> 4, e.getMantle().getRadius() - 1, StructureType.BURIED_TREASURE, (x, y, z, p) -> {
event.setCancelled(true);
Dolphin d = (Dolphin) event.getRightClicked();
INMS.get().setTreasurePos(d, new BlockPos(x, y, z));
d.getWorld().playSound(d, Sound.ENTITY_DOLPHIN_EAT, SoundCategory.NEUTRAL, 1, 1);
});
}
}
@ChunkCoordinates
public void findTreasure(Engine engine, int chunkX, int chunkY, StructureType type, Consumer4<Integer, Integer, Integer, MatterStructurePOI> consumer) {
AtomicReference<MatterStructurePOI> ref = new AtomicReference<>();
engine.getMantle().getMantle().iterateChunk(chunkX, chunkY, MatterStructurePOI.class, ref.get() == null ? (x, y, z, d) -> {
if (d.getType().equals(type.getKey().getKey())) {
ref.set(d);
consumer.accept(x, y, z, d);
}
} : (x, y, z, d) -> {
});
}
@ChunkCoordinates
public void searchNearestTreasure(Engine engine, int chunkX, int chunkY, int radius, StructureType type, Consumer4<Integer, Integer, Integer, MatterStructurePOI> consumer) {
AtomicReference<MatterStructurePOI> ref = new AtomicReference<>();
new Spiraler(radius * 2, radius * 2, (x, z) -> findTreasure(engine, x, z, type, ref.get() == null ? (i, d, g, a) -> {
ref.set(a);
consumer.accept(i, d, g, a);
} : (i, d, g, a) -> {
})).setOffset(chunkX, chunkY).drain();
}
}

View File

@@ -1,127 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.service;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.plugin.VolmitSender;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.VillagerCareerChangeEvent;
import java.util.List;
public class VillageSVC implements IrisService {
@Override
public void onEnable() {
}
@Override
public void onDisable() {
}
@EventHandler
public void on(VillagerCareerChangeEvent event) {
if (!IrisToolbelt.isIrisWorld(event.getEntity().getWorld())) {
return;
}
IrisDimension dim = IrisToolbelt.access(event.getEntity().getWorld())
.getEngine().getDimension();
if (!dim.isRemoveCartographersDueToCrash()) {
return;
}
if (event.getProfession().equals(Villager.Profession.CARTOGRAPHER)) {
event.setCancelled(true);
Location eventLocation = event.getEntity().getLocation();
int radius = dim.getNotifyPlayersOfCartographerCancelledRadius();
if (radius == -1) {
return;
}
List<Player> playersInWorld = event.getEntity().getWorld().getPlayers();
String message = C.GOLD + IrisSettings.get().getGeneral().cartographerMessage;
Iris.info("Cancelled Cartographer Villager to prevent server crash at " + eventLocation + "!");
if (radius == -2) {
playersInWorld.stream().map(VolmitSender::new).forEach(v -> v.sendMessage(message));
} else {
playersInWorld.forEach(p -> {
if (p.getLocation().distance(eventLocation) < radius) {
new VolmitSender(p).sendMessage(message);
}
});
}
}
}
/*
* Replace or disable villager trade add event to prevent explorer map
*/
/* Removed due to MC breaking stuff again. This event is now called after the cartographer maps are made,
so it can fuck right off.
@EventHandler
public void on(VillagerAcquireTradeEvent event) {
if(!IrisToolbelt.isIrisWorld((event.getEntity().getWorld()))) {
return;
}
// Iris.info("Trade event: type " + event.getRecipe().getResult().getType() + " / meta " + event.getRecipe().getResult().getItemMeta() + " / data " + event.getRecipe().getResult().getData());
if(!event.getRecipe().getResult().getType().equals(Material.FILLED_MAP)) {
return;
}
IrisVillagerOverride override = IrisToolbelt.access(event.getEntity().getWorld()).getEngine()
.getDimension().getPatchCartographers();
if(override.isDisableTrade()) {
event.setCancelled(true);
Iris.debug("Cancelled cartographer trade @ " + event.getEntity().getLocation());
return;
}
if(override.getValidItems() == null) {
event.setCancelled(true);
Iris.debug("Cancelled cartographer trade because no override items are valid @ " + event.getEntity().getLocation());
return;
}
IrisVillagerTrade trade = override.getValidItems().getRandom();
event.setRecipe(trade.convert());
Iris.debug("Overrode cartographer trade with: " + trade + " to prevent allowing cartography map trades");
}
*/
}

View File

@@ -76,6 +76,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
private final ChronoLatch ecl;
private final ChronoLatch cln;
private final ChronoLatch chunkUpdater;
private final ChronoLatch chunkDiscovery;
private double energy = 25;
private int entityCount = 0;
private long charge = 0;
@@ -92,12 +93,14 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
clw = null;
looper = null;
chunkUpdater = null;
chunkDiscovery = null;
id = -1;
}
public IrisWorldManager(Engine engine) {
super(engine);
chunkUpdater = new ChronoLatch(3000);
chunkDiscovery = new ChronoLatch(5000);
cln = new ChronoLatch(60000);
cl = new ChronoLatch(3000);
ecl = new ChronoLatch(250);
@@ -128,6 +131,10 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
updateChunks();
}
if (chunkDiscovery.flip()) {
discoverChunks();
}
if (getDimension().isInfiniteEnergy()) {
energy += 1000;
@@ -174,6 +181,19 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
looper.start();
}
private void discoverChunks() {
var mantle = getEngine().getMantle().getMantle();
for (Player i : getEngine().getWorld().realWorld().getPlayers()) {
int r = 1;
for (int x = -r; x <= r; x++) {
for (int z = -r; z <= r; z++) {
mantle.getChunk(i.getLocation().getChunk()).flag(MantleFlag.DISCOVERED, true);
}
}
}
}
private void updateChunks() {
for (Player i : getEngine().getWorld().realWorld().getPlayers()) {
int r = 1;

View File

@@ -839,7 +839,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
default void gotoJigsaw(IrisJigsawStructure s, Player player, boolean teleport) {
if (s.getLoadKey().equals(getDimension().getStronghold())) {
KList<Position2> p = getDimension().getStrongholds(getSeedManager().getSpawn());
KList<Position2> p = getDimension().getStrongholds(getSeedManager().getMantle());
if (p.isEmpty()) {
player.sendMessage(C.GOLD + "No strongholds in world.");

View File

@@ -110,7 +110,7 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
return;
}
KList<Position2> positions = getEngine().getDimension().getStrongholds(getEngine().getSeedManager().getSpawn());
KList<Position2> positions = getEngine().getDimension().getStrongholds(getEngine().getSeedManager().getMantle());
if (positions.isEmpty()) {
return;
}

View File

@@ -0,0 +1,8 @@
package com.volmit.iris.engine.framework;
import java.util.function.Function;
public interface ListFunction<T, R> extends Function<T, R> {
String key();
String fancyName();
}

View File

@@ -0,0 +1,121 @@
package com.volmit.iris.engine.framework;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.engine.object.IrisObject;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import org.apache.commons.lang3.function.TriFunction;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
@FunctionalInterface
public interface ResultLocator<T> {
static void cancelSearch() {
if (LocatorCanceller.cancel != null) {
LocatorCanceller.cancel.run();
LocatorCanceller.cancel = null;
}
}
static ResultLocator<IrisJigsawStructure> locateStructure(Collection<String> keys) {
return (e, pos) -> {
var structure = e.getStructureAt(pos.getX(), pos.getZ());
return structure != null && keys.contains(structure.getLoadKey()) ? structure : null;
};
}
static ResultLocator<IrisObject> locateObject(Collection<String> keys) {
return (e, pos) -> {
Set<String> objects = e.getObjectsAt(pos.getX(), pos.getZ());
for (String object : objects) {
if (!keys.contains(object)) continue;
return e.getData().getObjectLoader().load(object);
}
return null;
};
}
T find(Engine e, Position2 chunkPos);
default <R> ResultLocator<R> then(TriFunction<Engine, Position2, T, R> filter) {
return (e, pos) -> {
var t = find(e, pos);
return t != null ? filter.apply(e, pos, t) : null;
};
}
default Future<Result<T>> find(Engine engine, Position2 pos, long timeout, Consumer<Integer> checks, boolean cancelable) throws WrongEngineBroException {
if (engine.isClosed()) {
throw new WrongEngineBroException();
}
cancelSearch();
return MultiBurst.burst.completeValue(() -> {
int tc = IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism()) * 17;
MultiBurst burst = MultiBurst.burst;
AtomicBoolean found = new AtomicBoolean(false);
AtomicReference<Result<T>> foundObj = new AtomicReference<>();
Position2 cursor = pos;
AtomicInteger searched = new AtomicInteger();
AtomicBoolean stop = new AtomicBoolean(false);
PrecisionStopwatch px = PrecisionStopwatch.start();
if (cancelable) LocatorCanceller.cancel = () -> stop.set(true);
AtomicReference<Position2> next = new AtomicReference<>(cursor);
Spiraler s = new Spiraler(100000, 100000, (x, z) -> next.set(new Position2(x, z)));
s.setOffset(cursor.getX(), cursor.getZ());
s.next();
while (!found.get() && !stop.get() && px.getMilliseconds() < timeout) {
BurstExecutor e = burst.burst(tc);
for (int i = 0; i < tc; i++) {
Position2 p = next.get();
s.next();
e.queue(() -> {
var o = find(engine, p);
if (o != null) {
if (foundObj.get() == null) {
foundObj.set(new Result<>(o, p));
}
found.set(true);
}
searched.incrementAndGet();
});
}
e.complete();
checks.accept(searched.get());
}
LocatorCanceller.cancel = null;
if (found.get() && foundObj.get() != null) {
return foundObj.get();
}
return null;
});
}
record Result<T>(T obj, Position2 pos) {
public int getBlockX() {
return (pos.getX() << 4) + 8;
}
public int getBlockZ() {
return (pos.getZ() << 4) + 8;
}
}
}

View File

@@ -300,10 +300,8 @@ public class IrisDimension extends IrisRegistrant {
private IrisMaterialPalette rockPalette = new IrisMaterialPalette().qclear().qadd("stone");
@Desc("The palette of blocks for 'water'")
private IrisMaterialPalette fluidPalette = new IrisMaterialPalette().qclear().qadd("water");
@Desc("Remove cartographers so they do not crash the server (Iris worlds only)")
private boolean removeCartographersDueToCrash = true;
@Desc("Notify players of cancelled cartographer villager in this radius in blocks (set to -1 to disable, -2 for everyone)")
private int notifyPlayersOfCartographerCancelledRadius = 30;
@Desc("Prevent cartographers to generate explorer maps (Iris worlds only)\nONLY TOUCH IF YOUR SERVER CRASHES WHILE GENERATING EXPLORER MAPS")
private boolean disableExplorerMaps = false;
@Desc("Collection of ores to be generated")
@ArrayType(type = IrisOreGenerator.class, min = 1)
private KList<IrisOreGenerator> ores = new KList<>();

View File

@@ -69,6 +69,10 @@ public class IrisJigsawStructure extends IrisRegistrant {
@Desc("Set to true to prevent rotating the initial structure piece")
private boolean disableInitialRotation = false;
@RegistryListFunction(StructureKeyFunction.class)
@Desc("The minecraft key to use when creating treasure maps")
private String structureKey = null;
private transient AtomicCache<Integer> maxDimension = new AtomicCache<>();
private void loadPool(String p, KList<String> pools, KList<String> pieces) {

View File

@@ -0,0 +1,17 @@
package com.volmit.iris.engine.object.annotations;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.framework.ListFunction;
import com.volmit.iris.util.collection.KList;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListFunction {
Class<? extends ListFunction<IrisData, KList<String>>> value();
}

View File

@@ -0,0 +1,23 @@
package com.volmit.iris.engine.object.annotations;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.framework.ListFunction;
import com.volmit.iris.util.collection.KList;
public class StructureKeyFunction implements ListFunction<IrisData, KList<String>> {
@Override
public String key() {
return "structure-key";
}
@Override
public String fancyName() {
return "Structure Key";
}
@Override
public KList<String> apply(IrisData irisData) {
return INMS.get().getStructureKeys();
}
}

View File

@@ -34,7 +34,8 @@ public enum MantleFlag {
PLANNED,
ETCHED,
TILE,
CUSTOM;
CUSTOM,
DISCOVERED;
static StateList getStateList() {
return new StateList(MantleFlag.values());