Document a portion of NPCs

This commit is contained in:
Sam 2017-09-19 14:36:32 +01:00
parent de6ead8b2a
commit e392b65c68
4 changed files with 166 additions and 4 deletions

View File

@ -39,6 +39,13 @@ import mineplex.core.newnpc.event.NPCInteractEvent;
import mineplex.core.newnpc.event.NPCRefreshEvent;
import mineplex.core.recharge.Recharge;
/**
* NPCManager is a new version of the previous NpcManager to improve usability and more general purpose.
* <br>
* NPCs are saved in the table <b>newNPCs</b> in the <b>accounts</b> database.
* <br>
* Details on how to create NPCs can be found in the {@link NPC} and {@link PlayerNPC} classes.
*/
@ReflectivelyCreateMiniPlugin
public class NewNPCManager extends MiniPlugin
{
@ -71,7 +78,9 @@ public class NewNPCManager extends MiniPlugin
_builders = new HashMap<>();
_teleportMap = new HashMap<>();
// Loading NPCs on the main thread makes sure that _npcs is populated before anything tries to spawn NPCs.
loadNPCs();
// Any NPC with the metadata DUMMY will always be spawned regardless, useful for testing designs
spawnNPCs("DUMMY", null);
generatePermissions();
@ -93,6 +102,12 @@ public class NewNPCManager extends MiniPlugin
addCommand(new NPCCommand(this));
}
/**
* Loads synchronously all NPCs from the database and populates the {@link #_npcs} list if the npc was not already
* contained within the collection. Thus this method can be called more than once during runtime. Though it is
* recommended that if the caller is not calling this during startup then this should not be called from the main
* thread.
*/
private void loadNPCs()
{
_repository.getNPCs(npcs ->
@ -109,6 +124,12 @@ public class NewNPCManager extends MiniPlugin
});
}
/**
* Spawns all NPCs that have the metadata specified.
*
* @param metadata The metadata that must equal the NPC's metadata.
* @param after A callback consumer for each npc.
*/
public void spawnNPCs(String metadata, Consumer<NPC> after)
{
_creature.SetForce(true);
@ -128,6 +149,9 @@ public class NewNPCManager extends MiniPlugin
_creature.SetForce(false);
}
/**
* Calls {@link #loadNPCs()} then the {@link NPCRefreshEvent}
*/
public void refreshNPCS()
{
loadNPCs();
@ -135,6 +159,11 @@ public class NewNPCManager extends MiniPlugin
UtilServer.CallEvent(new NPCRefreshEvent());
}
/**
* Removes an NPC's entity and removes it from the database.
*
* @param npc The NPC you want to delete.
*/
public void deleteNPC(NPC npc)
{
runAsync(() -> _repository.deleteNPC(npc));
@ -147,6 +176,11 @@ public class NewNPCManager extends MiniPlugin
_npcs.remove(npc);
}
/**
* Deletes every NPC.
*
* @param deleteFromDB If true, all NPC's are deleted from the database. If false this action is only temporary.
*/
public void clearNPCS(boolean deleteFromDB)
{
if (deleteFromDB)
@ -165,25 +199,54 @@ public class NewNPCManager extends MiniPlugin
_npcs.clear();
}
/**
* @param npc The NPC you want to spawn.
* @see #addNPC(NPC, boolean)
*/
public void addNPC(NPC npc)
{
addNPC(npc, true);
}
/**
* Adds and spawns an NPC.
*
* @param npc The NPC you want to spawn.
* @param saveToDB If true the NPC will be saved to the database.
*/
public void addNPC(NPC npc, boolean saveToDB)
{
_creature.SetForce(true);
_npcs.add(npc);
npc.spawnEntity();
runAsync(() -> _repository.insertNPCIfNotExists(npc));
if (saveToDB)
{
runAsync(() -> _repository.insertNPCIfNotExists(npc));
}
_creature.SetForce(false);
}
/**
* Used by {@link NPCMoveCommand}. Has no other purpose.
*/
@Deprecated
public void setPlayerTeleport(Player player)
{
_teleportMap.put(player, player.getLocation());
}
/**
* Teleports an NPC to a location and saves that in the database for future reference.
*
* @param npc The NPC you want to move.
* @param location The Location you want to move the NPC to.
*/
public void teleport(NPC npc, Location location)
{
// If there isn't an entity or the location to go is null, then don't teleport.
if (npc.getEntity() == null || location == null)
{
return;
@ -193,6 +256,9 @@ public class NewNPCManager extends MiniPlugin
runAsync(() -> _repository.teleportNPC(npc, location));
}
/**
* Used by {@link mineplex.core.newnpc.command.NPCBuildCommand}. Has no other purpose.
*/
public void createBuilder(Player player)
{
_builders.put(player, new NPCBuilder());
@ -201,6 +267,9 @@ public class NewNPCManager extends MiniPlugin
player.sendMessage(F.main("Step 1", "Type in chat the Entity Type of your NPC."));
}
/**
* Cleans up NPC creation maps, if the player quits.
*/
@EventHandler
public void playerQuit(PlayerQuitEvent event)
{
@ -210,6 +279,9 @@ public class NewNPCManager extends MiniPlugin
_teleportMap.remove(player);
}
/**
* Handles {@link NPCBuilder} data input.
*/
@EventHandler(priority = EventPriority.LOWEST)
public void chat(AsyncPlayerChatEvent event)
{
@ -296,6 +368,9 @@ public class NewNPCManager extends MiniPlugin
_builders.remove(player);
}
/**
* Handles {@link NPCDeleteCommand} and {@link NPCMoveCommand} data input.
*/
@EventHandler(priority = EventPriority.LOWEST)
public void npcInteract(NPCInteractEvent event)
{
@ -318,6 +393,9 @@ public class NewNPCManager extends MiniPlugin
}
}
/**
* Prevents chunk unloading when there is an NPC in it.
*/
@EventHandler
public void chunkUnload(ChunkUnloadEvent event)
{
@ -331,6 +409,10 @@ public class NewNPCManager extends MiniPlugin
}
}
/*
A collection of listeners that make sure NPCs don't die.
*/
@EventHandler
public void entityCombust(EntityCombustEvent event)
{
@ -383,6 +465,11 @@ public class NewNPCManager extends MiniPlugin
event.GetEntities().removeIf(this::isNPC);
}
/**
* @param metadata The metadata you wish to find all the NPCs of.
* @return A list of {@link NPC} that are unloaded (have no entity attached to them) and that have the metadata
* specified.
*/
private List<NPC> getUnloadedNPCs(String metadata)
{
return _npcs.stream()
@ -390,6 +477,10 @@ public class NewNPCManager extends MiniPlugin
.collect(Collectors.toList());
}
/**
* @param entity The entity you want to get it's NPC of.
* @return The {@link NPC} representation of that entity or null if the entity is not an NPC.
*/
public NPC getNPC(Entity entity)
{
for (NPC npc : _npcs)
@ -403,6 +494,10 @@ public class NewNPCManager extends MiniPlugin
return null;
}
/**
* @param entity The entity you want to check.
* @return true if the entity is a {@link NPC}.
*/
private boolean isNPC(Entity entity)
{
return getNPC(entity) != null;

View File

@ -17,13 +17,31 @@ import mineplex.serverdata.database.column.ColumnDouble;
import mineplex.serverdata.database.column.ColumnInt;
import mineplex.serverdata.database.column.ColumnVarChar;
/**
* A repository class that provides an interface for getting and saving NPCs.
*/
class NewNPCRepository extends RepositoryBase
{
/**
* A SQL statement that returns all entries form the table.
*/
private static final String GET_NPCS = "SELECT * FROM newNPCs;";
/**
* A SQL statement that inserts an entry and returns the id field generated.
*/
private static final String INSERT_NPC = "INSERT INTO newNPCs (entity_type, name, world, x, y, z, yaw, pitch, in_hand, in_hand_data, helmet, chestplate, leggings, boots, metadata, skinValue, skinSignature) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
/**
* A SQL statement that deletes an entry with a specific id field.
*/
private static final String DELETE_NPC = "DELETE FROM newNPCs WHERE id=?;";
/**
* A SQL statement that removes all entries from the table.
*/
private static final String CLEAR_NPCS = "DELETE FROM newNPCs;";
/**
* A SQL statement that adjusts the location properties of an entry with a specific id field.
*/
private static final String MOVE_NPC = "UPDATE newNPCs SET world=?, x=?, y=?, z=?, yaw=?, pitch=? WHERE id=?";
NewNPCRepository()
@ -31,12 +49,23 @@ class NewNPCRepository extends RepositoryBase
super(DBPool.getAccount());
}
/**
* Executes the SQL query:
* <p>
* {@value GET_NPCS}
* </p>
* The values return are parsed into an instance of {@link NPC} or one of it's subclasses such as {@link PlayerNPC}
* if appropriate.
*
* @param response The consumer callback that supplies the list of NPCs.
*/
void getNPCs(Consumer<List<NPC>> response)
{
executeQuery(GET_NPCS, resultSet ->
{
List<NPC> npcs = new ArrayList<>();
// While there are more entries
while (resultSet.next())
{
int id = resultSet.getInt("id");
@ -61,11 +90,13 @@ class NewNPCRepository extends RepositoryBase
NPC npc;
World world = Bukkit.getWorld(worldName);
// If the world is not loaded on the server then don't add it to the list
if (world == null)
{
continue;
}
// If the entity type is of player then the NPC must be specified as a PlayerNPC
if (entityType == EntityType.PLAYER)
{
npc = new PlayerNPC(id, name, new Location(world, x, y, z, yaw, pitch), inHand, inHandData, helmet, chestplate, leggings, boots, metadata, skinValue, skinSignature);
@ -81,7 +112,8 @@ class NewNPCRepository extends RepositoryBase
response.accept(npcs);
});
}
// Simply calls Material.valueOf, if invalid null
private Material parseMaterial(String material)
{
try
@ -94,8 +126,18 @@ class NewNPCRepository extends RepositoryBase
}
}
/**
* Executes the SQL insert:
* <p>
* {@value INSERT_NPC}
* </p>
* If the NPC does not have an id of -1, the insert will not be run.
*
* @param npc The NPC you want to insert into the database.
*/
void insertNPCIfNotExists(NPC npc)
{
// If the id isn't -1 then it has already been inserted
if (npc.getId() != -1)
{
return;
@ -104,23 +146,48 @@ class NewNPCRepository extends RepositoryBase
Column<?>[] columns = npc.toDatabaseQuery().toArray(new Column[0]);
executeInsert(INSERT_NPC, resultSet ->
{
// If successful
if (resultSet.next())
{
// Set the NPC's id with that generated by the database
npc.setId(resultSet.getInt(1));
}
}, columns);
}
/**
* Executes the SQL insert:
* <p>
* {@value DELETE_NPC}
* </p>
*
* @param npc The NPC you want to delete.
*/
void deleteNPC(NPC npc)
{
executeUpdate(DELETE_NPC, new ColumnInt("id", npc.getId()));
}
/**
* Executes the SQL insert:
* <p>
* {@value CLEAR_NPCS}
* </p>
*/
void clearNPCs()
{
executeUpdate(CLEAR_NPCS);
}
/**
* Executes the SQL insert:
* <p>
* {@value MOVE_NPC}
* </p>
*
* @param npc The NPC you want to teleport.
* @param location The Location that you want to the npc to teleport to.
*/
void teleportNPC(NPC npc, Location location)
{
executeUpdate(MOVE_NPC,

View File

@ -19,7 +19,7 @@ public class NPCRefreshCommand extends CommandBase<NewNPCManager>
public void Execute(Player caller, String[] args)
{
caller.sendMessage(F.main(Plugin.getName(), "Refreshing NPCs..."));
Plugin.refreshNPCS();
Plugin.runAsync(() -> Plugin.refreshNPCS());
caller.sendMessage(F.main(Plugin.getName(), "Refreshed NPCs"));
}
}

View File

@ -16,7 +16,7 @@ public class NewsRepository extends RepositoryBase
private static final String INSERT_NEWS = "INSERT INTO hubNews (newsValue) VALUES (?);";
private static final String DELETE_NEWS = "DELETE FROM hubNews WHERE newsId=?;";
public NewsRepository()
NewsRepository()
{
super(DBPool.getAccount());
}