fix multiple null errors with unloaded worlds

This commit is contained in:
Pyrbu 2024-05-28 22:42:43 +02:00
parent 95ba3347b2
commit 1e80b0b217
5 changed files with 100 additions and 5 deletions

@ -0,0 +1,48 @@
package lol.pyr.znpcsplus.commands;
import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandHandler;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcTypeImpl;
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
import lol.pyr.znpcsplus.util.NpcLocation;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.List;
public class CloneCommand implements CommandHandler {
private final NpcRegistryImpl npcRegistry;
private final NpcTypeRegistryImpl typeRegistry;
public CloneCommand(NpcRegistryImpl npcRegistry, NpcTypeRegistryImpl typeRegistry) {
this.npcRegistry = npcRegistry;
this.typeRegistry = typeRegistry;
}
@Override
public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " create <id> <type>");
Player player = context.ensureSenderIsPlayer();
String id = context.popString();
if (npcRegistry.getById(id) != null) context.halt(Component.text("NPC with that ID already exists.", NamedTextColor.RED));
NpcTypeImpl type = context.parse(NpcTypeImpl.class);
NpcEntryImpl entry = npcRegistry.create(id, player.getWorld(), type, new NpcLocation(player.getLocation()));
entry.enableEverything();
context.send(Component.text("Created a " + type.getName() + " NPC with ID " + id + ".", NamedTextColor.GREEN));
}
@Override
public List<String> suggest(CommandContext context) throws CommandExecutionException {
if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
if (context.argSize() == 2) return context.suggestStream(typeRegistry.getAllImpl().stream().map(NpcTypeImpl::getName));
return Collections.emptyList();
}
}

