diff --git a/src/main/java/com/gmail/nossr50/datatypes/BlockLocationHistory.java b/src/main/java/com/gmail/nossr50/datatypes/BlockLocationHistory.java new file mode 100644 index 000000000..6674cd020 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/datatypes/BlockLocationHistory.java @@ -0,0 +1,41 @@ +package com.gmail.nossr50.datatypes; + +import com.google.common.collect.HashMultiset; +import org.bukkit.Location; + +import java.util.LinkedList; + +/** + * This class works with the assumption that you only pass in Block Locations. If locations have differing pitch/yaw, the logic breaks + */ +public class BlockLocationHistory { + private final LinkedList limitedSizeOrderedList = new LinkedList<>(); + private final HashMultiset lookup = HashMultiset.create(); + private final int maxSize; + + public BlockLocationHistory(int maxSize) { + this.maxSize = maxSize; + } + + /** + * Adds a block location to the history. If the history memory would exceed the max size, it will remove the least recently added block location + * + * @param newItem + */ + public void add(Location newItem) { + limitedSizeOrderedList.addFirst(newItem); + lookup.add(newItem); + if (limitedSizeOrderedList.size() > maxSize) + lookup.remove(limitedSizeOrderedList.removeLast()); + } + + /** + * Returns true if the block location is in the recorded history + * + * @param targetLoc the block location to search for + * @return true if the block location is in the recorded history + */ + public boolean contains(Location targetLoc) { + return lookup.contains(targetLoc); + } +} diff --git a/src/main/java/com/gmail/nossr50/datatypes/LimitedSizeList.java b/src/main/java/com/gmail/nossr50/datatypes/LimitedSizeList.java deleted file mode 100644 index c57b4996f..000000000 --- a/src/main/java/com/gmail/nossr50/datatypes/LimitedSizeList.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.gmail.nossr50.datatypes; - - -import org.bukkit.Location; - -public class LimitedSizeList { - public Location[] limitedSizeOrderedList; - private final int size; - - - public LimitedSizeList(int size) - { - this.size = size; - limitedSizeOrderedList = new Location[size]; - } - - /** - * Adds objects to our limited size ordered list - * New objects are added to the front - * @param newItem - */ - public void add(Location newItem) - { - Location[] newList = new Location[size]; - - for(int i = 0; i < size-1; i++) - { - if(i != 0) - newList[i] = limitedSizeOrderedList[i-1]; - else - newList[i] = newItem; - } - - limitedSizeOrderedList = newList; - } - - /** - * Returns true if the object is anywhere in our list - * @param targetLoc the object to check for - * @return true if the object is in our list - */ - public boolean contains(Location targetLoc) - { - for(Location iter : limitedSizeOrderedList) - { - if(iter == null) - continue; - - if(iter.getX() == targetLoc.getX() - && iter.getY() == targetLoc.getY() - && iter.getZ() == targetLoc.getZ()) - return true; - } - - return false; - } -} diff --git a/src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java b/src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java index ce8e6d93b..a4903e123 100644 --- a/src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java +++ b/src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java @@ -1,7 +1,7 @@ package com.gmail.nossr50.skills.acrobatics; import com.gmail.nossr50.config.experience.ExperienceConfig; -import com.gmail.nossr50.datatypes.LimitedSizeList; +import com.gmail.nossr50.datatypes.BlockLocationHistory; import com.gmail.nossr50.datatypes.experience.XPGainReason; import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.player.McMMOPlayer; @@ -28,13 +28,13 @@ public class AcrobaticsManager extends SkillManager { public AcrobaticsManager(McMMOPlayer mcMMOPlayer) { super(mcMMOPlayer, PrimarySkillType.ACROBATICS); - fallLocationMap = new LimitedSizeList(50); + fallLocationMap = new BlockLocationHistory(50); } private long rollXPCooldown = 0; private final long rollXPInterval = (1000 * 3); //1 Minute private long rollXPIntervalLengthen = (1000 * 10); //10 Seconds - private final LimitedSizeList fallLocationMap; + private final BlockLocationHistory fallLocationMap; public boolean hasFallenInLocationBefore(Location location) { diff --git a/src/main/java/com/gmail/nossr50/util/blockmeta/HashChunkManager.java b/src/main/java/com/gmail/nossr50/util/blockmeta/HashChunkManager.java index c1114130c..5f38022d5 100644 --- a/src/main/java/com/gmail/nossr50/util/blockmeta/HashChunkManager.java +++ b/src/main/java/com/gmail/nossr50/util/blockmeta/HashChunkManager.java @@ -38,7 +38,7 @@ public class HashChunkManager implements ChunkManager { rf.close(); regionMap.clear(); } - + private synchronized @Nullable ChunkStore readChunkStore(@NotNull World world, int cx, int cz) throws IOException { McMMOSimpleRegionFile rf = getReadableSimpleRegionFile(world, cx, cz); if (rf == null) diff --git a/src/test/java/com/gmail/nossr50/datatypes/BlockLocationHistoryTest.java b/src/test/java/com/gmail/nossr50/datatypes/BlockLocationHistoryTest.java new file mode 100644 index 000000000..5e9499a17 --- /dev/null +++ b/src/test/java/com/gmail/nossr50/datatypes/BlockLocationHistoryTest.java @@ -0,0 +1,37 @@ +package com.gmail.nossr50.datatypes; + +import org.bukkit.Location; +import org.junit.Assert; +import org.junit.Test; + +public class BlockLocationHistoryTest { + @Test + public void testRemovesOldestElement() { + BlockLocationHistory history = new BlockLocationHistory(2); + Location locationA = new Location(null, 0, 1, 2); + Location locationB = new Location(null, 1, 2, 3); + Location locationC = new Location(null, 2, 3, 4); + + history.add(locationA); + history.add(locationB); + history.add(locationC); + Assert.assertFalse(history.contains(locationA)); + Assert.assertTrue(history.contains(locationB)); + Assert.assertTrue(history.contains(locationC)); + } + + @Test + public void testSupportsDuplicateElement() { + BlockLocationHistory history = new BlockLocationHistory(2); + Location locationA = new Location(null, 0, 1, 2); + Location locationB = new Location(null, 1, 2, 3); + + history.add(locationA); + history.add(locationA); + history.add(locationB); + Assert.assertTrue(history.contains(locationA)); + Assert.assertTrue(history.contains(locationB)); + history.add(locationB); + Assert.assertFalse(history.contains(locationA)); + } +} diff --git a/src/test/java/ChunkStoreTest.java b/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java similarity index 99% rename from src/test/java/ChunkStoreTest.java rename to src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java index 2290ee103..5f1af96da 100644 --- a/src/test/java/ChunkStoreTest.java +++ b/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java @@ -1,10 +1,10 @@ -import com.gmail.nossr50.util.blockmeta.*; +package com.gmail.nossr50.util.blockmeta; + import com.google.common.io.Files; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.block.Block; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.junit.*; import org.junit.runner.RunWith; import org.mockito.Mockito;