add entity tracker hooks, fix crash after tweaking HandlerList

This commit is contained in:
asie 2018-12-11 17:51:23 +01:00
parent 7eb62310c5
commit f6b887b619
22 changed files with 213 additions and 37 deletions

View file

@ -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"
}

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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() {

View file

@ -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.

View file

@ -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() {

View file

@ -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() {

View file

@ -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() {

View file

@ -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);
}

View file

@ -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();
}
}
}
}

View file

@ -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();
}
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -6,6 +6,8 @@
"block.MixinBlockBuilder",
"block.entity.MixinBlockEntity",
"commands.MixinServerCommandManager",
"entity.MixinEntityTracker",
"entity.MixinEntityTrackerEntry",
"events.objectbuilder.MixinBlock",
"events.objectbuilder.MixinItem",
"events.playerinteraction.MixinServerPlayNetworkHandler",