mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2025-02-02 21:41:43 +01:00
Changes to trait api
This commit is contained in:
parent
28a9b62c25
commit
044c961522
Binary file not shown.
@ -4,6 +4,7 @@ import java.io.File;
|
||||
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
import net.citizensnpcs.api.Factory;
|
||||
import net.citizensnpcs.api.exception.NPCLoadException;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.trait.Character;
|
||||
@ -23,18 +24,14 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class Citizens extends JavaPlugin {
|
||||
private final CitizensNPCManager npcManager;
|
||||
private final CitizensCharacterManager characterManager;
|
||||
private final CitizensTraitManager traitManager;
|
||||
private Storage saves;
|
||||
private static final CitizensNPCManager npcManager = new CitizensNPCManager();
|
||||
private static final CitizensCharacterManager characterManager = new CitizensCharacterManager();
|
||||
private static final CitizensTraitManager traitManager = new CitizensTraitManager();
|
||||
private Settings config;
|
||||
private Storage saves;
|
||||
|
||||
public Citizens() {
|
||||
super();
|
||||
// Register API managers
|
||||
npcManager = new CitizensNPCManager();
|
||||
characterManager = new CitizensCharacterManager();
|
||||
traitManager = new CitizensTraitManager();
|
||||
CitizensAPI.setNPCManager(npcManager);
|
||||
CitizensAPI.setCharacterManager(characterManager);
|
||||
CitizensAPI.setTraitManager(traitManager);
|
||||
@ -44,6 +41,7 @@ public class Citizens extends JavaPlugin {
|
||||
public void onDisable() {
|
||||
config.save();
|
||||
saveNPCs();
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
|
||||
Messaging.log("v" + getDescription().getVersion() + " disabled.");
|
||||
}
|
||||
@ -58,7 +56,7 @@ public class Citizens extends JavaPlugin {
|
||||
saves = new YamlStorage(getDataFolder() + File.separator + "saves.yml");
|
||||
|
||||
// Register events
|
||||
getServer().getPluginManager().registerEvents(new EventListen(), this);
|
||||
getServer().getPluginManager().registerEvents(new EventListen(npcManager), this);
|
||||
|
||||
Messaging.log("v" + getDescription().getVersion() + " enabled.");
|
||||
|
||||
@ -85,7 +83,7 @@ public class Citizens extends JavaPlugin {
|
||||
NPC npc = npcManager.createNPC("aPunch");
|
||||
npc.spawn(((Player) sender).getLocation());
|
||||
} else if (args[0].equals("despawn")) {
|
||||
for (NPC npc : npcManager.getNPCs()) {
|
||||
for (NPC npc : npcManager.getSpawnedNPCs()) {
|
||||
npc.despawn();
|
||||
}
|
||||
}
|
||||
@ -94,7 +92,12 @@ public class Citizens extends JavaPlugin {
|
||||
|
||||
// TODO possibly separate this out some more
|
||||
private void setupNPCs() throws NPCLoadException {
|
||||
traitManager.registerTrait(SpawnLocation.class);
|
||||
traitManager.registerTraitFactory("location", new Factory<SpawnLocation>() {
|
||||
@Override
|
||||
public SpawnLocation create() {
|
||||
return new SpawnLocation();
|
||||
}
|
||||
});
|
||||
int spawned = 0;
|
||||
for (DataKey key : saves.getKey("npc").getIntegerSubKeys()) {
|
||||
int id = Integer.parseInt(key.name());
|
||||
@ -104,9 +107,9 @@ public class Citizens extends JavaPlugin {
|
||||
NPC npc = npcManager.createNPC(key.getString("name"), character);
|
||||
|
||||
// Load the character if it exists, otherwise remove the character
|
||||
if (character != null)
|
||||
if (character != null) {
|
||||
character.load(key.getRelative(character.getName()));
|
||||
else {
|
||||
} else {
|
||||
if (key.keyExists("character")) {
|
||||
Messaging.debug("Character '" + key.getString("character")
|
||||
+ "' does not exist. Removing character from the NPC with ID '" + npc.getId() + "'.");
|
||||
@ -116,15 +119,11 @@ public class Citizens extends JavaPlugin {
|
||||
|
||||
// Load traits
|
||||
for (DataKey traitKey : key.getSubKeys()) {
|
||||
for (Trait trait : traitManager.getRegisteredTraits()) {
|
||||
if (trait.getName().equals(traitKey.name())) {
|
||||
Messaging.debug("Found trait '" + trait.getName() + "' in the NPC with ID '" + id + "'.");
|
||||
npc.addTrait(trait.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Trait trait : npc.getTraits()) {
|
||||
trait.load(key.getRelative(trait.getName()));
|
||||
Trait trait = traitManager.getTrait(traitKey.name());
|
||||
if (trait == null)
|
||||
continue;
|
||||
trait.load(traitKey);
|
||||
npc.addTrait(trait);
|
||||
}
|
||||
|
||||
// Spawn the NPC
|
||||
@ -133,11 +132,11 @@ public class Citizens extends JavaPlugin {
|
||||
spawned++;
|
||||
}
|
||||
}
|
||||
Messaging.log("Loaded " + npcManager.getNPCs().size() + " NPCs (" + spawned + " spawned).");
|
||||
Messaging.log("Loaded " + npcManager.size() + " NPCs (" + spawned + " spawned).");
|
||||
}
|
||||
|
||||
private void saveNPCs() {
|
||||
for (NPC npc : npcManager.getNPCs()) {
|
||||
for (NPC npc : npcManager.getAllNPCs()) {
|
||||
DataKey root = saves.getKey("npc." + npc.getId());
|
||||
root.setString("name", npc.getFullName());
|
||||
root.setBoolean("spawned", npc.isSpawned());
|
||||
|
@ -1,10 +1,11 @@
|
||||
package net.citizensnpcs;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.NPCManager;
|
||||
import net.citizensnpcs.api.npc.trait.trait.SpawnLocation;
|
||||
|
||||
import org.bukkit.Location;
|
||||
@ -18,21 +19,26 @@ import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
|
||||
public class EventListen implements Listener {
|
||||
private Set<Integer> toRespawn = new HashSet<Integer>();
|
||||
private final List<Integer> toRespawn = new ArrayList<Integer>();
|
||||
private final NPCManager manager;
|
||||
|
||||
public EventListen(NPCManager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
/*
|
||||
* Entity events
|
||||
*/
|
||||
@EventHandler
|
||||
public void onEntityDamage(EntityDamageEvent event) {
|
||||
if (!CitizensAPI.getNPCManager().isNPC(event.getEntity()))
|
||||
if (!manager.isNPC(event.getEntity()))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
event.setCancelled(true); // TODO: implement damage handlers
|
||||
if (event instanceof EntityDamageByEntityEvent) {
|
||||
EntityDamageByEntityEvent e = (EntityDamageByEntityEvent) event;
|
||||
if (e.getDamager() instanceof Player) {
|
||||
NPC npc = CitizensAPI.getNPCManager().getNPC(event.getEntity());
|
||||
NPC npc = manager.getNPC(event.getEntity());
|
||||
if (npc.getCharacter() != null) {
|
||||
npc.getCharacter().onLeftClick(npc, (Player) e.getDamager());
|
||||
}
|
||||
@ -42,11 +48,10 @@ public class EventListen implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onEntityTarget(EntityTargetEvent event) {
|
||||
if (event.isCancelled() || !CitizensAPI.getNPCManager().isNPC(event.getEntity())
|
||||
|| !(event.getTarget() instanceof Player))
|
||||
if (event.isCancelled() || !manager.isNPC(event.getEntity()) || !(event.getTarget() instanceof Player))
|
||||
return;
|
||||
|
||||
NPC npc = CitizensAPI.getNPCManager().getNPC(event.getEntity());
|
||||
NPC npc = manager.getNPC(event.getEntity());
|
||||
npc.getCharacter().onRightClick(npc, (Player) event.getTarget());
|
||||
}
|
||||
|
||||
@ -55,10 +60,10 @@ public class EventListen implements Listener {
|
||||
*/
|
||||
@EventHandler
|
||||
public void onChunkLoad(ChunkLoadEvent event) {
|
||||
for (int id : toRespawn) {
|
||||
NPC npc = CitizensAPI.getNPCManager().getNPC(id);
|
||||
for (Iterator<Integer> itr = toRespawn.iterator();; itr.hasNext()) {
|
||||
NPC npc = manager.getNPC(itr.next());
|
||||
npc.spawn(npc.getTrait(SpawnLocation.class).getLocation());
|
||||
toRespawn.remove(id);
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +72,7 @@ public class EventListen implements Listener {
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
|
||||
for (NPC npc : CitizensAPI.getNPCManager().getNPCs()) {
|
||||
for (NPC npc : manager.getSpawnedNPCs()) {
|
||||
Location loc = npc.getBukkitEntity().getLocation();
|
||||
if (event.getWorld().equals(loc.getWorld()) && event.getChunk().getX() == loc.getChunk().getX()
|
||||
&& event.getChunk().getZ() == loc.getChunk().getZ()) {
|
||||
|
@ -51,7 +51,7 @@ public class Settings {
|
||||
}
|
||||
}
|
||||
|
||||
private YamlStorage config;
|
||||
private final YamlStorage config;
|
||||
private final DataKey root;
|
||||
|
||||
public Settings(Citizens plugin) {
|
||||
|
@ -4,11 +4,12 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.Factory;
|
||||
import net.citizensnpcs.api.event.NPCDespawnEvent;
|
||||
import net.citizensnpcs.api.event.NPCSpawnEvent;
|
||||
import net.citizensnpcs.api.npc.trait.Character;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.pathfinding.Navigator;
|
||||
import net.citizensnpcs.api.npc.trait.Character;
|
||||
import net.citizensnpcs.api.npc.trait.Trait;
|
||||
import net.citizensnpcs.api.npc.trait.trait.SpawnLocation;
|
||||
import net.citizensnpcs.resources.lib.CraftNPC;
|
||||
@ -21,13 +22,12 @@ import org.bukkit.entity.Entity;
|
||||
|
||||
public class CitizensNPC implements NPC {
|
||||
private final int id;
|
||||
private Character character = null;
|
||||
private Character character;
|
||||
private final Map<Class<? extends Trait>, Trait> traits = new HashMap<Class<? extends Trait>, Trait>();
|
||||
private String name;
|
||||
private CraftNPC mcEntity;
|
||||
private boolean spawned;
|
||||
private final CitizensNPCManager manager;
|
||||
private final Factory factory = new Factory();
|
||||
|
||||
public CitizensNPC(String name, Character character) {
|
||||
this.name = name;
|
||||
@ -59,11 +59,12 @@ public class CitizensNPC implements NPC {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTrait(Class<? extends Trait> trait) {
|
||||
if (!hasTrait(trait))
|
||||
traits.put(trait, factory.create(trait));
|
||||
else
|
||||
Messaging.debug("The NPC already has the trait '" + getTrait(trait).getName() + "'.");
|
||||
public void addTrait(Trait trait) {
|
||||
if (!hasTrait(trait.getClass())) {
|
||||
traits.put(trait.getClass(), trait);
|
||||
} else {
|
||||
Messaging.debug("The NPC already has the trait '" + getTrait(trait.getClass()).getName() + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -83,12 +84,9 @@ public class CitizensNPC implements NPC {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Trait> T getTrait(Class<T> trait) {
|
||||
Trait t = traits.get(trait);
|
||||
if (t != null) {
|
||||
return trait.cast(t);
|
||||
}
|
||||
return null;
|
||||
public <T extends Trait> T getTrait(Class<T> clazz) {
|
||||
Trait t = traits.get(clazz);
|
||||
return t != null ? clazz.cast(t) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -137,14 +135,14 @@ public class CitizensNPC implements NPC {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mcEntity == null)
|
||||
if (mcEntity == null) {
|
||||
mcEntity = manager.spawn(this, loc);
|
||||
else
|
||||
} else {
|
||||
manager.spawn(this, loc);
|
||||
}
|
||||
|
||||
// Set the location
|
||||
addTrait(SpawnLocation.class);
|
||||
getTrait(SpawnLocation.class).setLocation(loc);
|
||||
addTrait(new SpawnLocation(loc));
|
||||
|
||||
spawned = true;
|
||||
}
|
||||
@ -180,15 +178,23 @@ public class CitizensNPC implements NPC {
|
||||
return mcEntity;
|
||||
}
|
||||
|
||||
private class Factory {
|
||||
public static class ReflectionTraitFactory implements Factory<Trait> {
|
||||
private final Class<? extends Trait> clazz;
|
||||
|
||||
public <T extends Trait> T create(Class<T> clazz) {
|
||||
public ReflectionTraitFactory(Class<? extends Trait> clazz) {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trait create() {
|
||||
try {
|
||||
return clazz.cast(clazz.newInstance());
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
return clazz.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,20 @@
|
||||
package net.citizensnpcs.npc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.NPCManager;
|
||||
import net.citizensnpcs.api.npc.trait.Character;
|
||||
import net.citizensnpcs.api.npc.trait.Trait;
|
||||
import net.citizensnpcs.api.npc.trait.trait.SpawnLocation;
|
||||
import net.citizensnpcs.resources.lib.CraftNPC;
|
||||
import net.citizensnpcs.util.ByIdArray;
|
||||
import net.minecraft.server.ItemInWorldManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.Packet29DestroyEntity;
|
||||
import net.minecraft.server.WorldServer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -16,21 +26,9 @@ import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.NPCManager;
|
||||
import net.citizensnpcs.api.npc.trait.Character;
|
||||
import net.citizensnpcs.api.npc.trait.Trait;
|
||||
import net.citizensnpcs.api.npc.trait.trait.SpawnLocation;
|
||||
import net.citizensnpcs.resources.lib.CraftNPC;
|
||||
|
||||
import net.minecraft.server.ItemInWorldManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.Packet29DestroyEntity;
|
||||
import net.minecraft.server.WorldServer;
|
||||
|
||||
public class CitizensNPCManager implements NPCManager {
|
||||
private final Map<Entity, NPC> spawned = new ConcurrentHashMap<Entity, NPC>();
|
||||
private final Map<Integer, NPC> byID = new ConcurrentHashMap<Integer, NPC>();
|
||||
private final ByIdArray<NPC> spawned = ByIdArray.create();
|
||||
private final ByIdArray<NPC> byID = ByIdArray.create();
|
||||
|
||||
@Override
|
||||
public NPC createNPC(String name) {
|
||||
@ -51,18 +49,23 @@ public class CitizensNPCManager implements NPCManager {
|
||||
|
||||
@Override
|
||||
public NPC getNPC(Entity entity) {
|
||||
return spawned.get(entity);
|
||||
return spawned.get(entity.getEntityId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NPC> getNPCs() {
|
||||
return byID.values();
|
||||
public Iterable<NPC> getAllNPCs() {
|
||||
return byID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<NPC> getSpawnedNPCs() {
|
||||
return spawned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NPC> getNPCs(Class<? extends Trait> trait) {
|
||||
Set<NPC> npcs = new HashSet<NPC>();
|
||||
for (NPC npc : byID.values()) {
|
||||
List<NPC> npcs = new ArrayList<NPC>();
|
||||
for (NPC npc : byID) {
|
||||
if (npc.hasTrait(trait))
|
||||
npcs.add(npc);
|
||||
}
|
||||
@ -71,7 +74,7 @@ public class CitizensNPCManager implements NPCManager {
|
||||
|
||||
@Override
|
||||
public boolean isNPC(Entity entity) {
|
||||
return spawned.containsKey(entity);
|
||||
return spawned.contains(entity.getEntityId());
|
||||
}
|
||||
|
||||
public int getUniqueID() {
|
||||
@ -85,6 +88,8 @@ public class CitizensNPCManager implements NPCManager {
|
||||
}
|
||||
|
||||
public CraftNPC spawn(NPC npc, Location loc) {
|
||||
if (spawned.contains(npc.getBukkitEntity().getEntityId()))
|
||||
throw new IllegalStateException("already spawned");
|
||||
WorldServer ws = getWorldServer(loc.getWorld());
|
||||
CraftNPC mcEntity = new CraftNPC(getMinecraftServer(ws.getServer()), ws, npc.getFullName(),
|
||||
new ItemInWorldManager(ws));
|
||||
@ -93,11 +98,13 @@ public class CitizensNPCManager implements NPCManager {
|
||||
ws.addEntity(mcEntity);
|
||||
ws.players.remove(mcEntity);
|
||||
|
||||
spawned.put(mcEntity.getPlayer(), npc);
|
||||
spawned.put(mcEntity.getPlayer().getEntityId(), npc);
|
||||
return mcEntity;
|
||||
}
|
||||
|
||||
public void despawn(NPC npc) {
|
||||
if (!spawned.contains(npc.getBukkitEntity().getEntityId()))
|
||||
throw new IllegalStateException("already despawned");
|
||||
CraftNPC mcEntity = ((CitizensNPC) npc).getHandle();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
((CraftPlayer) player).getHandle().netServerHandler.sendPacket(new Packet29DestroyEntity(mcEntity.id));
|
||||
@ -106,11 +113,11 @@ public class CitizensNPCManager implements NPCManager {
|
||||
getWorldServer(loc.getWorld()).removeEntity(mcEntity);
|
||||
npc.getTrait(SpawnLocation.class).setLocation(loc);
|
||||
|
||||
spawned.remove(mcEntity.getPlayer());
|
||||
spawned.remove(mcEntity.getPlayer().getEntityId());
|
||||
}
|
||||
|
||||
public void remove(NPC npc) {
|
||||
if (spawned.containsKey(((CitizensNPC) npc).getHandle()))
|
||||
if (spawned.contains(npc.getBukkitEntity().getEntityId()))
|
||||
despawn(npc);
|
||||
byID.remove(npc.getId());
|
||||
}
|
||||
@ -122,4 +129,8 @@ public class CitizensNPCManager implements NPCManager {
|
||||
private MinecraftServer getMinecraftServer(Server server) {
|
||||
return ((CraftServer) server).getServer();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return byID.size();
|
||||
}
|
||||
}
|
@ -1,47 +1,28 @@
|
||||
package net.citizensnpcs.npc.trait;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.citizensnpcs.api.Factory;
|
||||
import net.citizensnpcs.api.npc.trait.Trait;
|
||||
import net.citizensnpcs.api.npc.trait.TraitManager;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
public class CitizensTraitManager implements TraitManager {
|
||||
private final Map<String, Class<? extends Trait>> registered = new HashMap<String, Class<? extends Trait>>();
|
||||
private final Set<Trait> traits = new HashSet<Trait>();
|
||||
private final Map<String, Factory<? extends Trait>> registered = Maps.newHashMap();
|
||||
|
||||
@Override
|
||||
public Trait getTrait(String name) {
|
||||
if (registered.get(name) == null) {
|
||||
return null;
|
||||
}
|
||||
for (Trait trait : traits) {
|
||||
if (trait.getName().equals(name)) {
|
||||
return trait;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return registered.get(name).create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTrait(Class<? extends Trait> trait) {
|
||||
if (registered.containsValue(trait)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Trait register = trait.newInstance();
|
||||
registered.put(register.getName(), trait);
|
||||
traits.add(register);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Trait> getRegisteredTraits() {
|
||||
return traits;
|
||||
public void registerTraitFactory(String name, Factory<? extends Trait> factory) {
|
||||
if (registered.get(name) != null)
|
||||
throw new IllegalArgumentException("trait factory already registered");
|
||||
registered.put(name, factory);
|
||||
}
|
||||
}
|
139
src/net/citizensnpcs/util/ByIdArray.java
Normal file
139
src/net/citizensnpcs/util/ByIdArray.java
Normal file
@ -0,0 +1,139 @@
|
||||
package net.citizensnpcs.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class ByIdArray<T> implements Iterable<T> {
|
||||
private Object[] elementData;
|
||||
private int size;
|
||||
private int modCount;
|
||||
private int highest;
|
||||
|
||||
public ByIdArray() {
|
||||
this(50);
|
||||
}
|
||||
|
||||
public ByIdArray(int capacity) {
|
||||
if (capacity < 0)
|
||||
throw new IllegalArgumentException("illegal capacity");
|
||||
elementData = new Object[capacity];
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
modCount = highest = size = 0;
|
||||
elementData = new Object[50];
|
||||
}
|
||||
|
||||
private void ensureCapacity(int minCapacity) { // from ArrayList
|
||||
int oldCapacity = elementData.length;
|
||||
if (minCapacity > oldCapacity) {
|
||||
int newCapacity = (oldCapacity * 3) / 2 + 1;
|
||||
if (newCapacity < minCapacity)
|
||||
newCapacity = minCapacity;
|
||||
elementData = Arrays.copyOf(elementData, newCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
private void fastRemove(int index) {
|
||||
if (index == highest)
|
||||
recalcHighest();
|
||||
elementData[index] = null;
|
||||
--size;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T get(int index) {
|
||||
if (index > elementData.length)
|
||||
return null;
|
||||
return (T) elementData[index];
|
||||
}
|
||||
|
||||
/*@SuppressWarnings("unchecked")
|
||||
public T[] toArray(T[] a) {
|
||||
if (a.length < size)
|
||||
// Make a new array of a's runtime type, but my contents:
|
||||
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
|
||||
System.arraycopy(elementData, 0, a, 0, size);
|
||||
if (a.length > size)
|
||||
a[size] = null;
|
||||
return a;
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
private int idx = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return highest + 1 > idx && size > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public T next() {
|
||||
T next = (T) elementData[idx];
|
||||
if (next == null || idx > highest)
|
||||
throw new NoSuchElementException();
|
||||
do {
|
||||
idx++;
|
||||
} while (idx != highest + 1 && elementData[idx] == null);
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
ByIdArray.this.fastRemove(idx);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void put(int index, T t) {
|
||||
if (t == null)
|
||||
throw new IllegalArgumentException("t cannot be null");
|
||||
++modCount;
|
||||
if (index > highest)
|
||||
highest = index;
|
||||
|
||||
ensureCapacity(index + 1);
|
||||
|
||||
elementData[index] = t;
|
||||
++size;
|
||||
}
|
||||
|
||||
private void recalcHighest() {
|
||||
while (highest != 0 && elementData[highest--] == null)
|
||||
;
|
||||
}
|
||||
|
||||
public T remove(int index) {
|
||||
++modCount;
|
||||
if (index == highest)
|
||||
recalcHighest();
|
||||
@SuppressWarnings("unchecked")
|
||||
T prev = (T) elementData[index];
|
||||
elementData[index] = null;
|
||||
if (prev != null)
|
||||
--size;
|
||||
return prev;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void trimToSize() {
|
||||
if (elementData.length > highest)
|
||||
elementData = Arrays.copyOf(elementData, highest + 1);
|
||||
}
|
||||
|
||||
public static <T> ByIdArray<T> create() {
|
||||
return new ByIdArray<T>();
|
||||
}
|
||||
|
||||
public boolean contains(int index) {
|
||||
return elementData.length > index && elementData[index] != null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user