Skip to content

Commit 3f79ffc

Browse files
committed
Add entity API
Instead of getting a table with a small amount of data when calling EnvironmentDetectorPeripheral.scanEntities(), UUIDs for entities are now the only thing that is returned. These can be used with the new entity API. For example, entity.getNBT(uuid) returns the NBT data of the entity with the given UUID. The entity API itself can be disabled in config, as well as the individual functions within it that could be exploitative on servers. A PlayerDetectorPeripheral.getPlayerUUID(username) function has also been added so that you can make use of the entity API when using a PlayerDetectorPeripheral.
1 parent f564efd commit 3f79ffc

15 files changed

+451
-51
lines changed

src/main/java/de/srendi/advancedperipherals/common/addons/botania/SpreaderIntegration.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public final int getMaxMana() {
3232
@LuaFunction(mainThread = true)
3333
public final Object getBounding() {
3434
if (blockEntity.getBinding() == null) return null;
35-
return LuaConverter.posToObject(blockEntity.getBinding());
35+
return LuaConverter.blockPosToLua(blockEntity.getBinding());
3636
}
3737

3838
@LuaFunction(mainThread = true)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package de.srendi.advancedperipherals.common.addons.computercraft.apis;
2+
3+
import dan200.computercraft.api.lua.*;
4+
import dan200.computercraft.shared.util.NBTUtil;
5+
import de.srendi.advancedperipherals.common.configuration.APConfig;
6+
import de.srendi.advancedperipherals.common.util.EntityUtil;
7+
import de.srendi.advancedperipherals.common.util.LuaConverter;
8+
import net.minecraft.world.entity.Entity;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
import java.util.Map;
12+
13+
public class EntityAPI implements ILuaAPI {
14+
15+
private static EntityAPI entityAPI;
16+
17+
@Override
18+
public String[] getNames() {
19+
return new String[]{"entity"};
20+
}
21+
22+
public static EntityAPI create(@NotNull IComputerSystem computer) {
23+
if (entityAPI == null && APConfig.API_CONFIG.enableEntityAPI.get())
24+
entityAPI = new EntityAPI();
25+
return entityAPI;
26+
}
27+
28+
@LuaFunction(mainThread = true)
29+
public final Object getNBT(IArguments arguments) throws LuaException {
30+
if (!APConfig.API_CONFIG.enableGetNBT.get())
31+
throw new LuaException("This function is disabled in the config. Activate it or ask an admin if they can activate it.");
32+
Entity entity = EntityUtil.getEntityFromUUIDLua(arguments.getTable(0));
33+
return NBTUtil.toLua(entity.serializeNBT());
34+
}
35+
36+
@LuaFunction(mainThread = true)
37+
public final Object getName(IArguments arguments) throws LuaException {
38+
Entity entity = EntityUtil.getEntityFromUUIDLua(arguments.getTable(0));
39+
return entity.getName().getString();
40+
}
41+
42+
@LuaFunction(mainThread = true)
43+
public final Map<String, Object> getBoundingBox(IArguments arguments) throws LuaException {
44+
if (!APConfig.API_CONFIG.enableGetBoundingBox.get())
45+
throw new LuaException("This function is disabled in the config. Activate it or ask an admin if they can activate it.");
46+
Entity entity = EntityUtil.getEntityFromUUIDLua(arguments.getTable(0));
47+
return LuaConverter.aabbToObject(entity.getBoundingBox());
48+
}
49+
50+
@LuaFunction(mainThread = true)
51+
public final Map<String, Object> getPos(IArguments arguments) throws LuaException {
52+
if (!APConfig.API_CONFIG.enableGetPos.get())
53+
throw new LuaException("This function is disabled in the config. Activate it or ask an admin if they can activate it.");
54+
Entity entity = EntityUtil.getEntityFromUUIDLua(arguments.getTable(0));
55+
return LuaConverter.vec3ToLua(entity.getPosition(1));
56+
}
57+
58+
/**
59+
* Returns entity data depending on the class of the entity. Included data is either not included in the entities
60+
* NBT data, or is especially useful so is included for convenience. Because most of this data
61+
* doesn't overlap with NBT, it ends up mainly being values that exist only at runtime.
62+
*/
63+
@LuaFunction(mainThread = true)
64+
public final Map<String, Object> getData(IArguments arguments) throws LuaException {
65+
if (!APConfig.API_CONFIG.enableGetData.get())
66+
throw new LuaException("This function is disabled in the config. Activate it or ask an admin if they can activate it.");
67+
Entity entity = EntityUtil.getEntityFromUUIDLua(arguments.getTable(0));
68+
return LuaConverter.completeEntityToLua(entity);
69+
}
70+
71+
/**
72+
* Returns persistent data added to entities by mods.
73+
*/
74+
@LuaFunction(mainThread = true)
75+
public final Object getPersistentData(IArguments arguments) throws LuaException {
76+
if (!APConfig.API_CONFIG.enableGetPersistentData.get())
77+
throw new LuaException("This function is disabled in the config. Activate it or ask an admin if they can activate it.");
78+
Entity entity = EntityUtil.getEntityFromUUIDLua(arguments.getTable(0));
79+
return NBTUtil.toLua(entity.getPersistentData());
80+
}
81+
}

src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ColonyPeripheral.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public final double getHappiness() throws LuaException {
126126
public final Object getLocation() throws LuaException {
127127
IColony colony = getColony();
128128

129-
return LuaConverter.posToObject(colony.getCenter());
129+
return LuaConverter.blockPosToLua(colony.getCenter());
130130
}
131131

132132
@LuaFunction(mainThread = true)

src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/EnvironmentDetectorPeripheral.java

+4-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import net.minecraft.world.entity.Entity;
2525
import net.minecraft.world.entity.LivingEntity;
2626
import net.minecraft.world.entity.player.Player;
27-
import net.minecraft.world.item.ItemStack;
2827
import net.minecraft.world.level.ChunkPos;
2928
import net.minecraft.world.level.Level;
3029
import net.minecraft.world.level.LightLayer;
@@ -36,7 +35,6 @@
3635
import net.minecraftforge.event.entity.player.SleepingTimeCheckEvent;
3736
import net.minecraftforge.eventbus.api.Event;
3837
import net.minecraftforge.server.ServerLifecycleHooks;
39-
4038
import org.jetbrains.annotations.NotNull;
4139

4240
import java.util.*;
@@ -210,9 +208,10 @@ public final MethodResult scanEntities(@NotNull IComputerAccess access, @NotNull
210208
}, context -> {
211209
BlockPos pos = owner.getPos();
212210
AABB box = new AABB(pos);
213-
List<Map<String, Object>> entities = new ArrayList<>();
214-
getLevel().getEntities((Entity) null, box.inflate(radius), LivingEntity.class::isInstance).forEach(entity -> entities.add(LuaConverter.completeEntityWithPositionToLua(entity, ItemStack.EMPTY, pos)));
215-
return MethodResult.of(entities);
211+
List<Map<Integer, Object>> entityUUIDs = new ArrayList<>();
212+
getLevel().getEntities((Entity) null, box.inflate(radius), LivingEntity.class::isInstance)
213+
.forEach(entity -> entityUUIDs.add(LuaConverter.uuidToLua(entity.getUUID())));
214+
return MethodResult.of(entityUUIDs);
216215
}, null);
217216
}
218217

