From 6c5ebcddee50917f8594624d3a2af66c8566f682 Mon Sep 17 00:00:00 2001 From: fullwall Date: Wed, 6 Nov 2013 15:10:11 +0800 Subject: [PATCH] Fix NPC iteration in certain cases --- .../citizensnpcs/commands/NPCCommands.java | 3 +- .../java/net/citizensnpcs/util/ByIdArray.java | 46 ++++++++----- .../net/citizensnpcs/util/ByIdArrayTest.java | 66 +++++++++++++++++++ 3 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 src/test/java/net/citizensnpcs/util/ByIdArrayTest.java diff --git a/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/src/main/java/net/citizensnpcs/commands/NPCCommands.java index 96b46f95e..4e485726e 100644 --- a/src/main/java/net/citizensnpcs/commands/NPCCommands.java +++ b/src/main/java/net/citizensnpcs/commands/NPCCommands.java @@ -588,8 +588,9 @@ public class NPCCommands { List npcs = new ArrayList(); if (args.hasFlag('a')) { - for (NPC add : npcRegistry) + for (NPC add : npcRegistry) { npcs.add(add); + } } else if (args.getValueFlags().size() == 0 && sender instanceof Player) { for (NPC add : npcRegistry) { if (!npcs.contains(add) && add.getTrait(Owner.class).isOwnedBy(sender)) diff --git a/src/main/java/net/citizensnpcs/util/ByIdArray.java b/src/main/java/net/citizensnpcs/util/ByIdArray.java index e952d73fd..2f5272ab4 100644 --- a/src/main/java/net/citizensnpcs/util/ByIdArray.java +++ b/src/main/java/net/citizensnpcs/util/ByIdArray.java @@ -26,6 +26,10 @@ public class ByIdArray implements Iterable { public int add(T t) { int index = 0; + if (elementData[0] == null) { + put(index, t); + return index; + } while (elementData[index++] != null) { if (index >= elementData.length) { ensureCapacity(elementData.length + 1); @@ -81,10 +85,12 @@ public class ByIdArray implements Iterable { if (t == null) throw new IllegalArgumentException("can't insert a null object"); ++modCount; - if (index > highest) + if (index > highest) { highest = index; - if (index < lowest) + } + if (index < lowest) { lowest = index; + } ensureCapacity(index + 2); @@ -94,28 +100,34 @@ public class ByIdArray implements Iterable { private void recalcHighest() { highest = elementData.length - 1; - while (highest != 0 && elementData[highest--] == null) + while (highest != 0 && elementData[--highest] == null) { ; + } } private void recalcLowest() { lowest = 0; - while (elementData.length > lowest && elementData[lowest++] == null) + while (elementData.length > lowest && elementData[lowest++] == null) { ; + } } public T remove(int index) { - if (index > elementData.length || elementData[index] == null) + if (index > elementData.length || elementData[index] == null) { return null; + } @SuppressWarnings("unchecked") T prev = (T) elementData[index]; elementData[index] = null; --size; ++modCount; - if (index >= highest) + + if (index >= highest) { recalcHighest(); - if (index <= lowest) + } + if (index <= lowest) { recalcLowest(); + } return prev; } @@ -132,13 +144,17 @@ public class ByIdArray implements Iterable { private class Itr implements Iterator { private int expected = ByIdArray.this.modCount; private int idx; - { + + private Itr() { if (size > 0) { - if (highest == Integer.MIN_VALUE || highest >= elementData.length || elementData[highest] == null) + if (lowest > highest || highest == Integer.MIN_VALUE || highest >= elementData.length + || elementData[highest] == null) { recalcHighest(); - if (lowest >= elementData.length || elementData[lowest] == null) + } + if (lowest > highest || lowest >= elementData.length || elementData[lowest] == null) { recalcLowest(); - idx = lowest - 1; + } + idx = lowest; } } @@ -147,7 +163,7 @@ public class ByIdArray implements Iterable { if (modCount != expected) { throw new ConcurrentModificationException(); } - return size > 0 && highest > idx; + return size > 0 && highest >= idx; } @Override @@ -157,12 +173,12 @@ public class ByIdArray implements Iterable { throw new ConcurrentModificationException(); if (idx > highest) throw new NoSuchElementException(); - do - idx++; - while (idx != highest + 1 && elementData[idx] == null); T next = (T) elementData[idx]; if (next == null) throw new NoSuchElementException(); + do { + idx++; + } while (idx != highest + 1 && elementData[idx] == null); return next; } diff --git a/src/test/java/net/citizensnpcs/util/ByIdArrayTest.java b/src/test/java/net/citizensnpcs/util/ByIdArrayTest.java new file mode 100644 index 000000000..929a03f07 --- /dev/null +++ b/src/test/java/net/citizensnpcs/util/ByIdArrayTest.java @@ -0,0 +1,66 @@ +package net.citizensnpcs.util; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +import com.google.common.collect.Iterables; + +public class ByIdArrayTest { + private void assertSize(ByIdArray array, int size) { + assertThat(array.size(), is(size)); + assertThat(Iterables.size(array), is(size)); + } + + @Test + public void testBeyondCapacity() { + ByIdArray array = ByIdArray.create(); + array.put(1000, 1); + assertThat(array.contains(1000), is(true)); + assertSize(array, 1); + } + + @Test + public void testClear() { + ByIdArray array = ByIdArray.create(); + array.put(0, 1); + array.put(1, 2); + array.clear(); + assertSize(array, 0); + } + + @Test + public void testContains() { + ByIdArray array = ByIdArray.create(); + array.put(1, 1); + assertThat(array.contains(1), is(true)); + } + + @Test + public void testInsertion() { + ByIdArray array = ByIdArray.create(); + array.add(1); + array.add(2); + assertSize(array, 2); + } + + @Test + public void testPut() { + ByIdArray array = ByIdArray.create(); + array.put(50, 1); + array.put(20, 2); + assertSize(array, 2); + assertThat(array.get(20), is(2)); + assertThat(array.get(50), is(1)); + } + + @Test + public void testRemoval() { + ByIdArray array = ByIdArray.create(); + array.put(0, 1); + array.put(1, 2); + array.remove(1); + assertSize(array, 1); + } +}