mirror of
https://github.com/FabricMC/fabric.git
synced 2025-03-23 21:40:02 -04:00
add entity tracker hooks, fix crash after tweaking HandlerList
This commit is contained in:
parent
7eb62310c5
commit
f6b887b619
22 changed files with 213 additions and 37 deletions
build.gradle
src/main
java/net/fabricmc/fabric
block
entity
events
mixin
entity
registry
registry/impl/listeners
BootstrapBiomeRegistryListener.javaBootstrapBlockRegistryListener.javaBootstrapFluidRegistryListener.javaBootstrapItemRegistryListener.javaIdListUpdater.java
util
resources
|
@ -34,7 +34,7 @@ minecraft {
|
|||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:18w49a"
|
||||
mappings "net.fabricmc:yarn:18w49a.6"
|
||||
mappings "net.fabricmc:yarn:18w49a.11"
|
||||
modCompile "net.fabricmc:fabric-loader:0.2.0.62"
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ public class FabricBlockSettings {
|
|||
private final FabricBlockSettings.Delegate castDelegate;
|
||||
|
||||
protected FabricBlockSettings(Material material, MaterialColor color) {
|
||||
this(Block.Settings.create(material, color));
|
||||
this(Block.Settings.of(material, color));
|
||||
}
|
||||
|
||||
protected FabricBlockSettings(Block base) {
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package net.fabricmc.fabric.entity;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.network.Packet;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
// TODO: javadocs
|
||||
public class EntityTrackingRegistry {
|
||||
public static class Entry {
|
||||
private final int trackingDistance;
|
||||
private final int updateIntervalTicks;
|
||||
private final boolean alwaysUpdateVelocity;
|
||||
|
||||
public Entry(int trackingDistance, int updateIntervalTicks, boolean alwaysUpdateVelocity) {
|
||||
this.trackingDistance = trackingDistance;
|
||||
this.updateIntervalTicks = updateIntervalTicks;
|
||||
this.alwaysUpdateVelocity = alwaysUpdateVelocity;
|
||||
}
|
||||
|
||||
public int getTrackingDistance() {
|
||||
return trackingDistance;
|
||||
}
|
||||
|
||||
public int getUpdateIntervalTicks() {
|
||||
return updateIntervalTicks;
|
||||
}
|
||||
|
||||
public boolean alwaysUpdateVelocity() {
|
||||
return alwaysUpdateVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
public static final EntityTrackingRegistry INSTANCE = new EntityTrackingRegistry();
|
||||
private final Map<EntityType, Entry> entries = new HashMap<>();
|
||||
private final Map<EntityType, Function<Entity, Packet>> spawnPacketProviders = new HashMap<>();
|
||||
|
||||
private EntityTrackingRegistry() {
|
||||
|
||||
}
|
||||
|
||||
public Entry get(EntityType type) {
|
||||
return entries.get(type);
|
||||
}
|
||||
|
||||
public Packet createSpawnPacket(Entity entity) {
|
||||
Function<Entity, Packet> packetFunction = spawnPacketProviders.get(entity.getType());
|
||||
if (packetFunction != null) {
|
||||
return packetFunction.apply(entity);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void register(EntityType type, int trackingDistance, int updateIntervalTicks) {
|
||||
register(type, trackingDistance, updateIntervalTicks, true);
|
||||
}
|
||||
|
||||
public void register(EntityType type, int trackingDistance, int updateIntervalTicks, boolean alwaysUpdateVelocity) {
|
||||
entries.put(type, new Entry(trackingDistance, updateIntervalTicks, alwaysUpdateVelocity));
|
||||
}
|
||||
|
||||
public void registerSpawnPacketProvider(EntityType type, Function<Entity, Packet> packetFunction) {
|
||||
spawnPacketProviders.put(type, packetFunction);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package net.fabricmc.fabric.entity;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.EntityType.Builder;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
// TODO: javadocs
|
||||
public class FabricEntityTypeBuilder<T extends Entity> {
|
||||
protected final EntityType.Builder<T> delegate;
|
||||
private int trackingDistance = -1;
|
||||
private int updateIntervalTicks = -1;
|
||||
private boolean alwaysUpdateVelocity = true;
|
||||
|
||||
protected FabricEntityTypeBuilder(EntityType.Builder<T> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public static <T extends Entity> FabricEntityTypeBuilder<T> create(Class<? extends T> entityClass) {
|
||||
return new FabricEntityTypeBuilder<>(EntityType.Builder.create(entityClass));
|
||||
}
|
||||
|
||||
public static <T extends Entity> FabricEntityTypeBuilder<T> create(Class<? extends T> entityClass, Function<? super World, ? extends T> function) {
|
||||
return new FabricEntityTypeBuilder<>(EntityType.Builder.create(entityClass, function));
|
||||
}
|
||||
|
||||
public FabricEntityTypeBuilder<T> disableSummon() {
|
||||
delegate.disableSummon();
|
||||
return this;
|
||||
}
|
||||
|
||||
public FabricEntityTypeBuilder<T> disableSaving() {
|
||||
delegate.disableSaving();
|
||||
return this;
|
||||
}
|
||||
|
||||
public FabricEntityTypeBuilder<T> trackable(int trackingDistance, int updateIntervalTicks) {
|
||||
return trackable(trackingDistance, updateIntervalTicks, true);
|
||||
}
|
||||
|
||||
public FabricEntityTypeBuilder<T> trackable(int trackingDistance, int updateIntervalTicks, boolean alwaysUpdateVelocity) {
|
||||
this.trackingDistance = trackingDistance;
|
||||
this.updateIntervalTicks = updateIntervalTicks;
|
||||
this.alwaysUpdateVelocity = alwaysUpdateVelocity;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EntityType<T> build(String id) {
|
||||
EntityType type = delegate.build(id);
|
||||
if (trackingDistance != -1) {
|
||||
EntityTrackingRegistry.INSTANCE.register(type, trackingDistance, updateIntervalTicks, alwaysUpdateVelocity);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
|
@ -29,8 +29,8 @@ import java.util.function.BiConsumer;
|
|||
* your own methods and transparently add the resulting information to a Map.
|
||||
*/
|
||||
public final class ObjectBuilderEvent {
|
||||
public static final HandlerRegistry<BiConsumer<Block.Settings, Block>> BLOCK = new HandlerList<>();
|
||||
public static final HandlerRegistry<BiConsumer<Item.Settings, Item>> ITEM = new HandlerList<>();
|
||||
public static final HandlerRegistry<BiConsumer<Block.Settings, Block>> BLOCK = new HandlerList<>(BiConsumer.class);
|
||||
public static final HandlerRegistry<BiConsumer<Item.Settings, Item>> ITEM = new HandlerList<>(BiConsumer.class);
|
||||
|
||||
private ObjectBuilderEvent() {
|
||||
|
||||
|
|
|
@ -66,12 +66,12 @@ public final class PlayerInteractionEvent {
|
|||
/**
|
||||
* Event emitted when a player "attacks" a block.
|
||||
*/
|
||||
public static final HandlerRegistry<Block> ATTACK_BLOCK = new HandlerList<>();
|
||||
public static final HandlerRegistry<Block> ATTACK_BLOCK = new HandlerList<>(Block.class);
|
||||
|
||||
/**
|
||||
* Event emitted when a player "attacks" an entity.
|
||||
*/
|
||||
public static final HandlerRegistry<Entity> ATTACK_ENTITY = new HandlerList<>();
|
||||
public static final HandlerRegistry<Entity> ATTACK_ENTITY = new HandlerList<>(Entity.class);
|
||||
|
||||
// TODO: For completeness' sake, but requires us to add a custom packet. Is it worth the complexity?
|
||||
/* public static final HandlerRegistry<Item> ATTACK_ITEM = new HandlerList<>(); */
|
||||
|
@ -79,7 +79,7 @@ public final class PlayerInteractionEvent {
|
|||
/**
|
||||
* Event emitted when a player interacts with a block.
|
||||
*/
|
||||
public static final HandlerRegistry<BlockPositioned> INTERACT_BLOCK = new HandlerList<>();
|
||||
public static final HandlerRegistry<BlockPositioned> INTERACT_BLOCK = new HandlerList<>(BlockPositioned.class);
|
||||
|
||||
/**
|
||||
* Event emitted when a player interacts with an entity.
|
||||
|
@ -90,12 +90,12 @@ public final class PlayerInteractionEvent {
|
|||
* only one event is currently provided, but it is accordingly named in
|
||||
* the case of a second event being necessary.
|
||||
*/
|
||||
public static final HandlerRegistry<EntityPositioned> INTERACT_ENTITY_POSITIONED = new HandlerList<>();
|
||||
public static final HandlerRegistry<EntityPositioned> INTERACT_ENTITY_POSITIONED = new HandlerList<>(EntityPositioned.class);
|
||||
|
||||
/**
|
||||
* Event emitted when a player interacts with an item.
|
||||
*/
|
||||
public static final HandlerRegistry<Item> INTERACT_ITEM = new HandlerList<>();
|
||||
public static final HandlerRegistry<Item> INTERACT_ITEM = new HandlerList<>(Item.class);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #ATTACK_BLOCK ATTACK_BLOCK} instead.
|
||||
|
|
|
@ -25,7 +25,7 @@ import net.minecraft.world.World;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
public final class ServerEvent {
|
||||
public static final HandlerRegistry<Consumer<MinecraftServer>> START = new HandlerList<>();
|
||||
public static final HandlerRegistry<Consumer<MinecraftServer>> START = new HandlerList<>(Consumer.class);
|
||||
|
||||
private ServerEvent() {
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ import java.util.function.Consumer;
|
|||
* You can use them as endpoints to tick your own, related logic "globally".
|
||||
*/
|
||||
public final class TickEvent {
|
||||
public static final HandlerRegistry<Consumer<MinecraftServer>> SERVER = new HandlerList<>();
|
||||
public static final HandlerRegistry<Consumer<World>> WORLD = new HandlerList<>();
|
||||
public static final HandlerRegistry<Consumer<MinecraftServer>> SERVER = new HandlerList<>(Consumer.class);
|
||||
public static final HandlerRegistry<Consumer<World>> WORLD = new HandlerList<>(Consumer.class);
|
||||
|
||||
private TickEvent() {
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import java.util.function.Consumer;
|
|||
* @see TickEvent
|
||||
*/
|
||||
public final class ClientTickEvent {
|
||||
public static final HandlerRegistry<Consumer<MinecraftClient>> CLIENT = new HandlerList<>();
|
||||
public static final HandlerRegistry<Consumer<MinecraftClient>> CLIENT = new HandlerList<>(Consumer.class);
|
||||
|
||||
private ClientTickEvent() {
|
||||
|
||||
|
|
|
@ -26,5 +26,5 @@ public class SpriteEvent {
|
|||
void registerSprites(SpriteRegistry registry);
|
||||
}
|
||||
|
||||
public static final HandlerRegistry<Provider> PROVIDE = new HandlerList<>();
|
||||
public static final HandlerRegistry<Provider> PROVIDE = new HandlerList<>(Provider.class);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package net.fabricmc.fabric.mixin.entity;
|
||||
|
||||
import net.fabricmc.fabric.entity.EntityTrackingRegistry;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.network.EntityTracker;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(EntityTracker.class)
|
||||
public abstract class MixinEntityTracker {
|
||||
@Shadow
|
||||
public abstract void add(Entity var1, int var2, int var3, boolean var4);
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "add", cancellable = true)
|
||||
public void add(Entity entity, CallbackInfo info) {
|
||||
if (entity != null) {
|
||||
EntityTrackingRegistry.Entry entry = EntityTrackingRegistry.INSTANCE.get(entity.getType());
|
||||
if (entry != null) {
|
||||
add(entity, entry.getTrackingDistance(), entry.getUpdateIntervalTicks(), entry.alwaysUpdateVelocity());
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package net.fabricmc.fabric.mixin.entity;
|
||||
|
||||
import net.fabricmc.fabric.entity.EntityTrackingRegistry;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.server.network.EntityTrackerEntry;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(EntityTrackerEntry.class)
|
||||
public class MixinEntityTrackerEntry {
|
||||
@Shadow
|
||||
private Entity entity;
|
||||
|
||||
@Inject(at = @At(value = "CONSTANT", args = {"stringValue=Don't know how to add "}), method = "createSpawnPacket", cancellable = true)
|
||||
public void createSpawnPacket(CallbackInfoReturnable<Packet> info) {
|
||||
Packet packet = EntityTrackingRegistry.INSTANCE.createSpawnPacket(entity);
|
||||
if (packet != null) {
|
||||
info.setReturnValue(packet);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,10 +19,10 @@ package net.fabricmc.fabric.mixin.registry;
|
|||
import net.fabricmc.fabric.networking.CustomPayloadPacketRegistry;
|
||||
import net.fabricmc.fabric.registry.ListenableRegistry;
|
||||
import net.fabricmc.fabric.registry.RegistrySyncManager;
|
||||
import net.fabricmc.fabric.registry.listeners.BootstrapBiomeRegistryListener;
|
||||
import net.fabricmc.fabric.registry.listeners.BootstrapBlockRegistryListener;
|
||||
import net.fabricmc.fabric.registry.listeners.BootstrapFluidRegistryListener;
|
||||
import net.fabricmc.fabric.registry.listeners.BootstrapItemRegistryListener;
|
||||
import net.fabricmc.fabric.registry.impl.listeners.BootstrapBiomeRegistryListener;
|
||||
import net.fabricmc.fabric.registry.impl.listeners.BootstrapBlockRegistryListener;
|
||||
import net.fabricmc.fabric.registry.impl.listeners.BootstrapFluidRegistryListener;
|
||||
import net.fabricmc.fabric.registry.impl.listeners.BootstrapItemRegistryListener;
|
||||
import net.minecraft.Bootstrap;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
|
|
|
@ -17,12 +17,10 @@
|
|||
package net.fabricmc.fabric.mixin.registry.client;
|
||||
|
||||
import net.fabricmc.fabric.registry.ListenableRegistry;
|
||||
import net.fabricmc.fabric.registry.listeners.IdListUpdater;
|
||||
import net.fabricmc.fabric.registry.impl.listeners.IdListUpdater;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.render.block.BlockColorMap;
|
||||
import net.minecraft.client.render.block.BlockColorMapper;
|
||||
import net.minecraft.client.render.item.ItemColorMap;
|
||||
import net.minecraft.client.render.item.ItemColorMapper;
|
||||
import net.minecraft.util.IdList;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package net.fabricmc.fabric.mixin.registry.client;
|
||||
|
||||
import net.fabricmc.fabric.registry.ListenableRegistry;
|
||||
import net.fabricmc.fabric.registry.listeners.IdListUpdater;
|
||||
import net.fabricmc.fabric.registry.impl.listeners.IdListUpdater;
|
||||
import net.minecraft.client.render.block.BlockColorMap;
|
||||
import net.minecraft.client.render.item.ItemColorMap;
|
||||
import net.minecraft.client.render.item.ItemColorMapper;
|
||||
|
|
|
@ -14,12 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.registry.listeners;
|
||||
package net.fabricmc.fabric.registry.impl.listeners;
|
||||
|
||||
import net.fabricmc.fabric.registry.ExtendedIdList;
|
||||
import net.fabricmc.fabric.registry.RegistryListener;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.biome.Biome;
|
|
@ -14,9 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.registry.listeners;
|
||||
package net.fabricmc.fabric.registry.impl.listeners;
|
||||
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import net.fabricmc.fabric.registry.ExtendedIdList;
|
||||
import net.fabricmc.fabric.registry.RegistryListener;
|
||||
import net.minecraft.block.Block;
|
|
@ -14,12 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.registry.listeners;
|
||||
package net.fabricmc.fabric.registry.impl.listeners;
|
||||
|
||||
import net.fabricmc.fabric.registry.ExtendedIdList;
|
||||
import net.fabricmc.fabric.registry.RegistryListener;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.Identifier;
|
|
@ -14,9 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.registry.listeners;
|
||||
package net.fabricmc.fabric.registry.impl.listeners;
|
||||
|
||||
import net.fabricmc.fabric.registry.ExtendedIdList;
|
||||
import net.fabricmc.fabric.registry.RegistryListener;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.block.BlockItem;
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.registry.listeners;
|
||||
package net.fabricmc.fabric.registry.impl.listeners;
|
||||
|
||||
import net.fabricmc.fabric.registry.ExtendedIdList;
|
||||
import net.fabricmc.fabric.registry.RegistryListener;
|
|
@ -16,13 +16,16 @@
|
|||
|
||||
package net.fabricmc.fabric.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
public class HandlerList<T> implements HandlerRegistry<T> {
|
||||
private static final Object[] EMPTY = new Object[0];
|
||||
private final Class tClass;
|
||||
private T[] array;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public HandlerList() {
|
||||
this.array = (T[]) EMPTY;
|
||||
public HandlerList(Class theClass) {
|
||||
this.tClass = theClass;
|
||||
this.array = (T[]) Array.newInstance(tClass, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,7 +37,7 @@ public class HandlerList<T> implements HandlerRegistry<T> {
|
|||
}
|
||||
|
||||
//noinspection unchecked
|
||||
T[] newArray = (T[]) new Object[array.length + 1];
|
||||
T[] newArray = (T[]) Array.newInstance(tClass, array.length + 1);
|
||||
System.arraycopy(array, 0, newArray, 0, array.length);
|
||||
newArray[array.length] = handler;
|
||||
array = newArray;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
"block.MixinBlockBuilder",
|
||||
"block.entity.MixinBlockEntity",
|
||||
"commands.MixinServerCommandManager",
|
||||
"entity.MixinEntityTracker",
|
||||
"entity.MixinEntityTrackerEntry",
|
||||
"events.objectbuilder.MixinBlock",
|
||||
"events.objectbuilder.MixinItem",
|
||||
"events.playerinteraction.MixinServerPlayNetworkHandler",
|
||||
|
|
Loading…
Add table
Reference in a new issue