mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-11-12 13:44:07 +01:00
Fix an issue with setDestination not working immediately after spawn
This commit is contained in:
parent
783dd9a5a9
commit
472ac50003
@ -4,7 +4,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Iterator;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
@ -152,7 +151,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
|
||||
getServer().getScheduler().cancelTasks(this);
|
||||
}
|
||||
|
||||
Messaging.log("v" + getDescription().getVersion() + " disabled.");
|
||||
Messaging.logF("v%s disabled.", getDescription().getVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -161,8 +160,8 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
|
||||
String mcVersion = ((CraftServer) getServer()).getServer().getVersion();
|
||||
compatible = mcVersion.startsWith(COMPATIBLE_MC_VERSION);
|
||||
if (!compatible) {
|
||||
Messaging.log(Level.SEVERE, "v" + getDescription().getVersion() + " is not compatible with Minecraft v"
|
||||
+ mcVersion + ". Disabling.");
|
||||
Messaging.severeF("v%s is not compatible with Minecraft v%s. Disabling.", getDescription().getVersion(),
|
||||
mcVersion);
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
@ -181,7 +180,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
|
||||
|
||||
registerCommands();
|
||||
|
||||
Messaging.log("v" + getDescription().getVersion() + " enabled.");
|
||||
Messaging.logF("v%s enabled.", getDescription().getVersion());
|
||||
|
||||
// Setup NPCs after all plugins have been enabled (allows for multiworld
|
||||
// support and for NPCs to properly register external settings)
|
||||
@ -193,7 +192,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
|
||||
startMetrics();
|
||||
}
|
||||
}) == -1) {
|
||||
Messaging.log(Level.SEVERE, "Issue enabling plugin. Disabling.");
|
||||
Messaging.severe("Issue enabling plugin. Disabling.");
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
}
|
||||
}
|
||||
@ -254,7 +253,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
|
||||
for (DataKey key : saves.getKey("npc").getIntegerSubKeys()) {
|
||||
int id = Integer.parseInt(key.name());
|
||||
if (!key.keyExists("name")) {
|
||||
Messaging.log("Could not find a name for the NPC with ID '" + id + "'.");
|
||||
Messaging.logF("Could not find a name for the NPC with ID '%s'.", id);
|
||||
continue;
|
||||
}
|
||||
String unparsedEntityType = key.getString("traits.type", "PLAYER");
|
||||
@ -263,8 +262,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
|
||||
try {
|
||||
type = EntityType.valueOf(unparsedEntityType);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Messaging.log("NPC type '" + unparsedEntityType
|
||||
+ "' was not recognized. Did you spell it correctly?");
|
||||
Messaging.logF("NPC type '%s' was not recognized. Did you spell it correctly?", unparsedEntityType);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -275,7 +273,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
|
||||
if (npc.isSpawned())
|
||||
++spawned;
|
||||
}
|
||||
Messaging.log("Loaded " + created + " NPCs (" + spawned + " spawned).");
|
||||
Messaging.logF("Loaded %d NPCs (%d spawned).", created, spawned);
|
||||
}
|
||||
|
||||
private void setupScripting() {
|
||||
@ -302,7 +300,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
|
||||
saves = new YamlStorage(getDataFolder() + File.separator + Setting.STORAGE_FILE.asString(),
|
||||
"Citizens NPC Storage");
|
||||
}
|
||||
Messaging.log("Save method set to", saves.toString());
|
||||
Messaging.logF("Save method set to %s.", saves.toString());
|
||||
}
|
||||
|
||||
private void startMetrics() {
|
||||
|
@ -19,7 +19,7 @@ public class Settings {
|
||||
config.load();
|
||||
for (Setting setting : Setting.values()) {
|
||||
if (!root.keyExists(setting.path)) {
|
||||
Messaging.log("Writing default setting: '" + setting.path + "'");
|
||||
Messaging.logF("Writing default setting: '%s'", setting.path);
|
||||
root.setRaw(setting.path, setting.value);
|
||||
} else
|
||||
setting.set(root.getRaw(setting.path));
|
||||
|
@ -137,7 +137,7 @@ public class NPCCommands {
|
||||
max = 5,
|
||||
permission = "npc.create")
|
||||
@Requirements
|
||||
public void create(CommandContext args, Player player, NPC npc) {
|
||||
public void create(CommandContext args, final Player player, NPC npc) {
|
||||
String name = args.getString(1);
|
||||
if (name.length() > 16) {
|
||||
Messaging.sendError(player, "NPC names cannot be longer than 16 characters. The name has been shortened.");
|
||||
|
@ -5,12 +5,14 @@ import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.minecraft.server.Block;
|
||||
import net.minecraft.server.Entity;
|
||||
import net.minecraft.server.EntityLiving;
|
||||
import net.minecraft.server.EntityTypes;
|
||||
import net.minecraft.server.World;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -41,6 +43,16 @@ public abstract class CitizensMobNPC extends CitizensNPC {
|
||||
protected EntityLiving createHandle(Location loc) {
|
||||
EntityLiving entity = createEntityFromClass(((CraftWorld) loc.getWorld()).getHandle());
|
||||
entity.setPositionRotation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
|
||||
|
||||
// entity.onGround isn't updated right away - we approximate here so
|
||||
// that things like pathfinding still work *immediately* after spawn.
|
||||
org.bukkit.Material beneath = loc.getBlock().getRelative(BlockFace.DOWN).getType();
|
||||
if (beneath.isBlock()) {
|
||||
Block block = Block.byId[beneath.getId()];
|
||||
if (block != null && block.material != null) {
|
||||
entity.onGround = block.material.isSolid();
|
||||
}
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
@ -113,17 +113,15 @@ public abstract class CitizensNPC extends AbstractNPC {
|
||||
for (DataKey traitKey : root.getRelative("traits").getSubKeys()) {
|
||||
Trait trait = traitManager.getTrait(traitKey.name(), this);
|
||||
if (trait == null) {
|
||||
Messaging.severe(String.format(
|
||||
"Skipped missing trait '%s' while loading NPC ID: '%d'. Has the name changed?",
|
||||
traitKey.name(), getId()));
|
||||
Messaging.severeF("Skipped missing trait '%s' while loading NPC ID: '%d'. Has the name changed?",
|
||||
traitKey.name(), getId());
|
||||
continue;
|
||||
}
|
||||
addTrait(trait);
|
||||
try {
|
||||
getTrait(trait.getClass()).load(traitKey);
|
||||
} catch (NPCLoadException ex) {
|
||||
Messaging.log(
|
||||
String.format("The trait '%s' failed to load for NPC ID: '%d'.", traitKey.name(), getId()),
|
||||
Messaging.logF("The trait '%s' failed to load for NPC ID: '%d'.", traitKey.name(), getId(),
|
||||
ex.getMessage());
|
||||
}
|
||||
}
|
||||
@ -195,7 +193,7 @@ public abstract class CitizensNPC extends AbstractNPC {
|
||||
super.update();
|
||||
ai.update();
|
||||
} catch (Exception ex) {
|
||||
Messaging.log("Exception while updating " + getId() + ": " + ex.getMessage() + ".");
|
||||
Messaging.logF("Exception while updating %d: %s.", getId(), ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.citizensnpcs.npc.ai;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.citizensnpcs.api.ai.AI;
|
||||
@ -98,13 +99,12 @@ public class CitizensAI implements AI {
|
||||
throw new IllegalArgumentException("destination cannot be null");
|
||||
if (!npc.isSpawned())
|
||||
throw new IllegalStateException("npc is not spawned");
|
||||
if (destination.getWorld() != npc.getBukkitEntity().getWorld())
|
||||
throw new IllegalArgumentException("location is not in the same world");
|
||||
|
||||
boolean replaced = executing != null;
|
||||
executing = new MCNavigationStrategy(npc, destination);
|
||||
|
||||
if (!replaced)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < callbacks.size(); ++i) {
|
||||
NavigationCallback next = callbacks.get(i).get();
|
||||
if (next == null || (replaced && next.onCancel(this, CancelReason.REPLACE)) || next.onBegin(this)) {
|
||||
@ -121,8 +121,6 @@ public class CitizensAI implements AI {
|
||||
boolean replaced = executing != null;
|
||||
executing = new MCTargetStrategy(npc, target, aggressive);
|
||||
|
||||
if (!replaced)
|
||||
return;
|
||||
for (int i = 0; i < callbacks.size(); ++i) {
|
||||
NavigationCallback next = callbacks.get(i).get();
|
||||
if (next == null || (replaced && next.onCancel(this, CancelReason.REPLACE)) || next.onBegin(this)) {
|
||||
@ -170,17 +168,19 @@ public class CitizensAI implements AI {
|
||||
if (toRemove == null)
|
||||
return;
|
||||
for (Goal goal : toRemove) {
|
||||
for (int i = 0; i < executingGoals.size(); ++i) {
|
||||
GoalEntry entry = executingGoals.get(i);
|
||||
Iterator<GoalEntry> itr = executingGoals.iterator();
|
||||
while (itr.hasNext()) {
|
||||
GoalEntry entry = itr.next();
|
||||
if (entry.getGoal().equals(goal)) {
|
||||
entry.getGoal().reset();
|
||||
executingGoals.remove(i);
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < goals.size(); ++i) {
|
||||
GoalEntry entry = goals.get(i);
|
||||
itr = goals.iterator();
|
||||
while (itr.hasNext()) {
|
||||
GoalEntry entry = itr.next();
|
||||
if (entry.getGoal().equals(goal))
|
||||
goals.remove(i);
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
|
||||
import net.citizensnpcs.npc.CitizensNPC;
|
||||
import net.citizensnpcs.npc.entity.EntityHumanNPC;
|
||||
import net.minecraft.server.EntityLiving;
|
||||
import net.minecraft.server.Navigation;
|
||||
|
||||
@ -18,7 +17,7 @@ public class MCNavigationStrategy implements PathStrategy {
|
||||
private final EntityLiving entity;
|
||||
private final Navigation navigation;
|
||||
|
||||
MCNavigationStrategy(CitizensNPC npc, Location dest) {
|
||||
MCNavigationStrategy(final CitizensNPC npc, final Location dest) {
|
||||
entity = npc.getHandle();
|
||||
if (npc.getBukkitEntity() instanceof Player) {
|
||||
entity.onGround = true;
|
||||
@ -26,14 +25,14 @@ public class MCNavigationStrategy implements PathStrategy {
|
||||
// navigation won't execute, and calling entity.move doesn't
|
||||
// entirely fix the problem.
|
||||
}
|
||||
navigation = npc.getHandle().al();
|
||||
navigation = entity.al();
|
||||
navigation.a(dest.getX(), dest.getY(), dest.getZ(), getSpeed(npc.getHandle()));
|
||||
|
||||
}
|
||||
|
||||
MCNavigationStrategy(EntityLiving entity, EntityLiving target) {
|
||||
this.entity = entity;
|
||||
if (entity instanceof EntityHumanNPC) {
|
||||
if (entity.getBukkitEntity() instanceof Player) {
|
||||
entity.onGround = true; // see above
|
||||
}
|
||||
navigation = entity.al();
|
||||
@ -60,10 +59,6 @@ public class MCNavigationStrategy implements PathStrategy {
|
||||
|
||||
@Override
|
||||
public boolean update() {
|
||||
if (entity instanceof EntityHumanNPC) {
|
||||
navigation.d();
|
||||
((EntityHumanNPC) entity).moveOnCurrentHeading();
|
||||
}
|
||||
return navigation.e();
|
||||
}
|
||||
|
||||
|
@ -28,13 +28,13 @@ public class CitizensHumanNPC extends CitizensNPC implements Equipable {
|
||||
WorldServer ws = ((CraftWorld) loc.getWorld()).getHandle();
|
||||
final EntityHumanNPC handle = new EntityHumanNPC(ws.getServer().getServer(), ws,
|
||||
StringHelper.parseColors(getFullName()), new ItemInWorldManager(ws), this);
|
||||
handle.getBukkitEntity().teleport(loc);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handle.X = loc.getYaw() % 360;
|
||||
handle.getBukkitEntity().teleport(loc);
|
||||
// set the position in another tick - if done immediately,
|
||||
// minecraft will not update the player's position.
|
||||
// set the head yaw in another tick - if done immediately,
|
||||
// minecraft will not update it.
|
||||
}
|
||||
});
|
||||
return handle;
|
||||
@ -89,7 +89,7 @@ public class CitizensHumanNPC extends CitizensNPC implements Equipable {
|
||||
trait.set(i, null);
|
||||
}
|
||||
}
|
||||
Messaging.send(equipper, "<e>" + getName() + " <a>had all of its items removed.");
|
||||
Messaging.sendF(equipper, "<e>%s<a>had all of its items removed.", getName());
|
||||
}
|
||||
// Drop any previous equipment on the ground
|
||||
if (trait.get(slot) != null && trait.get(slot).getType() != Material.AIR)
|
||||
|
@ -11,6 +11,7 @@ import net.citizensnpcs.npc.network.NPCSocket;
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.ItemInWorldManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.Navigation;
|
||||
import net.minecraft.server.NetHandler;
|
||||
import net.minecraft.server.NetworkManager;
|
||||
import net.minecraft.server.World;
|
||||
@ -44,7 +45,11 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHandle {
|
||||
@Override
|
||||
public void F_() {
|
||||
super.F_();
|
||||
if (!npc.getAI().hasDestination() && (motX != 0 || motZ != 0 || motY != 0)) {
|
||||
Navigation navigation = al();
|
||||
if (!navigation.e()) {
|
||||
navigation.d();
|
||||
moveOnCurrentHeading();
|
||||
} else if (motX != 0 || motZ != 0 || motY != 0) {
|
||||
a(0, 0);
|
||||
}
|
||||
if (noDamageTicks > 0)
|
||||
@ -52,7 +57,7 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHandle {
|
||||
npc.update();
|
||||
}
|
||||
|
||||
public void moveOnCurrentHeading() {
|
||||
private void moveOnCurrentHeading() {
|
||||
getControllerMove().c();
|
||||
getControllerLook().a();
|
||||
getControllerJump().b();
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.citizensnpcs.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
@ -29,12 +30,34 @@ public class Messaging {
|
||||
log(Level.INFO, msg);
|
||||
}
|
||||
|
||||
public static void send(CommandSender sender, Object msg) {
|
||||
sender.sendMessage(StringHelper.parseColors(msg.toString()));
|
||||
private static String getFormatted(Object[] msg) {
|
||||
String toFormat = msg[0].toString();
|
||||
Object[] args = msg.length > 1 ? Arrays.copyOfRange(msg, 1, msg.length) : new Object[] {};
|
||||
return String.format(toFormat, args);
|
||||
}
|
||||
|
||||
public static void sendError(CommandSender sender, Object msg) {
|
||||
send(sender, ChatColor.RED.toString() + msg);
|
||||
public static void logF(Object... msg) {
|
||||
log(getFormatted(msg));
|
||||
}
|
||||
|
||||
public static void send(CommandSender sender, Object... msg) {
|
||||
String joined = SPACE.join(msg);
|
||||
joined = StringHelper.parseColors(joined);
|
||||
sender.sendMessage(joined);
|
||||
}
|
||||
|
||||
public static void sendF(CommandSender sender, Object... msg) {
|
||||
String joined = getFormatted(msg);
|
||||
joined = StringHelper.parseColors(joined);
|
||||
sender.sendMessage(joined);
|
||||
}
|
||||
|
||||
public static void sendError(CommandSender sender, Object... msg) {
|
||||
send(sender, ChatColor.RED.toString() + SPACE.join(msg));
|
||||
}
|
||||
|
||||
public static void sendErrorF(CommandSender sender, Object... msg) {
|
||||
sendF(sender, ChatColor.RED.toString() + SPACE.join(msg));
|
||||
}
|
||||
|
||||
public static void sendWithNPC(CommandSender sender, Object msg, NPC npc) {
|
||||
@ -55,4 +78,8 @@ public class Messaging {
|
||||
public static void severe(Object... messages) {
|
||||
log(Level.SEVERE, messages);
|
||||
}
|
||||
|
||||
public static void severeF(Object... messages) {
|
||||
log(Level.SEVERE, getFormatted(messages));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user