Skip to content

Commit

Permalink
Added KeySet and KeyMap to API as well as reduced usage of KeyImpl as…
Browse files Browse the repository at this point in the history
… much as possible
  • Loading branch information
OmerBenGera committed Apr 2, 2022
1 parent b1c0adb commit 6f8abfb
Show file tree
Hide file tree
Showing 92 changed files with 998 additions and 681 deletions.
@@ -1,13 +1,20 @@
package com.bgsoftware.superiorskyblock.api.handlers;

import com.bgsoftware.superiorskyblock.api.key.Key;
import com.bgsoftware.superiorskyblock.api.key.KeyMap;
import com.bgsoftware.superiorskyblock.api.key.KeySet;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;

import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;

public interface KeysManager {

/**
Expand Down Expand Up @@ -60,4 +67,40 @@ public interface KeysManager {
*/
Key getKey(String key);

/**
* Get the key of a global-key and a sub-key.
*
* @param globalKey The global key
* @param subKey The sub key
*/
Key getKey(String globalKey, String subKey);

/**
* Create a new empty {@link KeySet} instance.
*/
KeySet createKeySet(Supplier<Set<String>> setCreator);

/**
* Create a new {@link KeySet} instance from the given collection.
* If the provided collection is also a {@link KeySet}, the exact same instance of that set is returned.
* Otherwise, the returned {@link KeySet} is a copy of that collection.
*
* @param collection The collection to create {@link KeySet} from.
*/
KeySet createKeySet(Supplier<Set<String>> setCreator, Collection<Key> collection);

/**
* Create a new empty {@link KeyMap <V>} instance.
*/
<V> KeyMap<V> createKeyMap(Supplier<Map<String, V>> mapCreator);

/**
* Create a new {@link KeyMap<V>} instance from the given map.
* If the provided map is also a {@link KeyMap<V>}, the exact same instance of the map is returned.
* Otherwise, the returned {@link KeyMap<V>} is a copy of that map.
*
* @param map The map to create {@link KeySet} from.
*/
<V> KeyMap<V> createKeyMap(Supplier<Map<String, V>> mapCreator, Map<Key, V> map);

}
18 changes: 10 additions & 8 deletions API/src/main/java/com/bgsoftware/superiorskyblock/api/key/Key.java
@@ -1,7 +1,6 @@
package com.bgsoftware.superiorskyblock.api.key;