@ -13,6 +13,7 @@ import org.bukkit.entity.Player;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
public class MoveCommand implements CommandHandler { public class MoveCommand implements CommandHandler {
private final NpcRegistryImpl npcRegistry; private final NpcRegistryImpl npcRegistry;
@ -27,7 +28,7 @@ public class MoveCommand implements CommandHandler {
Player player = context.ensureSenderIsPlayer(); Player player = context.ensureSenderIsPlayer();
NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc();
npc.setLocation(new NpcLocation(player.getLocation())); npc.setLocation(new NpcLocation(player.getLocation()));
if (!npc.getWorld().equals(player.getWorld())) npc.setWorld(player.getWorld()); if (!Objects.equals(npc.getWorld(), player.getWorld())) npc.setWorld(player.getWorld());
context.send(Component.text("NPC moved to your current location.", NamedTextColor.GREEN)); context.send(Component.text("NPC moved to your current location.", NamedTextColor.GREEN));
} }

@ -10,6 +10,7 @@ import lol.pyr.znpcsplus.util.NpcLocation;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
@ -32,7 +33,10 @@ public class NearCommand implements CommandHandler {
List<NpcEntryImpl> entries = npcRegistry.getAllModifiable().stream() List<NpcEntryImpl> entries = npcRegistry.getAllModifiable().stream()
.filter(entry -> Objects.equals(entry.getNpc().getWorld(), player.getWorld())) .filter(entry -> Objects.equals(entry.getNpc().getWorld(), player.getWorld()))
.filter(entry -> entry.getNpc().getBukkitLocation().distanceSquared(player.getLocation()) < radius) .filter(entry -> {
Location loc = entry.getNpc().getBukkitLocation();
return loc != null && loc.distanceSquared(player.getLocation()) < radius;
})
.collect(Collectors.toList()); .collect(Collectors.toList());
if (entries.isEmpty()) context.halt(Component.text("There are no npcs within " + raw + " blocks around you.", NamedTextColor.RED)); if (entries.isEmpty()) context.halt(Component.text("There are no npcs within " + raw + " blocks around you.", NamedTextColor.RED));

@ -20,6 +20,7 @@ import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -75,8 +76,10 @@ public class NpcImpl extends Viewable implements Npc {
return location; return location;
} }
public Location getBukkitLocation() { public @Nullable Location getBukkitLocation() {
return location.toBukkitLocation(getWorld()); World world = getWorld();
if (world == null) return null;
return location.toBukkitLocation(world);
} }
public void setLocation(NpcLocation location) { public void setLocation(NpcLocation location) {
@ -112,7 +115,7 @@ public class NpcImpl extends Viewable implements Npc {
return uuid; return uuid;
} }
public World getWorld() { public @Nullable World getWorld() {
return Bukkit.getWorld(worldName); return Bukkit.getWorld(worldName);
} }
@ -182,6 +185,11 @@ public class NpcImpl extends Viewable implements Npc {
setProperty((EntityPropertyImpl<T>) property, (T) value); setProperty((EntityPropertyImpl<T>) property, (T) value);
} }
@SuppressWarnings("unchecked")
public <T> void UNSAFE_setProperty(EntityProperty<?> property, Object value) {
setProperty((EntityPropertyImpl<T>) property, (T) value);
}
public Set<EntityProperty<?>> getAllProperties() { public Set<EntityProperty<?>> getAllProperties() {
return Collections.unmodifiableSet(propertyMap.keySet()); return Collections.unmodifiableSet(propertyMap.keySet());
} }

@ -1,12 +1,17 @@
package lol.pyr.znpcsplus.npc; package lol.pyr.znpcsplus.npc;
import lol.pyr.znpcsplus.ZNpcsPlus; import lol.pyr.znpcsplus.ZNpcsPlus;
import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.npc.NpcEntry; import lol.pyr.znpcsplus.api.npc.NpcEntry;
import lol.pyr.znpcsplus.api.npc.NpcRegistry; import lol.pyr.znpcsplus.api.npc.NpcRegistry;
import lol.pyr.znpcsplus.api.npc.NpcType; import lol.pyr.znpcsplus.api.npc.NpcType;
import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.config.ConfigManager;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.hologram.HologramItem;
import lol.pyr.znpcsplus.hologram.HologramLine;
import lol.pyr.znpcsplus.hologram.HologramText;
import lol.pyr.znpcsplus.interaction.ActionRegistry; import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler; import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import lol.pyr.znpcsplus.storage.NpcStorage; import lol.pyr.znpcsplus.storage.NpcStorage;
@ -153,6 +158,35 @@ public class NpcRegistryImpl implements NpcRegistry {
return entry; return entry;
} }
public NpcEntryImpl clone(String id, String newId, World newWorld, NpcLocation newLocation) {
NpcEntryImpl oldNpc = getById(id);
if (oldNpc == null) return null;
NpcEntryImpl newNpc = create(newId, newWorld, oldNpc.getNpc().getType(), newLocation);
newNpc.enableEverything();
for (EntityProperty<?> property : oldNpc.getNpc().getAllProperties()) {
newNpc.getNpc().UNSAFE_setProperty(property, oldNpc.getNpc().getProperty(property));
}
for (InteractionActionImpl action : oldNpc.getNpc().getActions()) {
newNpc.getNpc().addAction(action);
}
for (HologramLine<?> line : oldNpc.getNpc().getHologram().getLines()) {
if (line instanceof HologramText) {
HologramText text = (HologramText) line;
newNpc.getNpc().getHologram().addTextLineComponent(text.getValue());
}
else if (line instanceof HologramItem) {
HologramItem item = (HologramItem) line;
newNpc.getNpc().getHologram().addItemLinePEStack(item.getValue());
}
else throw new IllegalArgumentException("Unknown hologram line type during clone");
}
return newNpc;
}
@Override @Override
public void delete(String id) { public void delete(String id) {
NpcEntryImpl entry = npcIdLookupMap.get(id.toLowerCase()); NpcEntryImpl entry = npcIdLookupMap.get(id.toLowerCase());