diff --git a/.idea/workspace.xml b/.idea/workspace.xml index d67dbee..e62d9fa 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,9 +5,10 @@ - + + - + - { + "keyToString": { + "Downloaded.Files.Path.Enabled": "false", + "Gradle.Build EntityLib.executor": "Run", + "Gradle.EntityLib [dependencies].executor": "Run", + "Gradle.EntityLib [publish].executor": "Run", + "Gradle.EntityLib:code-gen [:code-gen:Main.main()].executor": "Run", + "Gradle.EntityLib:test-plugin [publish].executor": "Run", + "Gradle.EntityLib:test-plugin [runServer].executor": "Run", + "Gradle.EntityLib:test-plugin [shadowJar].executor": "Run", + "Repository.Attach.Annotations": "false", + "Repository.Attach.JavaDocs": "false", + "Repository.Attach.Sources": "false", + "RunOnceActivity.OpenProjectViewOnStart": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "WebServerToolWindowFactoryState": "false", + "git-widget-placeholder": "master", + "ignore.virus.scanning.warn.message": "true", + "jdk.selected.JAVA_MODULE": "corretto-17", + "kotlin-language-version-configured": "true", + "last_opened_file_path": "D:/Github/EntityLib/api/src/main/java/me/tofaa/entitylib/extras", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "project.structure.last.edited": "Project", + "project.structure.proportion": "0.15", + "project.structure.side.proportion": "0.2", + "settings.editor.selected.configurable": "preferences.pluginManager", + "vue.rearranger.settings.migration": "true" } -}]]> +} @@ -304,7 +305,7 @@ - + diff --git a/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java b/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java index b8f8a4e..18d8c06 100644 --- a/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java +++ b/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java @@ -35,7 +35,7 @@ public class Metadata { this.metadataMap.put(index, entry); final WrapperEntity entity = EntityLib.getApi().getEntity(entityId); - if (entity == null || entity.isSpawned()) return; // Not EntityLib entity then, the user must send the packet manually. OR not spawned. + if (entity == null || !entity.isSpawned()) return; // Not EntityLib entity then, the user must send the packet manually. OR not spawned. if (!this.notifyAboutChanges) { synchronized (this.notNotifiedChanges) { this.notNotifiedChanges.put(index, entry); diff --git a/api/src/main/java/me/tofaa/entitylib/utils/ConcurrentWeakIdentityHashMap.java b/api/src/main/java/me/tofaa/entitylib/utils/ConcurrentWeakIdentityHashMap.java new file mode 100644 index 0000000..f7dd347 --- /dev/null +++ b/api/src/main/java/me/tofaa/entitylib/utils/ConcurrentWeakIdentityHashMap.java @@ -0,0 +1,232 @@ +package me.tofaa.entitylib.utils; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.util.AbstractMap.SimpleEntry; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * @author Alex Snaps + */ +public class ConcurrentWeakIdentityHashMap implements ConcurrentMap { + + private final ConcurrentMap, V> map = new ConcurrentHashMap, V>(); + private final ReferenceQueue queue = new ReferenceQueue(); + + @Override + public V putIfAbsent(final K key, final V value) { + purgeKeys(); + return map.putIfAbsent(newKey(key), value); + } + + @Override + public boolean remove(final Object key, final Object value) { + purgeKeys(); + return map.remove(new WeakReference( key, null), value); + } + + @Override + public boolean replace(final K key, final V oldValue, final V newValue) { + purgeKeys(); + return map.replace(newKey(key), oldValue, newValue); + } + + + @Override + public V replace(final K key, final V value) { + purgeKeys(); + return map.replace(newKey(key), value); + } + + @Override + public int size() { + purgeKeys(); + return map.size(); + } + + @Override + public boolean isEmpty() { + purgeKeys(); + return map.isEmpty(); + } + + @Override + public boolean containsKey(final Object key) { + purgeKeys(); + return map.containsKey(new WeakReference(key, null)); + } + + @Override + public boolean containsValue(final Object value) { + purgeKeys(); + return map.containsValue(value); + } + + @Override + public V get(final Object key) { + purgeKeys(); + return map.get(new WeakReference(key, null)); + } + + @Override + public V put(final K key, final V value) { + purgeKeys(); + return map.put(newKey(key), value); + } + + @Override + public V remove(final Object key) { + purgeKeys(); + return map.remove(new WeakReference(key, null)); + } + + @Override + public void putAll(final Map m) { + purgeKeys(); + for (Entry entry : m.entrySet()) { + map.put(newKey(entry.getKey()), entry.getValue()); + } + } + + @Override + public void clear() { + purgeKeys(); + map.clear(); + } + + @Override + public Set keySet() { + return new AbstractSet() { + @Override + public Iterator iterator() { + purgeKeys(); + return new WeakSafeIterator>(map.keySet().iterator()) { + @Override + protected K extract(WeakReference u) { + return u.get(); + } + }; + } + + @Override + public boolean contains(Object o) { + return ConcurrentWeakIdentityHashMap.this.containsKey(o); + } + + @Override + public int size() { + return map.size(); + } + }; + } + + @Override + public Collection values() { + purgeKeys(); + return map.values(); + } + + @Override + public Set> entrySet() { + return new AbstractSet>() { + @Override + public Iterator> iterator() { + purgeKeys(); + return new WeakSafeIterator, Entry, V>>(map.entrySet().iterator()) { + @Override + protected Entry extract(Entry, V> u) { + K key = u.getKey().get(); + if (key == null) { + return null; + } else { + return new SimpleEntry(key, u.getValue()); + } + } + }; + } + + @Override + public int size() { + return map.size(); + } + }; + } + + private void purgeKeys() { + Reference reference; + while ((reference = queue.poll()) != null) { + map.remove(reference); + } + } + + private WeakReference newKey(final K key) { + return new WeakReference(key, queue); + } + + private static class WeakReference extends java.lang.ref.WeakReference { + + private final int hashCode; + + private WeakReference(final T referent, final ReferenceQueue q) { + super(referent, q); + hashCode = referent.hashCode(); + } + + @Override + public boolean equals(final Object obj) { + return obj != null && obj.getClass() == this.getClass() && (this == obj || this.get() == ((WeakReference)obj).get()); + } + + @Override + public int hashCode() { + return hashCode; + } + } + + private static abstract class WeakSafeIterator implements Iterator { + + private final Iterator weakIterator; + protected T strongNext; + + public WeakSafeIterator(Iterator weakIterator) { + this.weakIterator = weakIterator; + advance(); + } + + private void advance() { + while (weakIterator.hasNext()) { + U nextU = weakIterator.next(); + if ((strongNext = extract(nextU)) != null) { + return; + } + } + strongNext = null; + } + + @Override + public boolean hasNext() { + return strongNext != null; + } + + @Override + public final T next() { + T next = strongNext; + advance(); + return next; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + + protected abstract T extract(U u); + } +} \ No newline at end of file diff --git a/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/InternalRegistryListener.java b/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/InternalRegistryListener.java index 688b7ac..adc5213 100644 --- a/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/InternalRegistryListener.java +++ b/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/InternalRegistryListener.java @@ -97,7 +97,7 @@ final class InternalRegistryListener extends PacketListenerAbstract implements L public void onEntitySpawn(EntitySpawnEvent event) { Entity e = event.getEntity(); platform.getPlatformEntities().put(e.getEntityId(), e); + System.out.println("Entity spawned: " + e.getEntityId() + " " + e.getType() + " " + e.getLocation()); } - } diff --git a/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java b/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java index 4f20114..2dec15e 100644 --- a/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java +++ b/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java @@ -3,26 +3,20 @@ package me.tofaa.entitylib.spigot; import me.tofaa.entitylib.APIConfig; import me.tofaa.entitylib.TrackedEntity; import me.tofaa.entitylib.common.AbstractPlatform; -import org.bukkit.Bukkit; +import me.tofaa.entitylib.utils.ConcurrentWeakIdentityHashMap; import org.bukkit.entity.Entity; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntitySpawnEvent; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collections; import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.CompletableFuture; import java.util.logging.Logger; import java.util.stream.Stream; public class SpigotEntityLibPlatform extends AbstractPlatform { private SpigotEntityLibAPI api; - private Map platformEntities = Collections.synchronizedMap(new WeakHashMap<>()); // Silly + private Map platformEntities = new ConcurrentWeakIdentityHashMap<>(); public SpigotEntityLibPlatform(@NotNull JavaPlugin plugin) { super(plugin);