src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/PlayerDetectorPeripheral.java

+17-2
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ public final boolean isPlayerInRange(int range, String username) {
194194

195195
@LuaFunction(mainThread = true)
196196
public final Map<String, Object> getPlayerPos(String username) throws LuaException {
197-
if (!APConfig.PERIPHERALS_CONFIG.playerSpy.get())
198-
throw new LuaException("This function is disabled in the config. Activate it or ask an admin if he can activate it.");
197+
if (!APConfig.PERIPHERALS_CONFIG.enablePlayerPosFunction.get())
198+
throw new LuaException("This function is disabled in the config. Activate it or ask an admin if they can activate it.");
199199
ResourceKey<Level> dimension = getLevel().dimension();
200200

201201
ServerPlayer existingPlayer = null;
@@ -224,6 +224,21 @@ public final Map<String, Object> getPlayerPos(String username) throws LuaExcepti
224224
return info;
225225
}
226226

227+
@LuaFunction(mainThread = true)
228+
public final Map<Integer, Object> getPlayerUUID(String username) throws LuaException {
229+
if (!APConfig.PERIPHERALS_CONFIG.enablePlayerUUIDFunction.get())
230+
throw new LuaException("This function is disabled in the config. Activate it or ask an admin if they can activate it.");
231+
ResourceKey<Level> dimension = getLevel().dimension();
232+
233+
for (Player player : getPlayers()) {
234+
if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension)
235+
continue;
236+
if(player.getName().getString().equals(username))
237+
return LuaConverter.uuidToLua(player.getUUID());
238+
}
239+
return Collections.emptyMap();
240+
}
241+
227242
private List<ServerPlayer> getPlayers() {
228243
return ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayers();
229244
}