import com.bgsoftware.superiorskyblock.api.SuperiorSkyblockAPI;
import com.google.common.base.Preconditions;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
Expand All @@ -20,7 +19,6 @@ public interface Key extends Comparable<Key> {
* @param entityType The entity type to check.
*/
static Key of(EntityType entityType) {
Preconditions.checkNotNull(entityType, "entityType parameter cannot be null.");
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().getKey(entityType);
}

Expand All @@ -30,7 +28,6 @@ static Key of(EntityType entityType) {
* @param entity The entity to check.
*/
static Key of(Entity entity) {
Preconditions.checkNotNull(entity, "entity parameter cannot be null.");
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().getKey(entity);
}

Expand All @@ -40,7 +37,6 @@ static Key of(Entity entity) {
* @param block The block to check.
*/
static Key of(Block block) {
Preconditions.checkNotNull(block, "block parameter cannot be null.");
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().getKey(block);
}

Expand All @@ -50,7 +46,6 @@ static Key of(Block block) {
* @param blockState The block-state to check.
*/
static Key of(BlockState blockState) {
Preconditions.checkNotNull(blockState, "blockState parameter cannot be null.");
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().getKey(blockState);
}

Expand All @@ -60,7 +55,6 @@ static Key of(BlockState blockState) {
* @param itemStack The item-stack to check.
*/
static Key of(ItemStack itemStack) {
Preconditions.checkNotNull(itemStack, "itemStack parameter cannot be null.");
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().getKey(itemStack);
}

Expand All @@ -71,17 +65,25 @@ static Key of(ItemStack itemStack) {
* @param data The data to check.
*/
static Key of(Material material, short data) {
Preconditions.checkNotNull(material, "material parameter cannot be null.");
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().getKey(material, data);
}

/**
* Get the key of a global-key and a sub-key.
*
* @param globalKey The global key
* @param subKey The sub key
*/
static Key of(String globalKey, String subKey) {
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().getKey(globalKey, subKey);
}

/**
* Get the key of a string.
*
* @param key The string to check.
*/
static Key of(String key) {
Preconditions.checkNotNull(key, "key parameter cannot be null.");
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().getKey(key);
}

Expand Down
144 changes: 144 additions & 0 deletions API/src/main/java/com/bgsoftware/superiorskyblock/api/key/KeyMap.java
@@ -0,0 +1,144 @@
package com.bgsoftware.superiorskyblock.api.key;

import com.bgsoftware.superiorskyblock.api.SuperiorSkyblockAPI;

import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
* {@link Map} implementation for handling keys.
* The difference between this map and a regular {@link Map} is that this map handles checks for
* global keys as well as individual ones.
* <p>
* For example, if this map has "STONE" as a key inside it, the {@link #get(Object)} method will return the value
* of that key when "STONE" is provided, as well as any other key with a different sub-key ("STONE:0", for example).
* <p>
* However, if this set has "STONE:0" as a key, as well as the global key inside it, the {@link #get(Object)} method
* will return the value of the exact same key and not its global key (Therefore, the value of "STONE:0" will be
* returned if "STONE:0" is provided, and the value of "STONE" will be provided if "STONE:1" is provided)
*/
public interface KeyMap<V> extends Map<Key, V> {

/**
* Create a new empty {@link KeyMap<V>} instance.
*
* @param mapCreator The map creator for the inner-map of the new {@link KeyMap}
*/
static <V> KeyMap<V> createKeyMap(Supplier<Map<String, V>> mapCreator) {
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().createKeyMap(mapCreator);
}

/**
* Create a new empty {@link KeyMap<V>} instance based on {@link HashMap}.
*/
static <V> KeyMap<V> createKeyMap() {
return createKeyMap(() -> new HashMap<>());
}

/**
* Create a new {@link KeyMap<V>} instance from the given map based on {@link HashMap}.
* If the provided map is also a {@link KeyMap<V>}, the exact same instance of that map is returned.
* Otherwise, the returned {@link KeyMap<V>} is a copy of that map.
*
* @param map The map to create {@link KeySet} from.
*/
static <V> KeyMap<V> createKeyMap(Map<Key, V> map) {
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().createKeyMap(() -> new HashMap<>(), map);
}

/**
* Create a new empty {@link KeyMap<V>} instance based on {@link ConcurrentHashMap}.
*/
static <V> KeyMap<V> createConcurrentKeyMap() {
return createKeyMap(() -> new ConcurrentHashMap<>());
}

/**
* Create a new {@link KeyMap<V>} instance from the given map based on {@link ConcurrentHashMap}.
* If the provided map is also a {@link KeyMap<V>}, the exact same instance of that map is returned.
* Otherwise, the returned {@link KeyMap<V>} is a copy of that map.
*
* @param map The map to create {@link KeySet} from.
*/
static <V> KeyMap<V> createConcurrentKeyMap(Map<Key, V> map) {
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().createKeyMap(() -> new ConcurrentHashMap<>(), map);
}

/**
* Create a collector for {@link KeyMap} that can be used in streams.
*
* @param keyMapper The key mapper to apply.
* @param valueMapper The values mapper to apply.
* @param mapCreator The map creator for the inner-map of the new {@link KeyMap}
*/
static <K, V> Collector<K, ?, KeyMap<V>> getCollector(Function<? super K, ? extends Key> keyMapper,
Function<? super K, ? extends V> valueMapper,
Supplier<Map<String, V>> mapCreator) {
return Collectors.toMap(keyMapper, valueMapper, (v1, v2) -> {
throw new IllegalStateException(String.format("Duplicate key %s", v1));
}, () -> createKeyMap(mapCreator));
}

/**
* Create a collector for {@link KeyMap} based on {@link HashMap} that can be used in streams
*
* @param keyMapper The key mapper to apply.
* @param valueMapper The values mapper to apply.
*/
static <K, V> Collector<K, ?, KeyMap<V>> getCollector(Function<? super K, ? extends Key> keyMapper,
Function<? super K, ? extends V> valueMapper) {
return Collectors.toMap(keyMapper, valueMapper, (v1, v2) -> {
throw new IllegalStateException(String.format("Duplicate key %s", v1));
}, KeyMap::createKeyMap);
}

/**
* Get the key that is similar to the provided key.
* For example, if {@param original} is "STONE:0", and the map contains only "STONE", "STONE" will be returned.
* However, if the map contains "STONE" as well as "STONE:0", "STONE:0" will be returned.
* If the key is not inside the map, null will be returned.
*
* @param original The original key.
*/
@Nullable
Key getKey(Key original);

/**
* Get the key that is similar to the provided key.
* For example, if {@param original} is "STONE:0", and the map contains only "STONE", "STONE" will be returned.
* However, if the map contains "STONE" as well as "STONE:0", "STONE:0" will be returned.
* If the key is not inside the map, {@param def} will be returned.
*
* @param original The original key.
* @param def Default key to be returned if {@param original} is not in the map.
*/
Key getKey(Key original, @Nullable Key def);

/**
* Get a value from the key without checking for global keys or other similar keys.
* This means that if the map doesn't contain {@param key}, {@param def} will be returned.
* This is a similar behavior to a regular {@link Map}
*
* @param key The key to check
* @param def The default value to return.
*/
V getRaw(Key key, V def);

/**
* See {@link java.util.Collection#removeIf(Predicate)}
*/
boolean removeIf(Predicate<Key> predicate);

/**
* Return a regular {@link java.util.HashMap} with the keys and values of this map.
*/
Map<Key, V> asMap();

}
@@ -0,0 +1,79 @@
package com.bgsoftware.superiorskyblock.api.key;

import com.bgsoftware.superiorskyblock.api.SuperiorSkyblockAPI;

import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;

/**
* {@link Set} implementation for handling keys.
* The difference between this set and a regular {@link Set} is that this set handles checks for
* global keys as well as individual ones.
* <p>
* For example, if this set has "STONE" as a key inside it, the {@link #contains(Object)} method will return true
* if "STONE" is provided, as well as any other key with a different sub-key ("STONE:0", for example).
* <p>
* However, if this set only has "STONE:0" as a key inside it, the {@link #contains(Object)} method will only return
* true for the exact same keys (Therefore, "STONE" will return false alongside of any other key with a different
* sub-key)
*/
public interface KeySet extends Set<Key> {

/**
* Create a new empty {@link KeySet} instance.
*
* @param setCreator The set creator for the inner-set of the new {@link KeySet}
*/
static KeySet createKeySet(Supplier<Set<String>> setCreator) {
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().createKeySet(setCreator);
}

/**
* Create a new empty {@link KeySet} instance based on {@link HashSet}
*/
static KeySet createKeySet() {
return createKeySet(HashSet::new);
}

/**
* Create a new {@link KeySet} instance from the given collection based on {@link HashSet}.
* If the provided collection is also a {@link KeySet}, the exact same instance of that set is returned.
* Otherwise, the returned {@link KeySet} is a copy of that collection.
*
* @param collection The collection to create {@link KeySet} from.
*/
static KeySet createKeySet(Collection<Key> collection) {
return SuperiorSkyblockAPI.getSuperiorSkyblock().getKeys().createKeySet(HashSet::new, collection);
}

/**
* Get the key that is similar to the provided key.
* For example, if {@param original} is "STONE:0", and the set contains only "STONE", "STONE" will be returned.
* However, if the set contains "STONE" as well as "STONE:0", "STONE:0" will be returned.
* If the key is not inside the map, null will be returned.
*
* @param original The original key.
*/
@Nullable
Key getKey(Key original);

/**
* Get the key that is similar to the provided key.
* For example, if {@param original} is "STONE:0", and the set contains only "STONE", "STONE" will be returned.
* However, if the set contains "STONE" as well as "STONE:0", "STONE:0" will be returned.
* If the key is not inside the map, {@param def} will be returned.
*
* @param original The original key.
* @param def Default key to be returned if {@param original} is not in the map.
*/
Key getKey(Key original, Key def);

/**
* Return a regular {@link java.util.HashSet} with the keys of this set.
*/
Set<Key> asSet();

}
Expand Up @@ -3,7 +3,7 @@
import com.bgsoftware.superiorskyblock.SuperiorSkyblockPlugin;
import com.bgsoftware.superiorskyblock.api.island.Island;
import com.bgsoftware.superiorskyblock.api.objects.Pair;
import com.bgsoftware.superiorskyblock.key.Key;
import com.bgsoftware.superiorskyblock.key.KeyImpl;
import com.bgsoftware.superiorskyblock.utils.legacy.Materials;
import com.google.common.base.Preconditions;
import gcspawners.ASAPI;
Expand Down Expand Up @@ -53,14 +53,14 @@ public void onSpawnerStack(AdvancedSpawnerPlaceEvent e) {
Island island = plugin.getGrid().getIslandAt(location);

if (island != null)
island.handleBlockPlace(Key.of(Materials.SPAWNER.toBukkitType() + "", e.getEntityType().toUpperCase()), e.getCountPlaced());
island.handleBlockPlace(KeyImpl.of(Materials.SPAWNER.toBukkitType() + "", e.getEntityType().toUpperCase()), e.getCountPlaced());
}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSpawnerUnstack(AdvancedSpawnersBreakEvent e) {
Island island = plugin.getGrid().getIslandAt(e.getSpawner().getLocation());
if (island != null)
island.handleBlockBreak(Key.of(Materials.SPAWNER.toBukkitType() + "", e.getEntityType().toUpperCase()), e.getCountBroken());
island.handleBlockBreak(KeyImpl.of(Materials.SPAWNER.toBukkitType() + "", e.getEntityType().toUpperCase()), e.getCountBroken());
}

}
Expand Down

0 comments on commit 6f8abfb

Please sign in to comment.