Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from PXAV/development
Changes for v0.3.2 - The region update
- Loading branch information
Showing
36 changed files
with
3,764 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# v0.3.2 | ||
> Release date: 19.03.2021 | ||
**The regions update**: | ||
* Add basic region library to the kelp world library. | ||
* Add supertype for regions `KelpRegion` | ||
* Add region implementation `CuboidRegion` representing a cuboid area of blocks | ||
* Add region implementation `EllipsoidRegion` representing ellipsoids including spheres and sphereoids | ||
* Add new event type `KelpRegionEvent` | ||
* Add `PlayerEnterRegionEvent` triggered when a player enters a region | ||
* Add `PlayerLeaveRegionEvent` triggered when a player leaves a region | ||
* Add new multimap type `ConcurrentMultimap` offering multimaps with thread-safety. | ||
* `ConcurrentSetMultimap` using a set in the background | ||
* `ConcurrentListMultimap` using a normal list in the background | ||
* Add a custom implementation of bukkits block face: `KelpBlockFace` | ||
* Add documentation to `KelpChunk` | ||
* Add basic NPC and region tests to `testing-module` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
222 changes: 222 additions & 0 deletions
222
core/src/main/java/de/pxav/kelp/core/common/ConcurrentListMultimap.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
package de.pxav.kelp.core.common; | ||
|
||
import com.google.common.collect.*; | ||
|
||
import javax.annotation.Nullable; | ||
import java.util.*; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.ConcurrentMap; | ||
|
||
public class ConcurrentListMultimap<K, V> implements ConcurrentMultimap<K, V> { | ||
|
||
private final ConcurrentMap<K, ArrayList<V>> map; | ||
|
||
public static <K, V> ConcurrentListMultimap<K, V> create() { | ||
return new ConcurrentListMultimap<>(); | ||
} | ||
|
||
public static <K, V> ConcurrentListMultimap<K, V> create(Multimap<K, V> source) { | ||
ConcurrentListMultimap<K, V> multimap = new ConcurrentListMultimap<>(); | ||
multimap.putAll(source); | ||
return multimap; | ||
} | ||
|
||
public static <K, V> ConcurrentListMultimap<K, V> create(Map<K, V> source) { | ||
ConcurrentListMultimap<K, V> multimap = new ConcurrentListMultimap<>(); | ||
source.forEach(multimap::put); | ||
multimap.putAll(source); | ||
return multimap; | ||
} | ||
|
||
public ConcurrentListMultimap() { | ||
this.map = new ConcurrentHashMap<>(); | ||
} | ||
|
||
@Override | ||
public int size() { | ||
int size = 0; | ||
for (Collection<V> value : this.map.values()) { | ||
size += value.size(); | ||
} | ||
return size; | ||
} | ||
|
||
@Override | ||
public boolean isEmpty() { | ||
return this.map.isEmpty(); | ||
} | ||
|
||
@Override | ||
public boolean containsKey(Object o) { | ||
return this.map.containsKey(o); | ||
} | ||
|
||
@Override | ||
public boolean containsValue(Object o) { | ||
Iterator<Collection<V>> iterator = this.asMap().values().iterator(); | ||
|
||
Collection<V> collection; | ||
|
||
do { | ||
if (!iterator.hasNext()) { | ||
return false; | ||
} | ||
|
||
collection = iterator.next(); | ||
} while(!collection.contains(o)); | ||
|
||
return true; | ||
} | ||
|
||
@Override | ||
public boolean containsEntry(Object o, Object o1) { | ||
Collection<V> collection = this.map.get(o); | ||
return collection != null && collection.contains(o1); | ||
} | ||
|
||
@Override | ||
public boolean put(K k, V v) { | ||
if (this.get(k) == null) { | ||
this.map.put(k, Lists.newArrayList()); | ||
} | ||
return this.get(k).add(v); | ||
} | ||
|
||
@Override | ||
public boolean remove(Object key, Object value) { | ||
if (this.map.get(key) == null) { | ||
return false; | ||
} | ||
return this.map.get(key).remove(value); | ||
} | ||
|
||
@Override | ||
public boolean putAll(K k, Iterable<? extends V> iterable) { | ||
if (iterable instanceof Collection) { | ||
Collection<V> collection = (Collection<V>) iterable; | ||
if (collection.isEmpty()) { | ||
return false; | ||
} | ||
|
||
if (this.get(k) == null) { | ||
this.map.put(k, Lists.newArrayList()); | ||
} | ||
return this.get(k).addAll(collection); | ||
} else { | ||
Iterator<? extends V> valueItr = iterable.iterator(); | ||
if (!valueItr.hasNext()) { | ||
return false; | ||
} | ||
|
||
if (this.get(k) == null) { | ||
this.map.put(k, Lists.newArrayList()); | ||
} | ||
return Iterators.addAll(this.get(k), valueItr); | ||
} | ||
} | ||
|
||
@Override | ||
public boolean putAll(Multimap<? extends K, ? extends V> multimap) { | ||
for (Map.Entry<? extends K, ? extends V> entry : multimap.entries()) { | ||
this.put(entry.getKey(), entry.getValue()); | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public void putAll(Map<K, V> newMap) { | ||
for (Map.Entry<K, V> entry : newMap.entrySet()) { | ||
this.put(entry.getKey(), entry.getValue()); | ||
} | ||
} | ||
|
||
@Override | ||
public Collection<V> replaceValues(K k, Iterable<? extends V> iterable) { | ||
Collection<V> result = this.removeAll(k); | ||
this.putAll(k, iterable); | ||
return result; | ||
} | ||
|
||
@Override | ||
public Collection<V> removeAll(Object key) { | ||
if (this.map.get(key) == null) { | ||
return Lists.newArrayList(); | ||
} | ||
return this.map.remove(key); | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
this.map.clear(); | ||
} | ||
|
||
@Override | ||
public Collection<V> get(@Nullable K k) { | ||
return this.map.get(k); | ||
} | ||
|
||
@Override | ||
public Set<K> keySet() { | ||
return this.map.keySet(); | ||
} | ||
|
||
@Override | ||
public Multiset<K> keys() { | ||
return HashMultiset.create(this.map.keySet()); | ||
} | ||
|
||
@Override | ||
public Collection<V> values() { | ||
Iterator<Collection<V>> iterator = this.asMap().values().iterator(); | ||
Collection<V> result = Lists.newArrayList(); | ||
|
||
while (iterator.hasNext()) { | ||
result.addAll(iterator.next()); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
@Override | ||
public Collection<Map.Entry<K, V>> entries() { | ||
Collection<Map.Entry<K, V>> entries = Lists.newArrayList(); | ||
this.map.forEach((key, valueSet) -> valueSet.forEach(element -> { | ||
AbstractMap.SimpleEntry<K, V> entry = new AbstractMap.SimpleEntry<>(key, element); | ||
entries.add(entry); | ||
})); | ||
return entries; | ||
} | ||
|
||
|
||
@Override | ||
public ConcurrentMap<K, Collection<V>> asMap() { | ||
ConcurrentMap<K, Collection<V>> output = Maps.newConcurrentMap(); | ||
output.putAll(this.map); | ||
return output; | ||
} | ||
|
||
@Override | ||
public boolean containsValue(Collection<V> iterable) { | ||
return this.map.containsValue(iterable); | ||
} | ||
|
||
@Override | ||
public Collection<V> getOrDefault(K key, Collection<V> defaultCollection) { | ||
return this.map.getOrDefault(key, Lists.newArrayList(defaultCollection)); | ||
} | ||
|
||
@Override | ||
public Collection<V> getOrEmpty(K key) { | ||
return this.map.getOrDefault(key, Lists.newArrayList()); | ||
} | ||
|
||
@Override | ||
public void removeWithValue(V value) { | ||
this.map.forEach((key, valueSet) -> valueSet.forEach(current -> { | ||
if (current.equals(value)) { | ||
this.remove(key, current); | ||
} | ||
})); | ||
} | ||
|
||
} |
67 changes: 67 additions & 0 deletions
67
core/src/main/java/de/pxav/kelp/core/common/ConcurrentMultimap.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package de.pxav.kelp.core.common; | ||
|
||
import com.google.common.collect.Multimap; | ||
|
||
import java.util.Collection; | ||
import java.util.Map; | ||
|
||
/** | ||
* This is a custom implementation of Guava's normal {@link Multimap} with the | ||
* only difference that this offers thread-safety and some performance optimizations | ||
* in some operations, while other operations are slightly slower than with a normal | ||
* {@code Multimap}. | ||
* | ||
* @param <K> The key type for each multimap entry | ||
* @param <V> The value type for each multimap entry. | ||
*/ | ||
public interface ConcurrentMultimap<K, V> extends Multimap<K, V> { | ||
|
||
/** | ||
* Checks whether a single key has all values | ||
* contained by the given collection. | ||
* | ||
* @param iterable The collection to check. | ||
* @return {@code true} of a single key had all of the values contained by the collection. | ||
*/ | ||
boolean containsValue(Collection<V> iterable); | ||
|
||
/** | ||
* Gets the collection associated with the given | ||
* key. If there is no entry for the given key, | ||
* the given fallback collection will be returned. | ||
* | ||
* @param key The key to get the collection of. | ||
* @param defaultCollection The fallback collection to return | ||
* if there is no collection associated with the given key. | ||
* @return The collection associated with the given key or the given fallback collection. | ||
*/ | ||
Collection<V> getOrDefault(K key, Collection<V> defaultCollection); | ||
|
||
/** | ||
* Gets the collection associated with the given | ||
* key. If there is no entry for the given key, | ||
* an empty collection (depending on the implementation) | ||
* will be returned. | ||
* | ||
* @param key The key to get the collection of. | ||
* @return The collection associated with the given key or an empty collection. | ||
*/ | ||
Collection<V> getOrEmpty(K key); | ||
|
||
/** | ||
* Removes all entries with the given value. | ||
* | ||
* @param value The value to remove all entries with. | ||
*/ | ||
void removeWithValue(V value); | ||
|
||
/** | ||
* Takes a normal map and inserts its values | ||
* into the multimap. If one of the contained keys | ||
* already exists, it will simply be added to the collection. | ||
* | ||
* @param newMap The map to be added to the multimap. | ||
*/ | ||
void putAll(Map<K, V> newMap); | ||
|
||
} |
Oops, something went wrong.