Changed custom entity selectors from event based to factory based. (#3579)
This commit is contained in:
parent
6ffd94a08e
commit
34463690c5
7 changed files with 191 additions and 11 deletions
|
@ -4,7 +4,7 @@
|
|||
list2.addAll(func_184951_f(map));
|
||||
list2.addAll(func_180698_a(map, vec3d));
|
||||
list2.addAll(func_179662_g(map));
|
||||
+ list2.addAll(net.minecraftforge.event.ForgeEventFactory.gatherEntitySelectors(map, s, p_179656_0_, vec3d));
|
||||
+ list2.addAll(net.minecraftforge.fml.common.registry.GameRegistry.createEntitySelectors(map, s, p_179656_0_, vec3d));
|
||||
list1.addAll(func_179660_a(map, p_179656_2_, list2, s, world, blockpos));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,22 +25,18 @@ import net.minecraft.command.EntitySelector;
|
|||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fml.common.IEntitySelectorFactory;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* EntitySelectorEvent is fired whenever Minecraft collects entity selectors.
|
||||
* This happens (one or multiple times) when you use something like @a[gamemode=1] in a command.<br>
|
||||
* This event is fired via {@link ForgeEventFactory#gatherEntitySelectors(Map, String, ICommandSender, Vec3d)},
|
||||
* which is executed in {@link net.minecraft.command.EntitySelector#matchEntities(ICommandSender, String, Class)}<br>
|
||||
* <br>
|
||||
* This event is not cancelable and does not have a result.<br>
|
||||
* <br>
|
||||
* This event is fired on the {@link MinecraftForge#EVENT_BUS}
|
||||
* Is not fired anymore.
|
||||
* Replaced by a factory, which has to be registered with {@link net.minecraftforge.fml.common.registry.GameRegistry#registerEntitySelector(IEntitySelectorFactory, String...)}
|
||||
* TODO remove in 1.12
|
||||
*/
|
||||
@Deprecated
|
||||
public class EntitySelectorEvent extends Event
|
||||
{
|
||||
|
||||
|
|
|
@ -253,6 +253,10 @@ public class ForgeEventFactory
|
|||
return event.getDisplayname();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO remove in 1.12
|
||||
*/
|
||||
@Deprecated
|
||||
public static List<Predicate<Entity>> gatherEntitySelectors(Map<String, String> map, String mainSelector, ICommandSender sender, Vec3d position)
|
||||
{
|
||||
EntitySelectorEvent event=new EntitySelectorEvent(map, mainSelector, sender, position);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.common;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import net.minecraft.command.EntitySelector;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Allows mods to create custom selectors in commands.
|
||||
* Registered in {@link net.minecraftforge.fml.common.registry.GameRegistry#registerEntitySelector(IEntitySelectorFactory, String...)}
|
||||
* For an example implementation, see CustomEntitySelectorTest
|
||||
*/
|
||||
public interface IEntitySelectorFactory
|
||||
{
|
||||
/**
|
||||
* Called every time a command that contains entity selectors is executed
|
||||
*
|
||||
* @param arguments A map with all arguments and their values
|
||||
* @param mainSelector The main selector string (e.g. 'a' for all players or 'e' for all entities)
|
||||
* @param sender The sender of the command
|
||||
* @param position A position either specified in the selector arguments or by the players position. See {@link EntitySelector#getPosFromArguments(Map, Vec3d)}
|
||||
* @return A list of new predicates, can be empty ({@link Collections#emptyList()} but not null.
|
||||
*/
|
||||
@Nonnull List<Predicate<Entity>> createPredicates(Map<String, String> arguments, String mainSelector, ICommandSender sender, Vec3d position);
|
||||
}
|
|
@ -32,7 +32,11 @@ import java.util.Map;
|
|||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.command.EntitySelector;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
@ -45,6 +49,7 @@ import net.minecraft.nbt.NBTException;
|
|||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.IChunkGenerator;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
|
@ -55,6 +60,7 @@ import net.minecraftforge.fml.common.Loader;
|
|||
import net.minecraftforge.fml.common.LoaderException;
|
||||
import net.minecraftforge.fml.common.LoaderState;
|
||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||
import net.minecraftforge.fml.common.IEntitySelectorFactory;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
|
@ -76,6 +82,7 @@ public class GameRegistry
|
|||
private static Map<IWorldGenerator, Integer> worldGeneratorIndex = Maps.newHashMap();
|
||||
private static List<IFuelHandler> fuelHandlers = Lists.newArrayList();
|
||||
private static List<IWorldGenerator> sortedGeneratorList;
|
||||
private static List<IEntitySelectorFactory> entitySelectorFactories = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* Register a world generator - something that inserts new block types into the world
|
||||
|
@ -94,6 +101,49 @@ public class GameRegistry
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a entity selector factory which is used to create predicates whenever a command containing selectors is executed
|
||||
* Any non vanilla arguments that you expect has to be registered. Otherwise Minecraft will throw an CommandException on usage.
|
||||
*
|
||||
* If you want to react to a command like "/kill @e[xyz=5]", you would have to register the argument "xyz" here and check for that argument in the factory.
|
||||
* One factory can listen to any number of arguments as long as they are registered here.
|
||||
*
|
||||
* For inter mod compatibility you might want to use "modid:xyz" (e.g. "forge:min_health") as argument.
|
||||
*
|
||||
* For an example usage, see CustomEntitySelectorTest
|
||||
* @param arguments Expected string arguments in commands
|
||||
*/
|
||||
public static void registerEntitySelector(IEntitySelectorFactory factory, String... arguments)
|
||||
{
|
||||
entitySelectorFactories.add(factory);
|
||||
for (String s : arguments)
|
||||
{
|
||||
EntitySelector.addArgument(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of entity selectors using the registered factories.
|
||||
* Should probably only be called by Forge
|
||||
*/
|
||||
public static List<Predicate<Entity>> createEntitySelectors(Map<String, String> arguments, String mainSelector, ICommandSender sender, Vec3d position)
|
||||
{
|
||||
List<Predicate<Entity>> selectors = Lists.newArrayList();
|
||||
for (IEntitySelectorFactory factory : entitySelectorFactories)
|
||||
{
|
||||
try
|
||||
{
|
||||
selectors.addAll(factory.createPredicates(arguments, mainSelector, sender, position));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "Exception caught during entity selector creation with %s for argument map %s of %s for %s at %s", factory,
|
||||
arguments, mainSelector, sender, position);
|
||||
}
|
||||
}
|
||||
return selectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback hook for world gen - if your mod wishes to add extra mod related generation to the world
|
||||
* call this
|
||||
|
|
|
@ -303,4 +303,7 @@ protected net.minecraft.entity.monster.EntityWitherSkeleton func_190727_o()Lnet/
|
|||
protected net.minecraft.entity.monster.EntityStray func_190727_o()Lnet/minecraft/util/SoundEvent; # getStepSound - make AbstractSkeleton implementable
|
||||
|
||||
# EntitySkeleton
|
||||
protected net.minecraft.entity.monster.EntitySkeleton func_190727_o()Lnet/minecraft/util/SoundEvent; # getStepSound - make AbstractSkeleton implementable
|
||||
protected net.minecraft.entity.monster.EntitySkeleton func_190727_o()Lnet/minecraft/util/SoundEvent; # getStepSound - make AbstractSkeleton implementable
|
||||
|
||||
# EntitySelector
|
||||
public net.minecraft.command.EntitySelector func_190826_c(Ljava/lang/String;)Ljava/lang/String; # addArgument
|
|
@ -0,0 +1,77 @@
|
|||
package net.minecraftforge.test;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraftforge.fml.common.IEntitySelectorFactory;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* You can verify that this test is working fine by following these steps.
|
||||
* Spawn a few cows and a few sheep and then use "/kill @e[forge:min_health=!10]"
|
||||
* All entities with less than 10 health points (current, not max) should die.
|
||||
* This should include the sheep, but not the (healthy) cows.
|
||||
*
|
||||
*/
|
||||
@Mod(modid = "customentityselectortest", name = "Custom Entity Selector Test", version = "1.0", acceptableRemoteVersions = "*")
|
||||
public class CustomEntitySelectorTest
|
||||
{
|
||||
|
||||
@Mod.EventHandler
|
||||
public void init(FMLInitializationEvent event)
|
||||
{
|
||||
GameRegistry.registerEntitySelector(new EntitySelectorFactory(), "forge:min_health");
|
||||
}
|
||||
|
||||
private class EntitySelectorFactory implements IEntitySelectorFactory
|
||||
{
|
||||
|
||||
@Nonnull @Override
|
||||
public List<Predicate<Entity>> createPredicates(Map<String, String> arguments, String mainSelector, ICommandSender sender, Vec3d position)
|
||||
{
|
||||
String health = arguments.get("forge:min_health");
|
||||
|
||||
//If our selector is used in this command create a Predicate otherwise return an empty list.
|
||||
if (health != null)
|
||||
{
|
||||
final boolean invert = health.startsWith("!");
|
||||
|
||||
if (invert)
|
||||
{
|
||||
health = health.substring(1);
|
||||
}
|
||||
try
|
||||
{
|
||||
final int value = Integer.parseInt(health);
|
||||
|
||||
//Return a list of predicates. All these predicates have to apply for any entity to be selected.
|
||||
return Collections.<Predicate<Entity>>singletonList(new Predicate<Entity>()
|
||||
{
|
||||
@Override
|
||||
public boolean apply(@Nullable Entity input)
|
||||
{
|
||||
if (!(input instanceof EntityLivingBase)) return false;
|
||||
return (((EntityLivingBase) input).getHealth() >= value)!=invert;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Entity selector 'forge:min_health' has to be an integer"));
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue