mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-01 05:58:00 +01:00
Simplify Acquirable, support for all objects
This commit is contained in:
parent
26bd0dd43c
commit
845a8608db
@ -1,7 +1,7 @@
|
||||
package net.minestom.server;
|
||||
|
||||
import com.google.common.collect.Queues;
|
||||
import net.minestom.server.entity.acquirable.Acquisition;
|
||||
import net.minestom.server.acquirable.Acquisition;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
|
@ -1,23 +1,18 @@
|
||||
package net.minestom.server.entity.acquirable;
|
||||
package net.minestom.server.acquirable;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.thread.ThreadProvider;
|
||||
import net.minestom.server.thread.TickThread;
|
||||
import net.minestom.server.utils.consumer.EntityConsumer;
|
||||
import net.minestom.server.utils.async.AsyncUtils;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Represents an {@link Entity entity} which can be acquired.
|
||||
* Used for synchronization purpose.
|
||||
*/
|
||||
public class AcquirableEntity {
|
||||
|
||||
private static final ThreadLocal<Stream<Entity>> CURRENT_ENTITIES = ThreadLocal.withInitial(Stream::empty);
|
||||
public interface Acquirable<T> {
|
||||
|
||||
/**
|
||||
* Gets all the {@link Entity entities} being ticked in the current thread.
|
||||
@ -26,12 +21,12 @@ public class AcquirableEntity {
|
||||
*
|
||||
* @return the entities ticked in the current thread
|
||||
*/
|
||||
public static @NotNull Stream<@NotNull Entity> current() {
|
||||
return CURRENT_ENTITIES.get();
|
||||
static @NotNull Stream<@NotNull Entity> currentEntities() {
|
||||
return AcquirableImpl.CURRENT_ENTITIES.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the stream returned by {@link #current()}.
|
||||
* Changes the stream returned by {@link #currentEntities()}.
|
||||
* <p>
|
||||
* Mostly for internal use, external calls are unrecommended as they could lead
|
||||
* to unexpected behavior.
|
||||
@ -39,21 +34,32 @@ public class AcquirableEntity {
|
||||
* @param entities the new entity stream
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public static void refresh(@NotNull Stream<@NotNull Entity> entities) {
|
||||
CURRENT_ENTITIES.set(entities);
|
||||
static void refreshEntities(@NotNull Stream<@NotNull Entity> entities) {
|
||||
AcquirableImpl.CURRENT_ENTITIES.set(entities);
|
||||
}
|
||||
|
||||
private final Entity entity;
|
||||
private final Handler handler;
|
||||
|
||||
public AcquirableEntity(@NotNull Entity entity) {
|
||||
this.entity = entity;
|
||||
this.handler = new Handler();
|
||||
static <T> @NotNull Acquirable<T> of(@NotNull T value) {
|
||||
return new AcquirableImpl<>(value);
|
||||
}
|
||||
|
||||
public @NotNull Acquired<? extends Entity> acquire() {
|
||||
final TickThread elementThread = getHandler().getTickThread();
|
||||
return new Acquired<>(unwrap(), elementThread);
|
||||
default void sync(@NotNull Consumer<T> consumer) {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
final TickThread tickThread = getHandler().getTickThread();
|
||||
Acquisition.acquire(currentThread, tickThread, () -> consumer.accept(unwrap()));
|
||||
}
|
||||
|
||||
default void async(@NotNull Consumer<T> consumer) {
|
||||
// TODO per-thread list
|
||||
AsyncUtils.runAsync(() -> sync(consumer));
|
||||
}
|
||||
|
||||
default @NotNull Optional<T> optional() {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
final TickThread tickThread = getHandler().getTickThread();
|
||||
if (Objects.equals(currentThread, tickThread)) {
|
||||
return Optional.of(unwrap());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,9 +69,7 @@ public class AcquirableEntity {
|
||||
*
|
||||
* @return the unwrapped value
|
||||
*/
|
||||
public @NotNull Entity unwrap() {
|
||||
return entity;
|
||||
}
|
||||
@NotNull T unwrap();
|
||||
|
||||
/**
|
||||
* Gets the {@link Handler} of this acquirable element,
|
||||
@ -76,11 +80,9 @@ public class AcquirableEntity {
|
||||
* @return this element handler
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public @NotNull Handler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
@NotNull Handler getHandler();
|
||||
|
||||
public static class Handler {
|
||||
class Handler {
|
||||
|
||||
private volatile ThreadProvider.ChunkEntry chunkEntry;
|
||||
|
@ -0,0 +1,19 @@
|
||||
package net.minestom.server.acquirable;
|
||||
|
||||
import net.minestom.server.utils.collection.CollectionView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class AcquirableCollection<E> extends CollectionView<E, Acquirable<E>> {
|
||||
|
||||
private final Collection<Acquirable<E>> acquirableEntityCollection;
|
||||
|
||||
public AcquirableCollection(@NotNull Collection<Acquirable<E>> acquirableEntityCollection) {
|
||||
super(acquirableEntityCollection,
|
||||
null,
|
||||
//Entity::getAcquirable,
|
||||
acquirableEntity -> (E) acquirableEntity.unwrap());
|
||||
this.acquirableEntityCollection = acquirableEntityCollection;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package net.minestom.server.acquirable;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class AcquirableImpl<T> implements Acquirable<T> {
|
||||
|
||||
protected static final ThreadLocal<Stream<Entity>> CURRENT_ENTITIES = ThreadLocal.withInitial(Stream::empty);
|
||||
|
||||
/**
|
||||
* Changes the stream returned by {@link #currentEntities()}.
|
||||
* <p>
|
||||
* Mostly for internal use, external calls are unrecommended as they could lead
|
||||
* to unexpected behavior.
|
||||
*
|
||||
* @param entities the new entity stream
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
static void refreshEntities(@NotNull Stream<@NotNull Entity> entities) {
|
||||
AcquirableImpl.CURRENT_ENTITIES.set(entities);
|
||||
}
|
||||
|
||||
private final T value;
|
||||
private final Acquirable.Handler handler;
|
||||
|
||||
public AcquirableImpl(@NotNull T value) {
|
||||
this.value = value;
|
||||
this.handler = new Acquirable.Handler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull T unwrap() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Acquirable.Handler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package net.minestom.server.entity.acquirable;
|
||||
package net.minestom.server.acquirable;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.thread.TickThread;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -27,8 +26,8 @@ public final class Acquisition {
|
||||
* @param collection the collection to acquire
|
||||
* @param consumer the consumer called for each of the collection element
|
||||
*/
|
||||
public static void acquireForEach(@NotNull Collection<AcquirableEntity> collection,
|
||||
@NotNull Consumer<Entity> consumer) {
|
||||
public static <T> void acquireForEach(@NotNull Collection<Acquirable<T>> collection,
|
||||
@NotNull Consumer<T> consumer) {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
var threadEntitiesMap = retrieveOptionalThreadMap(collection, currentThread, consumer);
|
||||
|
||||
@ -36,11 +35,11 @@ public final class Acquisition {
|
||||
{
|
||||
for (var entry : threadEntitiesMap.entrySet()) {
|
||||
final TickThread tickThread = entry.getKey();
|
||||
final List<Entity> entities = entry.getValue();
|
||||
final List<T> values = entry.getValue();
|
||||
|
||||
acquire(currentThread, tickThread, () -> {
|
||||
for (Entity entity : entities) {
|
||||
consumer.accept(entity);
|
||||
for (T value : values) {
|
||||
consumer.accept(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -107,15 +106,15 @@ public final class Acquisition {
|
||||
* @param consumer the consumer to execute when an element is already in the current thread
|
||||
* @return a new Thread to acquirable elements map
|
||||
*/
|
||||
protected static Map<TickThread, List<Entity>> retrieveOptionalThreadMap(@NotNull Collection<AcquirableEntity> collection,
|
||||
@NotNull Thread currentThread,
|
||||
@NotNull Consumer<? super Entity> consumer) {
|
||||
protected static <T> Map<TickThread, List<T>> retrieveOptionalThreadMap(@NotNull Collection<Acquirable<T>> collection,
|
||||
@NotNull Thread currentThread,
|
||||
@NotNull Consumer<T> consumer) {
|
||||
// Separate a collection of acquirable elements into a map of thread->elements
|
||||
// Useful to reduce the number of acquisition
|
||||
|
||||
Map<TickThread, List<Entity>> threadCacheMap = new HashMap<>();
|
||||
for (AcquirableEntity element : collection) {
|
||||
final Entity value = element.unwrap();
|
||||
Map<TickThread, List<T>> threadCacheMap = new HashMap<>();
|
||||
for (var element : collection) {
|
||||
final T value = element.unwrap();
|
||||
|
||||
final TickThread elementThread = element.getHandler().getTickThread();
|
||||
if (currentThread == elementThread) {
|
||||
@ -123,7 +122,7 @@ public final class Acquisition {
|
||||
consumer.accept(value);
|
||||
} else {
|
||||
// The element is manager in a different thread, cache it
|
||||
List<Entity> threadCacheList = threadCacheMap.computeIfAbsent(elementThread, tickThread -> new ArrayList<>());
|
||||
List<T> threadCacheList = threadCacheMap.computeIfAbsent(elementThread, tickThread -> new ArrayList<>());
|
||||
threadCacheList.add(value);
|
||||
}
|
||||
}
|
@ -8,12 +8,12 @@ import net.kyori.adventure.text.event.HoverEventSource;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.Tickable;
|
||||
import net.minestom.server.Viewable;
|
||||
import net.minestom.server.acquirable.Acquirable;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.collision.BoundingBox;
|
||||
import net.minestom.server.collision.CollisionUtils;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.data.DataContainer;
|
||||
import net.minestom.server.entity.acquirable.AcquirableEntity;
|
||||
import net.minestom.server.entity.metadata.EntityMeta;
|
||||
import net.minestom.server.event.Event;
|
||||
import net.minestom.server.event.EventCallback;
|
||||
@ -125,8 +125,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
|
||||
private long ticks;
|
||||
private final EntityTickEvent tickEvent = new EntityTickEvent(this);
|
||||
|
||||
// Not final in order to be modifiable in subclasses, use at your own risk
|
||||
protected AcquirableEntity acquirable = new AcquirableEntity(this);
|
||||
private final Acquirable<? extends Entity> acquirable = Acquirable.of(this);
|
||||
|
||||
/**
|
||||
* Lock used to support #switchEntityType
|
||||
@ -1574,7 +1573,7 @@ public class Entity implements Viewable, Tickable, EventHandler, DataContainer,
|
||||
return Objects.requireNonNullElse(this.customSynchronizationCooldown, SYNCHRONIZATION_COOLDOWN);
|
||||
}
|
||||
|
||||
public @NotNull AcquirableEntity getAcquirable() {
|
||||
public @NotNull Acquirable<? extends Entity> getAcquirable() {
|
||||
return acquirable;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ import net.kyori.adventure.text.event.HoverEventSource;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.title.Title;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.acquirable.Acquirable;
|
||||
import net.minestom.server.advancements.AdvancementTab;
|
||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.adventure.Localizable;
|
||||
@ -27,8 +28,6 @@ import net.minestom.server.collision.BoundingBox;
|
||||
import net.minestom.server.command.CommandManager;
|
||||
import net.minestom.server.command.CommandSender;
|
||||
import net.minestom.server.effects.Effects;
|
||||
import net.minestom.server.entity.acquirable.AcquirablePlayer;
|
||||
import net.minestom.server.entity.acquirable.Acquired;
|
||||
import net.minestom.server.entity.damage.DamageType;
|
||||
import net.minestom.server.entity.fakeplayer.FakePlayer;
|
||||
import net.minestom.server.entity.vehicle.PlayerVehicleInformation;
|
||||
@ -187,8 +186,6 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
this.username = username;
|
||||
this.playerConnection = playerConnection;
|
||||
|
||||
this.acquirable = new AcquirablePlayer(this);
|
||||
|
||||
setBoundingBox(0.6f, 1.8f, 0.6f);
|
||||
|
||||
setRespawnPoint(new Position(0, 0, 0));
|
||||
@ -331,13 +328,12 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
|
||||
//System.out.println(getAcquiredElement().getHandler().getBatchThread());
|
||||
if (username.equals("TheMode911"))
|
||||
for (Player p : MinecraftServer.getConnectionManager().getOnlinePlayers()) {
|
||||
//players.add(p1.getAcquiredElement());
|
||||
var acquired = p.getAcquirable().acquire();
|
||||
acquired.sync(player -> {
|
||||
//System.out.println("sync");
|
||||
});
|
||||
}
|
||||
for (Player p : MinecraftServer.getConnectionManager().getOnlinePlayers()) {
|
||||
//players.add(p1.getAcquiredElement());
|
||||
p.getAcquirable().sync(player -> {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
super.update(time); // Super update (item pickup/fire management)
|
||||
|
||||
@ -2462,8 +2458,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull AcquirablePlayer getAcquirable() {
|
||||
return (AcquirablePlayer) super.getAcquirable();
|
||||
public @NotNull Acquirable<? extends Player> getAcquirable() {
|
||||
return (Acquirable<? extends Player>) super.getAcquirable();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,25 +0,0 @@
|
||||
package net.minestom.server.entity.acquirable;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.utils.collection.CollectionView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class AcquirableCollection<E extends Entity> extends CollectionView<E, AcquirableEntity> {
|
||||
|
||||
private final Collection<AcquirableEntity> acquirableEntityCollection;
|
||||
|
||||
public AcquirableCollection(@NotNull Collection<AcquirableEntity> acquirableEntityCollection) {
|
||||
super(acquirableEntityCollection,
|
||||
Entity::getAcquirable,
|
||||
acquirableEntity -> (E) acquirableEntity.unwrap());
|
||||
this.acquirableEntityCollection = acquirableEntityCollection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super E> action) {
|
||||
// Acquisition.acquireForEach(acquirableEntityCollection, action);
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package net.minestom.server.entity.acquirable;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AcquirablePlayer extends AcquirableEntity {
|
||||
|
||||
public AcquirablePlayer(@NotNull Entity entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Acquired<? extends Player> acquire() {
|
||||
return (Acquired<? extends Player>) super.acquire();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Player unwrap() {
|
||||
return (Player) super.unwrap();
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package net.minestom.server.entity.acquirable;
|
||||
|
||||
import net.minestom.server.thread.TickThread;
|
||||
import net.minestom.server.utils.async.AsyncUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Acquired<T> {
|
||||
|
||||
private final T value;
|
||||
private final TickThread tickThread;
|
||||
|
||||
protected Acquired(@NotNull T value, @NotNull TickThread tickThread) {
|
||||
this.value = value;
|
||||
this.tickThread = tickThread;
|
||||
}
|
||||
|
||||
public void sync(@NotNull Consumer<T> consumer) {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
Acquisition.acquire(currentThread, tickThread, () -> consumer.accept(unwrap()));
|
||||
}
|
||||
|
||||
public void async(@NotNull Consumer<T> consumer) {
|
||||
// TODO per-thread list
|
||||
AsyncUtils.runAsync(() -> sync(consumer));
|
||||
}
|
||||
|
||||
public @NotNull Optional<T> optional() {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
if (Objects.equals(currentThread, tickThread)) {
|
||||
return Optional.of(unwrap());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public @NotNull T unwrap() {
|
||||
return value;
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package net.minestom.server.thread;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.acquirable.Acquirable;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.acquirable.AcquirableEntity;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
@ -121,13 +121,13 @@ public abstract class ThreadProvider {
|
||||
final var chunkEntries = threadChunkMap.get(thread);
|
||||
if (chunkEntries == null || chunkEntries.isEmpty()) {
|
||||
// Nothing to tick
|
||||
AcquirableEntity.refresh(Stream.empty());
|
||||
Acquirable.refreshEntities(Stream.empty());
|
||||
return;
|
||||
}
|
||||
|
||||
final var entities = chunkEntries.stream()
|
||||
.flatMap(chunkEntry -> chunkEntry.entities.stream());
|
||||
AcquirableEntity.refresh(entities);
|
||||
Acquirable.refreshEntities(entities);
|
||||
|
||||
final ReentrantLock lock = thread.getLock();
|
||||
lock.lock();
|
||||
@ -146,7 +146,7 @@ public abstract class ThreadProvider {
|
||||
entity.tick(time);
|
||||
});
|
||||
});
|
||||
AcquirableEntity.refresh(Stream.empty());
|
||||
Acquirable.refreshEntities(Stream.empty());
|
||||
lock.unlock();
|
||||
});
|
||||
}
|
||||
@ -294,7 +294,7 @@ public abstract class ThreadProvider {
|
||||
if (removedEntities.isEmpty())
|
||||
return;
|
||||
for (Entity entity : removedEntities) {
|
||||
AcquirableEntity acquirableEntity = entity.getAcquirable();
|
||||
var acquirableEntity = entity.getAcquirable();
|
||||
ChunkEntry chunkEntry = acquirableEntity.getHandler().getChunkEntry();
|
||||
// Remove from list
|
||||
if (chunkEntry != null) {
|
||||
@ -308,7 +308,7 @@ public abstract class ThreadProvider {
|
||||
if (updatableEntities.isEmpty())
|
||||
return;
|
||||
for (Entity entity : updatableEntities) {
|
||||
AcquirableEntity acquirableEntity = entity.getAcquirable();
|
||||
var acquirableEntity = entity.getAcquirable();
|
||||
ChunkEntry handlerChunkEntry = acquirableEntity.getHandler().getChunkEntry();
|
||||
|
||||
Chunk entityChunk = entity.getChunk();
|
||||
|
Loading…
Reference in New Issue
Block a user