src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityHandPlugin.java

+18-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dan200.computercraft.api.lua.LuaException;
44
import dan200.computercraft.api.lua.LuaFunction;
55
import dan200.computercraft.api.lua.MethodResult;
6+
import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner;
67
import de.srendi.advancedperipherals.common.addons.computercraft.owner.TurtlePeripheralOwner;
78
import de.srendi.advancedperipherals.common.util.LuaConverter;
89
import de.srendi.advancedperipherals.lib.peripherals.AutomataCorePeripheral;
@@ -15,6 +16,7 @@
1516
import net.minecraft.world.phys.AABB;
1617
import net.minecraft.world.phys.EntityHitResult;
1718
import net.minecraft.world.phys.HitResult;
19+
import net.minecraftforge.common.IForgeShearable;
1820
import org.jetbrains.annotations.Nullable;
1921

2022
import java.util.ArrayList;
@@ -64,7 +66,7 @@ public final MethodResult inspectAnimal() {
6466
if (!(entity instanceof Animal animal))
6567
return MethodResult.of(null, "Well, entity is not animal entity, but how?");
6668

67-
return MethodResult.of(LuaConverter.animalToLua(animal, owner.getToolInMainHand()));
69+
return MethodResult.of(completeEntityToLuaWithShearable(animal, owner));
6870
}
6971

7072
@LuaFunction(mainThread = true)
@@ -75,7 +77,21 @@ public final MethodResult searchAnimals() {
7577
AABB box = new AABB(currentPos);
7678
List<Map<String, Object>> entities = new ArrayList<>();
7779
ItemStack itemInHand = owner.getToolInMainHand();
78-
owner.getLevel().getEntities((Entity) null, box.inflate(automataCore.getInteractionRadius()), suitableEntity).forEach(entity -> entities.add(LuaConverter.completeEntityWithPositionToLua(entity, itemInHand, currentPos)));
80+
owner.getLevel().getEntities((Entity) null, box.inflate(automataCore.getInteractionRadius()), suitableEntity)
81+
.forEach(entity -> {
82+
Map<String, Object> entityTable = completeEntityToLuaWithShearable(entity, owner);
83+
entityTable.put("relativePos", LuaConverter.relativePositionToLua(entity, currentPos));
84+
entities.add(entityTable);
85+
});
7986
return MethodResult.of(entities);
8087
}
88+
89+
protected static Map<String, Object> completeEntityToLuaWithShearable(Entity entity, IPeripheralOwner owner) {
90+
Map<String, Object> entityTable = LuaConverter.completeEntityToLua(entity);
91+
ItemStack toolInHand = owner.getToolInMainHand();
92+
if (entity instanceof IForgeShearable shearable && !toolInHand.isEmpty()) {
93+
entityTable.put("shearable", shearable.isShearable(toolInHand, entity.level, entity.blockPosition()));
94+
}
95+
return entityTable;
96+
}
8197
}

src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityTransferPlugin.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import dan200.computercraft.api.lua.LuaFunction;
55
import dan200.computercraft.api.lua.MethodResult;
66
import de.srendi.advancedperipherals.common.addons.computercraft.owner.TurtlePeripheralOwner;
7-
import de.srendi.advancedperipherals.common.util.LuaConverter;
87
import de.srendi.advancedperipherals.lib.peripherals.AutomataCorePeripheral;
98
import de.srendi.advancedperipherals.lib.peripherals.IPeripheralOperation;
109
import net.minecraft.core.BlockPos;
@@ -15,8 +14,8 @@
1514
import net.minecraft.world.entity.player.Player;
1615
import net.minecraft.world.phys.EntityHitResult;
1716
import net.minecraft.world.phys.HitResult;
18-
1917
import org.jetbrains.annotations.Nullable;
18+
2019
import java.util.function.Predicate;
2120

2221
import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation.CAPTURE_ANIMAL;
@@ -112,6 +111,6 @@ public final MethodResult releaseAnimal() {
112111
@LuaFunction(mainThread = true)
113112
public final MethodResult getCapturedAnimal() {
114113
Entity extractedEntity = extractEntity();
115-
return MethodResult.of(LuaConverter.completeEntityToLua(extractedEntity, automataCore.getPeripheralOwner().getToolInMainHand()));
114+
return MethodResult.of(AutomataEntityHandPlugin.completeEntityToLuaWithShearable(extractedEntity, automataCore.getPeripheralOwner()));
116115
}
117116
}

src/main/java/de/srendi/advancedperipherals/common/addons/minecolonies/MineColonies.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ public static Object citizenToObject(ICitizenData citizen) {
6666
Map<String, Object> map = new HashMap<>();
6767
map.put("id", citizen.getId());
6868
map.put("name", citizen.getName());
69-
map.put("bedPos", LuaConverter.posToObject(citizen.getBedPos()));
69+
map.put("bedPos", LuaConverter.blockPosToLua(citizen.getBedPos()));
7070
map.put("children", citizen.getChildren());
71-
map.put("location", LuaConverter.posToObject(citizen.getLastPosition()));
71+
map.put("location", LuaConverter.blockPosToLua(citizen.getLastPosition()));
7272
map.put("state", citizen.getStatus() == null ? "Idle" : Component.translatable(citizen.getStatus().getTranslationKey()).getString());
7373
map.put("age", citizen.isChild() ? "child" : "adult");
7474
map.put("gender", citizen.isFemale() ? "female" : "male");
@@ -100,7 +100,7 @@ public static Object visitorToObject(IVisitorData visitor) {
100100
Map<String, Object> map = new HashMap<>();
101101
map.put("id", visitor.getId());
102102
map.put("name", visitor.getName());
103-
map.put("location", LuaConverter.posToObject(visitor.getSittingPosition()));
103+
map.put("location", LuaConverter.blockPosToLua(visitor.getSittingPosition()));
104104
map.put("age", visitor.isChild() ? "child" : "adult");
105105
map.put("gender", visitor.isFemale() ? "female" : "male");
106106
map.put("saturation", visitor.getSaturation());
@@ -120,7 +120,7 @@ public static Object visitorToObject(IVisitorData visitor) {
120120
*/
121121
public static Object jobToObject(IBuilding work, IJob<?> job) {
122122
Map<String, Object> map = new HashMap<>();
123-
map.put("location", LuaConverter.posToObject(work.getLocation().getInDimensionLocation()));
123+
map.put("location", LuaConverter.blockPosToLua(work.getLocation().getInDimensionLocation()));
124124
map.put("type", work.getSchematicName());
125125
map.put("level", work.getBuildingLevel());
126126
map.put("name", work.getBuildingDisplayName());
@@ -137,7 +137,7 @@ public static Object jobToObject(IBuilding work, IJob<?> job) {
137137
*/
138138
public static Object homeToObject(IBuilding home) {
139139
Map<String, Object> map = new HashMap<>();
140-
map.put("location", LuaConverter.posToObject(home.getLocation().getInDimensionLocation()));
140+
map.put("location", LuaConverter.blockPosToLua(home.getLocation().getInDimensionLocation()));
141141
map.put("type", home.getSchematicName());
142142
map.put("level", home.getBuildingLevel());
143143

@@ -172,8 +172,8 @@ public static Object skillsToObject(Map<Skill, Tuple<Integer, Double>> skills) {
172172
*/
173173
public static Object buildingToObject(IRegisteredStructureManager buildingManager, IBuilding building, BlockPos pos) {
174174
Map<String, Object> structureData = new HashMap<>();
175-
structureData.put("cornerA", LuaConverter.posToObject(building.getCorners().getA()));
176-
structureData.put("cornerB", LuaConverter.posToObject(building.getCorners().getB()));
175+
structureData.put("cornerA", LuaConverter.blockPosToLua(building.getCorners().getA()));
176+
structureData.put("cornerB", LuaConverter.blockPosToLua(building.getCorners().getB()));
177177
structureData.put("rotation", building.getRotation());
178178
structureData.put("mirror", building.isMirrored());
179179

@@ -186,7 +186,7 @@ public static Object buildingToObject(IRegisteredStructureManager buildingManage
186186
}
187187

188188
Map<String, Object> map = new HashMap<>();
189-
map.put("location", LuaConverter.posToObject(pos));
189+
map.put("location", LuaConverter.blockPosToLua(pos));
190190
map.put("type", building.getSchematicName());
191191
map.put("style", building.getStructurePack());
192192
map.put("level", building.getBuildingLevel());
@@ -232,12 +232,12 @@ public static int getAmountOfConstructionSites(IColony colony) {
232232
public static Object workOrderToObject(IWorkOrder workOrder) {
233233
Map<String, Object> map = new HashMap<>();
234234

235-
map.put("builder", LuaConverter.posToObject(workOrder.getClaimedBy()));
235+
map.put("builder", LuaConverter.blockPosToLua(workOrder.getClaimedBy()));
236236
map.put("changed", workOrder.isDirty());
237237
map.put("id", workOrder.getID());
238238
map.put("priority", workOrder.getPriority());
239239
map.put("isClaimed", workOrder.isClaimed());
240-
map.put("location", LuaConverter.posToObject(workOrder.getLocation()));
240+
map.put("location", LuaConverter.blockPosToLua(workOrder.getLocation()));
241241
map.put("type", workOrder.getClass().getSimpleName());
242242
map.put("buildingName", workOrder.getDisplayName().getString());
243243
map.put("targetLevel", workOrder.getTargetLevel());

src/main/java/de/srendi/advancedperipherals/common/configuration/APConfig.java

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class APConfig extends ModConfig {
1818
public static final PeripheralsConfig PERIPHERALS_CONFIG = new PeripheralsConfig();
1919
public static final MetaphysicsConfig METAPHYSICS_CONFIG = new MetaphysicsConfig();
2020
public static final WorldConfig WORLD_CONFIG = new WorldConfig();
21+
public static final APIConfig API_CONFIG = new APIConfig();
2122

2223
public APConfig(IAPConfig config, ModContainer container) {
2324
super(config.getType(), config.getConfigSpec(), container, "Advancedperipherals/" + config.getFileName() + ".toml");
@@ -32,6 +33,7 @@ public static void register(ModLoadingContext context) {
3233
modContainer.addConfig(new APConfig(PERIPHERALS_CONFIG, modContainer));
3334
modContainer.addConfig(new APConfig(METAPHYSICS_CONFIG, modContainer));
3435
modContainer.addConfig(new APConfig(WORLD_CONFIG, modContainer));
36+
modContainer.addConfig(new APConfig(API_CONFIG, modContainer));
3537
}
3638

3739
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package de.srendi.advancedperipherals.common.configuration;
2+
3+
import net.minecraftforge.common.ForgeConfigSpec;
4+
import net.minecraftforge.fml.config.ModConfig;
5+
6+
public class APIConfig implements IAPConfig {
7+
//Entity
8+
public final ForgeConfigSpec.BooleanValue enableEntityAPI;
9+
public final ForgeConfigSpec.BooleanValue enableGetNBT;
10+
public final ForgeConfigSpec.BooleanValue enableGetBoundingBox;
11+
public final ForgeConfigSpec.BooleanValue enableGetPos;
12+
public final ForgeConfigSpec.BooleanValue enableGetData;
13+
public final ForgeConfigSpec.BooleanValue enableGetPersistentData;
14+
private final ForgeConfigSpec configSpec;
15+
16+
public APIConfig() {
17+
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
18+
19+
builder.comment("APIs config").push("APIs");
20+
21+
builder.push("entity");
22+
23+
enableEntityAPI = builder.comment("Enables the \"entity\" API").define("enableEntityAPI", true);
24+
enableGetNBT = builder.comment("Activates the \"getNBT\" function of the entity API").define("enableGetNBT", true);
25+
enableGetBoundingBox = builder.comment("Activates the \"getBoundingBox\" function of the entity API").define("enableGetBoundingBox", true);
26+
enableGetPos = builder.comment("Activates the \"getPos\" function of the entity API").define("enableGetPos", true);
27+
enableGetData = builder.comment("Activates the \"getData\" function of the entity API").define("enableGetData", true);
28+
enableGetPersistentData = builder.comment("Activates the \"getPersistentData\" function of the entity API").define("enableGetPersistentData", true);
29+
30+
builder.pop();
31+
32+
configSpec = builder.build();
33+
}
34+
35+
@Override
36+
public ForgeConfigSpec getConfigSpec() {
37+
return configSpec;
38+
}
39+
40+
@Override
41+
public String getFileName() {
42+
return "APIs";
43+
}
44+
45+
@Override
46+
public ModConfig.Type getType() {
47+
return ModConfig.Type.COMMON;
48+
}
49+
}

0 commit comments

Comments
 (0)