diff --git a/build.gradle b/build.gradle index 23996b4b..072107bd 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,7 @@ minecraft { replace '${mc_version}', project.mc_version replace '${cct_version}', project.cct_version replace '${forge_version}', project.forge_version + } jar { @@ -129,7 +130,7 @@ dependencies { // compileOnly "org.squiddev:forgelint:0.1.1" compileOnly "com.google.errorprone:error_prone_annotations:2.0.21" - testCompile 'junit:junit:4.11' + testImplementation 'junit:junit:4.11' } processResources { @@ -174,7 +175,7 @@ curseforge { changelog = "Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/plethora/releases/tag/v${project.version})." relations { - requiredLibrary 'cc-tweaked' + requiredDependency 'cc-tweaked' } } } diff --git a/gradle.properties b/gradle.properties index 043ddbd6..a1c46c21 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ # Mod properties -mod_version=1.2.3 +mod_version=1.2.4 cct_version=1.86.2 # Minecraft properties (update mods.toml when changing) mc_version=1.12.2 forge_version=14.23.5.2768 -mappings_version=20200429-1.15.1 \ No newline at end of file +mappings_version=20200429-1.15.1 diff --git a/src/main/java/org/squiddev/plethora/api/method/ICostHandler.java b/src/main/java/org/squiddev/plethora/api/method/ICostHandler.java index 95db304d..607e3c9c 100644 --- a/src/main/java/org/squiddev/plethora/api/method/ICostHandler.java +++ b/src/main/java/org/squiddev/plethora/api/method/ICostHandler.java @@ -26,6 +26,8 @@ public interface ICostHandler { */ double get(); + double getLimit(); + /** * Consume a set amount of energy * diff --git a/src/main/java/org/squiddev/plethora/api/method/wrapper/ArgumentTypes.java b/src/main/java/org/squiddev/plethora/api/method/wrapper/ArgumentTypes.java index 6acfcc65..5f253d33 100644 --- a/src/main/java/org/squiddev/plethora/api/method/wrapper/ArgumentTypes.java +++ b/src/main/java/org/squiddev/plethora/api/method/wrapper/ArgumentTypes.java @@ -2,10 +2,14 @@ import dan200.computercraft.api.lua.LuaException; import net.minecraft.item.Item; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fml.common.registry.EntityEntry; +import net.minecraftforge.fml.common.registry.ForgeRegistries; import org.squiddev.plethora.api.Injects; +import org.squiddev.plethora.utils.NBTUtilsRecursive; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -93,6 +97,14 @@ public String name() { } }; + public static final ArgumentType NBT_TAG_COMPOUND_ARG = TABLE.map(NBTUtilsRecursive::encodeNBTTagCompound); + + public static final ArgumentType ENTITY_ARG = RESOURCE.map(name -> { + EntityEntry entityEntry = ForgeRegistries.ENTITIES.getValue(name); + if (entityEntry == null || !ForgeRegistries.ENTITIES.containsKey(name)) throw new LuaException("Unknown entity '" + name + "'"); + return entityEntry; + }); + private ArgumentTypes() { } } diff --git a/src/main/java/org/squiddev/plethora/core/capabilities/DefaultCostHandler.java b/src/main/java/org/squiddev/plethora/core/capabilities/DefaultCostHandler.java index 028cdad0..f547f761 100644 --- a/src/main/java/org/squiddev/plethora/core/capabilities/DefaultCostHandler.java +++ b/src/main/java/org/squiddev/plethora/core/capabilities/DefaultCostHandler.java @@ -33,6 +33,11 @@ public synchronized double get() { return value; } + @Override + public double getLimit() { + return CostSystem.limit; + } + @Override public synchronized boolean consume(double amount) { if (amount < 0) throw new IllegalArgumentException("amount must be >= 0"); diff --git a/src/main/java/org/squiddev/plethora/core/capabilities/EmptyCostHandler.java b/src/main/java/org/squiddev/plethora/core/capabilities/EmptyCostHandler.java index 1acd0fbc..95fd32f9 100644 --- a/src/main/java/org/squiddev/plethora/core/capabilities/EmptyCostHandler.java +++ b/src/main/java/org/squiddev/plethora/core/capabilities/EmptyCostHandler.java @@ -17,12 +17,22 @@ public double get() { return 0; } + @Override + public double getLimit() { + return 0; + } + @Override public boolean consume(double amount) { if (amount < 0) throw new IllegalArgumentException("amount must be >= 0"); return amount == 0; } + @Override + public MethodResult await(double amount, MethodResult next) throws LuaException { + throw new LuaException("Insufficient energy (requires " + amount + ", has 0)."); + } + @Override public MethodResult await(double amount, Callable next) throws LuaException { throw new LuaException("Insufficient energy (requires " + amount + ", has 0)."); diff --git a/src/main/java/org/squiddev/plethora/core/wrapper/MethodClassLoader.java b/src/main/java/org/squiddev/plethora/core/wrapper/MethodClassLoader.java index e2655de0..b8db19dc 100644 --- a/src/main/java/org/squiddev/plethora/core/wrapper/MethodClassLoader.java +++ b/src/main/java/org/squiddev/plethora/core/wrapper/MethodClassLoader.java @@ -217,10 +217,10 @@ private static boolean loadLuaArg(MethodVisitor mw, int index, Parameter paramet } } else if (argument == double.class) { if (def == null) { - visitGet(mw, "Real", "D"); + visitGet(mw, "Double", "D"); } else { loadDouble(mw, def.defDoub()); - visitOpt(mw, "Real", "D"); + visitOpt(mw, "Double", "D"); } } else if (argument == float.class) { if (def == null) { diff --git a/src/main/java/org/squiddev/plethora/gameplay/ConfigGameplay.java b/src/main/java/org/squiddev/plethora/gameplay/ConfigGameplay.java index 71c6274c..fdc716f6 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/ConfigGameplay.java +++ b/src/main/java/org/squiddev/plethora/gameplay/ConfigGameplay.java @@ -195,6 +195,13 @@ public static final class Scanner { @Range(min = 0) public static int scanLevelCost; + /** + * The additional cost each level incurs for rayTrace(). + */ + @DefaultInt(5) + @Range(min = 0) + public static int rayTraceCost; + private Scanner() { } } diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/ItemModule.java b/src/main/java/org/squiddev/plethora/gameplay/modules/ItemModule.java index ed96b38a..dcda74f6 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/modules/ItemModule.java +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/ItemModule.java @@ -25,6 +25,7 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; import org.squiddev.plethora.api.Constants; import org.squiddev.plethora.api.PlethoraAPI; import org.squiddev.plethora.api.method.IContextBuilder; @@ -149,7 +150,7 @@ public ActionResult onItemRightClick(World world, EntityPlayer player } @Override - public void onPlayerStoppedUsing(ItemStack stack, World world, EntityLivingBase player, int remaining) { + public void onPlayerStoppedUsing(@Nonnull ItemStack stack, World world, @Nonnull EntityLivingBase player, int remaining) { if (world.isRemote) return; if (isBlacklisted(stack)) return; @@ -193,7 +194,7 @@ public int getMaxItemUseDuration(ItemStack stack) { @Override @SideOnly(Side.CLIENT) - public boolean hasEffect(ItemStack stack) { + public boolean hasEffect(@Nonnull ItemStack stack) { return super.hasEffect(stack) || getLevel(stack) > 0; } @@ -229,7 +230,7 @@ public void addInformation(ItemStack stack, World world, List out, ITool @Nonnull @Override - public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound tag) { + public ICapabilityProvider initCapabilities(@Nonnull ItemStack stack, NBTTagCompound tag) { return new ItemModuleHandler(stack); } @@ -299,7 +300,7 @@ public void getAdditionalContext(@Nonnull IModuleAccess access, @Nonnull IContex // Inject range information for scanners int level = getLevel(stack); builder.addContext(moduleKey, RangeInfo.of(level, - x -> x * ConfigGameplay.Scanner.scanLevelCost, + x -> (x+1) * ConfigGameplay.Scanner.scanLevelCost, x -> getEffectiveRange(x, ConfigGameplay.Scanner.radius, ConfigGameplay.Scanner.maxRadius) )); break; @@ -309,7 +310,7 @@ public void getAdditionalContext(@Nonnull IModuleAccess access, @Nonnull IContex // Inject range information for sensors int level = getLevel(stack); builder.addContext(moduleKey, RangeInfo.of(level, - x -> x * ConfigGameplay.Sensor.senseLevelCost, + x -> (x+1) * ConfigGameplay.Sensor.senseLevelCost, x -> getEffectiveRange(x, ConfigGameplay.Sensor.radius, ConfigGameplay.Sensor.maxRadius) )); break; diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/methods/MethodsCanvas2D.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/methods/MethodsCanvas2D.java index d1d9e03d..587694ec 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/methods/MethodsCanvas2D.java +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/methods/MethodsCanvas2D.java @@ -2,6 +2,7 @@ import dan200.computercraft.api.lua.LuaException; import net.minecraft.item.Item; +import net.minecraft.nbt.NBTTagCompound; import org.squiddev.plethora.api.method.IContext; import org.squiddev.plethora.api.method.MethodResult; import org.squiddev.plethora.api.method.TypedLuaObject; @@ -166,6 +167,7 @@ public static TypedLuaObject addItem( model.setScale(scale); model.setItem(item); model.setDamage(damage); + model.setNBTTagCompound(new NBTTagCompound()); canvas.add(model); return baked.makeChild(model, canvas.reference(model)).getObject(); diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/methods/MethodsCanvas3D.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/methods/MethodsCanvas3D.java index 384c281d..2edc76bd 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/methods/MethodsCanvas3D.java +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/methods/MethodsCanvas3D.java @@ -1,8 +1,10 @@ package org.squiddev.plethora.gameplay.modules.glasses.methods; +import com.mojang.authlib.GameProfile; import dan200.computercraft.api.lua.LuaException; import net.minecraft.item.Item; import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.common.registry.EntityEntry; import org.squiddev.plethora.api.IWorldLocation; import org.squiddev.plethora.api.method.ContextKeys; import org.squiddev.plethora.api.method.IContext; @@ -15,6 +17,9 @@ import org.squiddev.plethora.gameplay.modules.glasses.objects.ObjectGroup.Group3D; import org.squiddev.plethora.gameplay.modules.glasses.objects.ObjectGroup.Origin3D; import org.squiddev.plethora.gameplay.modules.glasses.objects.object3d.*; +import org.squiddev.plethora.integration.EntityIdentifier; + +import java.util.UUID; import static dan200.computercraft.api.lua.ArgumentHelper.optInt; import static org.squiddev.plethora.api.method.ArgumentHelper.getFloat; @@ -52,33 +57,19 @@ public static TypedLuaObject addFrame(IContext baked, @Fro } @PlethoraMethod(worldThread = false, - doc = "function(x:number, y:number, z:number[, width:number, height:number, depth:number][, color:number]):table -- Create a new box." + doc = "function(x: table, [, width:number, height:number, depth:number][, color:number]):table -- Create a new box." ) - public static TypedLuaObject addBox(IContext baked, @FromContext CanvasServer canvas, Object[] args) throws LuaException { - double x = getFloat(args, 0); - double y = getFloat(args, 1); - double z = getFloat(args, 2); - - int colour; - double width, height, depth; - if (args.length <= 4) { - width = 1; - height = 1; - depth = 1; - colour = optInt(args, 3, DEFAULT_COLOUR); - } else { - width = getFloat(args, 3); - height = getFloat(args, 4); - depth = getFloat(args, 5); - colour = optInt(args, 6, DEFAULT_COLOUR); - } + public static TypedLuaObject addBox(IContext baked, @FromContext CanvasServer canvas, Vec3d position, + @Optional(defDoub = 1) double width, @Optional(defDoub = 1) double height, + @Optional(defDoub = 1) double depth, @Optional(defInt = DEFAULT_COLOUR) int colour) { Group3D group = baked.getTarget(); Box box = new Box(canvas.newObjectId(), group.id()); - box.setPosition(new Vec3d(x, y, z)); + box.setPosition(position); box.setSize(width, height, depth); box.setColour(colour); + box.setRotation(Vec3d.ZERO); canvas.add(box); @@ -89,7 +80,7 @@ public static TypedLuaObject addBox(IContext baked, @FromContext C public static TypedLuaObject addLine( IContext baked, @FromContext CanvasServer canvas, Vec3d start, Vec3d end, - @Optional(defDoub = 1.0f) float thickness, @Optional(defInt = DEFAULT_COLOUR) int colour + @Optional(defDoub = 1.0f) float thickness, @Optional() int colour ) { Group3D group = baked.getTarget(); @@ -104,6 +95,58 @@ public static TypedLuaObject addLine( return baked.makeChild(line, canvas.reference(line)).getObject(); } + + + @PlethoraMethod(doc = "function(position: table, entity: string, scale: number): table-- Create a entity model.", worldThread = false) + public static TypedLuaObject addEntity(IContext baked, @FromContext CanvasServer canvas, + Vec3d position, EntityEntry entityEntry, + @Optional(defDoub = 1) float scale) { + Group3D group = baked.getTarget(); + + Entity3D model = new Entity3D(canvas.newObjectId(), group.id()); + model.setEntityEntry(entityEntry); + model.setPosition(position); + model.setScale(scale); + + canvas.add(model); + + return baked.makeChild(model, canvas.reference(model)).getObject(); + } + +// @PlethoraMethod(doc = "function(position: table, entity: string, scale: number): table-- Create a entity model.", worldThread = false) +// public static TypedLuaObject addPlayerByUUID(IContext baked, @FromContext CanvasServer canvas, +// Vec3d position, UUID uuid, +// @Optional(defDoub = 1) float scale) { +// Group3D group = baked.getTarget(); +// +// Player3D model = new Player3D(canvas.newObjectId(), group.id()); +// model.setPlayerIdentifier(new EntityIdentifier.Player(new GameProfile(uuid,null))); +// model.setPosition(position); +// model.setScale(scale); +// +// canvas.add(model); +// +// return baked.makeChild(model, canvas.reference(model)).getObject(); +// } +// +// @PlethoraMethod(doc = "function(position: table, entity: string, scale: number): table-- Create a entity model.", worldThread = false) +// public static TypedLuaObject addPlayerByName(IContext baked, @FromContext CanvasServer canvas, +// Vec3d position, String name, +// @Optional(defDoub = 1) float scale) { +// Group3D group = baked.getTarget(); +// +// Player3D model = new Player3D(canvas.newObjectId(), group.id()); +// model.setPlayerIdentifier(new EntityIdentifier.Player(new GameProfile(null, name))); +// model.setPosition(position); +// model.setScale(scale); +// +// canvas.add(model); +// +// return baked.makeChild(model, canvas.reference(model)).getObject(); +// } + + + @PlethoraMethod(doc = "-- Create a item model.", worldThread = false) public static TypedLuaObject addItem( IContext baked, @FromContext CanvasServer canvas, diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/NBTTaggable.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/NBTTaggable.java new file mode 100644 index 00000000..065133c4 --- /dev/null +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/NBTTaggable.java @@ -0,0 +1,25 @@ +package org.squiddev.plethora.gameplay.modules.glasses.objects; + +import dan200.computercraft.shared.util.NBTUtil; +import net.minecraft.nbt.NBTTagCompound; +import org.squiddev.plethora.api.method.MethodResult; +import org.squiddev.plethora.api.method.wrapper.FromTarget; +import org.squiddev.plethora.api.method.wrapper.PlethoraMethod; + +public interface NBTTaggable { + + NBTTagCompound getNBTTagCompound(); + + void setNBTTagCompound(NBTTagCompound nbt); + + @PlethoraMethod(doc = "function(): table -- Get all NBT tags for this object", worldThread = false) + static MethodResult getNBTTags(@FromTarget NBTTaggable object) { + return MethodResult.result(NBTUtil.toLua(object.getNBTTagCompound())); + } + + + @PlethoraMethod(doc = "function(nbt: table): nil -- Update a NBT Tag value for this object", worldThread = false) + static void setNBTTags(@FromTarget NBTTaggable object, NBTTagCompound nbt) { + object.setNBTTagCompound(nbt); + } +} diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/ObjectRegistry.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/ObjectRegistry.java index 5a5468b3..7efd6033 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/ObjectRegistry.java +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/ObjectRegistry.java @@ -22,8 +22,9 @@ public final class ObjectRegistry { public static final byte BOX_3D = 11; public static final byte ITEM_3D = 12; public static final byte LINE_3D = 13; + public static final byte ENTITY = 14; - private static final BaseObject.Factory[] FACTORIES = new BaseObject.Factory[]{ + private static final BaseObject.Factory[] FACTORIES = new BaseObject.Factory[]{ Rectangle::new, Line::new, Dot::new, @@ -38,7 +39,8 @@ public final class ObjectRegistry { ObjectFrame::new, Box::new, Item3D::new, - Line3D::new + Line3D::new, + Entity3D::new }; private ObjectRegistry() { diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object2d/Item2D.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object2d/Item2D.java index 411385c2..93cf0625 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object2d/Item2D.java +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object2d/Item2D.java @@ -9,6 +9,7 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -19,6 +20,7 @@ import org.squiddev.plethora.gameplay.modules.glasses.BaseObject; import org.squiddev.plethora.gameplay.modules.glasses.CanvasClient; import org.squiddev.plethora.gameplay.modules.glasses.objects.ItemObject; +import org.squiddev.plethora.gameplay.modules.glasses.objects.NBTTaggable; import org.squiddev.plethora.gameplay.modules.glasses.objects.ObjectRegistry; import org.squiddev.plethora.gameplay.modules.glasses.objects.Scalable; import org.squiddev.plethora.utils.ByteBufUtils; @@ -29,11 +31,12 @@ import static org.squiddev.plethora.gameplay.modules.glasses.CanvasHandler.HEIGHT; import static org.squiddev.plethora.gameplay.modules.glasses.CanvasHandler.WIDTH; -public class Item2D extends BaseObject implements Scalable, ItemObject, Positionable2D { +public class Item2D extends BaseObject implements NBTTaggable, Scalable, ItemObject, Positionable2D { private float scale; private Vec2d position = Vec2d.ZERO; private int damage; + private NBTTagCompound nbt; private Item item; private ItemStack stack; @@ -82,6 +85,18 @@ public void setDamage(int damage) { } } + @Override + public void setNBTTagCompound(NBTTagCompound nbt) { + if (this.nbt == null || this.nbt != nbt) { + this.nbt = nbt; + stack = null; + setDirty(); + } + } + + @Override + public NBTTagCompound getNBTTagCompound() { return nbt; } + @Override @Nonnull public Item getItem() { @@ -103,6 +118,7 @@ public void writeInitial(ByteBuf buf) { buf.writeFloat(scale); ByteBufUtils.writeUTF8String(buf, item.getRegistryName().toString()); buf.writeInt(damage); + ByteBufUtils.writeTag(buf, nbt); } @Override @@ -114,6 +130,8 @@ public void readInitial(ByteBuf buf) { item = Item.REGISTRY.getObject(name); damage = buf.readInt(); + + nbt = ByteBufUtils.readTag(buf); } @Override @@ -151,7 +169,10 @@ public void draw(CanvasClient canvas) { GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); RenderHelper.enableGUIStandardItemLighting(); - if (stack == null) stack = new ItemStack(item, 1, damage); + if (stack == null) { + stack = new ItemStack(item, 1, damage, nbt); + stack.setTagCompound(nbt); + } Minecraft.getMinecraft().getRenderItem() .renderItemAndEffectIntoGUI(Minecraft.getMinecraft().player, stack, 0, 0); diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Box.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Box.java index faa87ac4..7635f7d0 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Box.java +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Box.java @@ -2,13 +2,16 @@ import com.google.common.base.Objects; import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.math.Vec3d; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; import org.squiddev.plethora.api.method.MethodResult; import org.squiddev.plethora.api.method.wrapper.FromTarget; @@ -16,12 +19,14 @@ import org.squiddev.plethora.gameplay.modules.glasses.CanvasClient; import org.squiddev.plethora.gameplay.modules.glasses.objects.ColourableObject; import org.squiddev.plethora.gameplay.modules.glasses.objects.ObjectRegistry; +import org.squiddev.plethora.gameplay.modules.glasses.objects.Scalable; import org.squiddev.plethora.utils.ByteBufUtils; import javax.annotation.Nonnull; -public class Box extends ColourableObject implements Positionable3D, DepthTestable { +public class Box extends ColourableObject implements Rotatable3D, Positionable3D, DepthTestable { private Vec3d position; + private Vec3d rotation; private double width; private double height; private double depth; @@ -59,6 +64,18 @@ public void setPosition(@Nonnull Vec3d position) { } } + @Nullable + @Override + public Vec3d getRotation() { return rotation; } + + @Override + public void setRotation(@Nullable Vec3d rotation) { + if (this.rotation == null || !this.rotation.equals(rotation)) { + this.rotation = rotation; + setDirty(); + } + } + public void setSize(double width, double height, double depth) { if (this.width != width || this.height != height || this.depth != depth) { this.width = width; @@ -91,6 +108,8 @@ public void writeInitial(ByteBuf buf) { @Override @SideOnly(Side.CLIENT) public void draw(CanvasClient canvas) { + Minecraft mc = Minecraft.getMinecraft(); + setupFlat(); if (depthTest) { GlStateManager.enableDepth(); @@ -98,6 +117,16 @@ public void draw(CanvasClient canvas) { GlStateManager.disableDepth(); } + if (rotation == null) { + RenderManager renderManager = mc.getRenderManager(); + GlStateManager.rotate(180 - renderManager.playerViewY, 0, 1, 0); + GlStateManager.rotate(-renderManager.playerViewX, 1, 0, 0); + } else { + GlStateManager.rotate((float) rotation.x, 1, 0, 0); + GlStateManager.rotate((float) rotation.y, 0, 1, 0); + GlStateManager.rotate((float) rotation.z, 0, 0, 1); + } + double minX = position.x, minY = position.y, minZ = position.z; double maxX = minX + width, maxY = minY + height, maxZ = minZ + depth; int red = getRed(), green = getGreen(), blue = getBlue(), alpha = getAlpha(); @@ -106,6 +135,7 @@ public void draw(CanvasClient canvas) { BufferBuilder buffer = tessellator.getBuffer(); buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + //down buffer.pos(minX, minY, minZ).color(red, green, blue, alpha).endVertex(); buffer.pos(maxX, minY, minZ).color(red, green, blue, alpha).endVertex(); buffer.pos(maxX, minY, maxZ).color(red, green, blue, alpha).endVertex(); diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Entity3D.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Entity3D.java new file mode 100644 index 00000000..b9b83480 --- /dev/null +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Entity3D.java @@ -0,0 +1,163 @@ +package org.squiddev.plethora.gameplay.modules.glasses.objects.object3d; + +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.common.registry.EntityEntry; +import net.minecraftforge.fml.common.registry.ForgeRegistries; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.squiddev.plethora.gameplay.modules.glasses.BaseObject; +import org.squiddev.plethora.gameplay.modules.glasses.CanvasClient; +import org.squiddev.plethora.gameplay.modules.glasses.objects.ObjectRegistry; +import org.squiddev.plethora.gameplay.modules.glasses.objects.Scalable; +import org.squiddev.plethora.utils.ByteBufUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Objects; + +public class Entity3D extends BaseObject implements EntityObject, Scalable, Positionable3D, DepthTestable, Rotatable3D { + private float scale; + private Vec3d position = Vec3d.ZERO; + private Vec3d rotation = Vec3d.ZERO; + private boolean depthTest = true; + + + private EntityEntry entityEntry; + private Entity entity; + + + public Entity3D(int id, int parent) {super(id, parent, ObjectRegistry.ENTITY ); } + + @Override + public float getScale() { + return scale; + } + + @Override + public void setScale(float scale) { + if (this.scale != scale) { + this.scale = scale; + setDirty(); + } + } + + @Nonnull + @Override + public Vec3d getPosition() { + return position; + } + + @Override + public void setPosition(@Nonnull Vec3d position) { + if (!this.position.equals(position)) { + this.position = position; + setDirty(); + } + } + + @Override + public boolean hasDepthTest() { + return depthTest; + } + + @Override + public void setDepthTest(boolean depthTest) { + if (this.depthTest != depthTest) { + this.depthTest = depthTest; + setDirty(); + } + } + + @Nonnull + public EntityEntry getEntityEntry() { return entityEntry; } + + public void setEntityEntry(@Nonnull EntityEntry entityEntry) { + if (this.entityEntry == null || this.entityEntry != entityEntry) { + this.entityEntry = entityEntry; + entity = null; + setDirty(); + } + } + + @Nullable + @Override + public Vec3d getRotation() { + return rotation; + } + + @Override + public void setRotation(@Nullable Vec3d rotation) { + if (!Objects.equals(this.rotation, rotation)) { + this.rotation = rotation; + setDirty(); + } + } + + @Override + public void writeInitial(ByteBuf buf) { + ByteBufUtils.writeVec3d(buf, position); + ByteBufUtils.writeOptVec3d(buf, rotation); + buf.writeFloat(scale); + buf.writeBoolean(depthTest); + + ByteBufUtils.writeUTF8String(buf, entityEntry.getRegistryName().toString()); + } + + @Override + public void readInitial(ByteBuf buf) { + position = ByteBufUtils.readVec3d(buf); + rotation = ByteBufUtils.readOptVec3d(buf); + scale = buf.readFloat(); + depthTest = buf.readBoolean(); + + String resourceName = ByteBufUtils.readUTF8String(buf); + ResourceLocation name = new ResourceLocation(resourceName); + entityEntry = ForgeRegistries.ENTITIES.getValue(name); + } + + @Override + @SideOnly(Side.CLIENT) + public void draw(CanvasClient canvas) { + + Minecraft mc = Minecraft.getMinecraft(); + + if (entity == null) { + entity = entityEntry.newInstance(mc.world); + } + + GlStateManager.pushMatrix(); + + GlStateManager.translate(position.x, position.y, position.z); + GlStateManager.scale(scale, scale, scale); + if (rotation == null) { + RenderManager renderManager = mc.getRenderManager(); + + GlStateManager.rotate(180 - renderManager.playerViewY, 0, 1, 0); + GlStateManager.rotate(-renderManager.playerViewX, 1, 0, 0); + } else { + GlStateManager.rotate((float) rotation.x, 1, 0, 0); + GlStateManager.rotate((float) rotation.y, 0, 1, 0); + GlStateManager.rotate((float) rotation.z, 0, 0, 1); + } + + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.enableTexture2D(); + GlStateManager.enableRescaleNormal(); + + if (depthTest) { + GlStateManager.enableDepth(); + } else { + GlStateManager.disableDepth(); + } + + mc.getRenderManager().renderEntity(entity, position.x, position.y, position.z, 0, 0, true); + + GlStateManager.popMatrix(); + } +} diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/EntityObject.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/EntityObject.java new file mode 100644 index 00000000..d23591aa --- /dev/null +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/EntityObject.java @@ -0,0 +1,30 @@ +package org.squiddev.plethora.gameplay.modules.glasses.objects.object3d; + + +import net.minecraftforge.fml.common.registry.EntityEntry; +import org.squiddev.plethora.api.method.MethodResult; +import org.squiddev.plethora.api.method.wrapper.FromTarget; +import org.squiddev.plethora.api.method.wrapper.PlethoraMethod; + +import javax.annotation.Nonnull; + +/** + * An object which contains an entity. + */ +public interface EntityObject { + + @Nonnull + EntityEntry getEntityEntry(); + + void setEntityEntry(@Nonnull EntityEntry entityEntry); + + @PlethoraMethod(doc = "function(): string -- Get the entity name for this object.", worldThread = false) + static MethodResult getEntity(@FromTarget EntityObject object) { + return MethodResult.result(object.getEntityEntry().getRegistryName().toString()); + } + + @PlethoraMethod(doc = "function(string name): -- Set the entity value for this object.", worldThread = false) + static void setEntity(@FromTarget EntityObject object, EntityEntry entityEntry) { + object.setEntityEntry(entityEntry); + } +} diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Item3D.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Item3D.java index 4330cc7f..4bb17438 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Item3D.java +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Item3D.java @@ -7,6 +7,7 @@ import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.Vec3d; import net.minecraftforge.fml.relauncher.Side; @@ -14,6 +15,7 @@ import org.squiddev.plethora.gameplay.modules.glasses.BaseObject; import org.squiddev.plethora.gameplay.modules.glasses.CanvasClient; import org.squiddev.plethora.gameplay.modules.glasses.objects.ItemObject; +import org.squiddev.plethora.gameplay.modules.glasses.objects.NBTTaggable; import org.squiddev.plethora.gameplay.modules.glasses.objects.ObjectRegistry; import org.squiddev.plethora.gameplay.modules.glasses.objects.Scalable; import org.squiddev.plethora.utils.ByteBufUtils; @@ -22,7 +24,7 @@ import javax.annotation.Nullable; import java.util.Objects; -public class Item3D extends BaseObject implements Scalable, Positionable3D, DepthTestable, ItemObject, Rotatable3D { +public class Item3D extends BaseObject implements NBTTaggable, Scalable, Positionable3D, DepthTestable, ItemObject, Rotatable3D { private float scale; private Vec3d position = Vec3d.ZERO; private Vec3d rotation = Vec3d.ZERO; @@ -31,6 +33,7 @@ public class Item3D extends BaseObject implements Scalable, Positionable3D, Dept private int damage; private Item item; private ItemStack stack; + private NBTTagCompound nbt; public Item3D(int id, int parent) { super(id, parent, ObjectRegistry.ITEM_3D); @@ -90,6 +93,18 @@ public void setDamage(int damage) { } } + @Override + public NBTTagCompound getNBTTagCompound() { return nbt; } + + @Override + public void setNBTTagCompound(NBTTagCompound nbt) { + if (this.nbt == null || this.nbt != nbt) { + this.nbt = nbt; + stack = null; + setDirty(); + } + } + @Override @Nonnull public Item getItem() { @@ -128,6 +143,7 @@ public void writeInitial(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, item.getRegistryName().toString()); buf.writeInt(damage); + ByteBufUtils.writeTag(buf, nbt); } @Override @@ -141,6 +157,7 @@ public void readInitial(ByteBuf buf) { item = Item.REGISTRY.getObject(name); damage = buf.readInt(); + nbt = ByteBufUtils.readTag(buf); } @Override @@ -172,9 +189,13 @@ public void draw(CanvasClient canvas) { GlStateManager.disableDepth(); } - if (stack == null) stack = new ItemStack(item, 1, damage); + if (stack == null) { + stack = new ItemStack(item, 1, damage, nbt); + stack.setTagCompound(nbt); + } mc.getRenderItem().renderItem(stack, mc.player, ItemCameraTransforms.TransformType.NONE, false); GlStateManager.popMatrix(); } + } diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Rotatable3D.java b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Rotatable3D.java index 30c133e9..f0042b65 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Rotatable3D.java +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/glasses/objects/object3d/Rotatable3D.java @@ -4,6 +4,7 @@ import net.minecraft.util.math.Vec3d; import org.squiddev.plethora.api.method.MethodResult; import org.squiddev.plethora.api.method.wrapper.FromTarget; +import org.squiddev.plethora.api.method.wrapper.Optional; import org.squiddev.plethora.api.method.wrapper.PlethoraMethod; import javax.annotation.Nullable; @@ -23,10 +24,7 @@ static MethodResult getRotation(@FromTarget Rotatable3D object) { } @PlethoraMethod(doc = "function([x:number, y:number, z:number]) -- Set the rotation for this object, passing nothing if it should face the player.", worldThread = false) - static void setRotation(@FromTarget Rotatable3D object, Object[] args) throws LuaException { - object.setRotation(args.length == 0 || (args.length == 1 && args[0] == null) - ? null - : new Vec3d(getFloat(args, 0), getFloat(args, 1), getFloat(args, 2)) - ); + static void setRotation(@FromTarget Rotatable3D object, @Optional() Vec3d rotation) throws LuaException { + object.setRotation(rotation); } } diff --git a/src/main/java/org/squiddev/plethora/gameplay/modules/methods/MethodsScanner.java b/src/main/java/org/squiddev/plethora/gameplay/modules/methods/MethodsScanner.java index 51709508..31d2ed2d 100644 --- a/src/main/java/org/squiddev/plethora/gameplay/modules/methods/MethodsScanner.java +++ b/src/main/java/org/squiddev/plethora/gameplay/modules/methods/MethodsScanner.java @@ -4,7 +4,10 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import org.lwjgl.Sys; import org.squiddev.plethora.api.IWorldLocation; import org.squiddev.plethora.api.WorldLocation; import org.squiddev.plethora.api.meta.TypedMeta; @@ -12,6 +15,7 @@ import org.squiddev.plethora.api.method.IContext; import org.squiddev.plethora.api.method.MethodResult; import org.squiddev.plethora.api.method.wrapper.FromContext; +import org.squiddev.plethora.api.method.wrapper.Optional; import org.squiddev.plethora.api.method.wrapper.PlethoraMethod; import org.squiddev.plethora.api.module.IModuleContainer; import org.squiddev.plethora.api.reference.BlockReference; @@ -26,6 +30,7 @@ import java.util.Map; import static org.squiddev.plethora.api.method.ArgumentHelper.assertBetween; +import static org.squiddev.plethora.gameplay.ConfigGameplay.Scanner.rayTraceCost; public final class MethodsScanner { private MethodsScanner() { @@ -49,27 +54,68 @@ public static MethodResult scan( for (int oX = x - radius; oX <= x + radius; oX++) { for (int oY = y - radius; oY <= y + radius; oY++) { for (int oZ = z - radius; oZ <= z + radius; oZ++) { - BlockPos subPos = new BlockPos(oX, oY, oZ); - IBlockState block = world.getBlockState(subPos).getActualState(world, subPos); + result.add(getBasicMeta(world, new BlockPos(oX, oY, oZ), new Vec3d(x, y,z))); + } + } + } + + return result; + } - HashMap data = new HashMap<>(6); - data.put("x", oX - x); - data.put("y", oY - y); - data.put("z", oZ - z); - ResourceLocation name = block.getBlock().getRegistryName(); - data.put("name", name == null ? "unknown" : name.toString()); + @PlethoraMethod(module = PlethoraModules.SCANNER_S, + doc = "function(yaw: number, pitch: number, [hitLiquid: boolean[, ignoreBlockWithoutBoundingBox: boolean]): number, table -- Get a the distance and basic meta from a block using ray trace") + public static MethodResult rayTrace( + IContext context, + @FromContext(ContextKeys.ORIGIN) IWorldLocation location, + @FromContext(PlethoraModules.SCANNER_S) RangeInfo range, + double yaw, double pitch, @Optional(defBool = false) boolean hitLiquid, @Optional(defBool = true) boolean ignoreBlockWithoutBoundingBox + ) throws LuaException { + int radius = range.getRange(); + final double x = -Math.sin(yaw / 180.0f * Math.PI) * Math.cos(pitch / 180.0f * Math.PI); + final double z = Math.cos(yaw / 180.0f * Math.PI) * Math.cos(pitch / 180.0f * Math.PI); + final double y = -Math.sin(pitch / 180.0f * Math.PI); - MetaBlockState.fillBasicMeta(data, block); + return context.getCostHandler().await(rayTraceCost*radius, () -> { - result.add(data); - } + + Vec3d origin = location.getLoc(); + + Vec3d positionEnd = origin.add(new Vec3d(x,y,z).scale(range.getRange())); + + System.out.println(origin + " - " + positionEnd); + + RayTraceResult rayTraceResult = location.getWorld().rayTraceBlocks(origin, positionEnd, hitLiquid, ignoreBlockWithoutBoundingBox, false); + if (rayTraceResult == null) { + return MethodResult.empty(); + + } else { + BlockPos blockPos = rayTraceResult.getBlockPos(); + + return MethodResult.result( + origin.distanceTo(new Vec3d(blockPos.getX(), blockPos.getY(), blockPos.getZ())), + getBasicMeta(location.getWorld(), rayTraceResult.getBlockPos(), new Vec3d((int) origin.x, (int) origin.y, (int) origin.z))); } - } + }); + } - return result; + private static Map getBasicMeta(World world, BlockPos blockPos, Vec3d origin) { + IBlockState block = world.getBlockState(blockPos).getActualState(world, blockPos); + + HashMap data = new HashMap<>(6); + data.put("x", blockPos.getX() - origin.x); + data.put("y", blockPos.getY() - origin.y); + data.put("z", blockPos.getZ() - origin.z); + + ResourceLocation name = block.getBlock().getRegistryName(); + data.put("name", name == null ? "unknown" : name.toString()); + + MetaBlockState.fillBasicMeta(data, block); + + return data; } + @Nonnull @PlethoraMethod(module = PlethoraModules.SCANNER_S, doc = "-- Get metadata about a nearby block") public static TypedMeta getBlockMeta( @@ -78,6 +124,7 @@ public static MethodResult scan( @FromContext(PlethoraModules.SCANNER_S) RangeInfo range, int x, int y, int z ) throws LuaException { + int radius = range.getRange(); assertBetween(x, -radius, radius, "X coordinate out of bounds (%s)"); assertBetween(y, -radius, radius, "Y coordinate out of bounds (%s)"); diff --git a/src/main/java/org/squiddev/plethora/integration/MethodsCore.java b/src/main/java/org/squiddev/plethora/integration/MethodsCore.java index e3901b6a..75e69b04 100644 --- a/src/main/java/org/squiddev/plethora/integration/MethodsCore.java +++ b/src/main/java/org/squiddev/plethora/integration/MethodsCore.java @@ -2,16 +2,14 @@ import dan200.computercraft.api.lua.LuaException; import net.minecraft.util.ResourceLocation; -import org.squiddev.plethora.api.method.IContext; -import org.squiddev.plethora.api.method.IMethod; -import org.squiddev.plethora.api.method.IMethodCollection; -import org.squiddev.plethora.api.method.TypedLuaObject; +import org.squiddev.plethora.api.method.*; import org.squiddev.plethora.api.method.wrapper.ArgumentTypes; import org.squiddev.plethora.api.method.wrapper.FromTarget; import org.squiddev.plethora.api.method.wrapper.Optional; import org.squiddev.plethora.api.method.wrapper.PlethoraMethod; import org.squiddev.plethora.api.module.BasicModuleContainer; import org.squiddev.plethora.api.module.IModuleContainer; +import org.squiddev.plethora.core.ConfigCore; import javax.annotation.Nonnull; import java.util.HashMap; @@ -74,4 +72,14 @@ public static Object getDocs(@FromTarget IMethodCollection methodCollection, @Op throw new LuaException("No such method"); } } + + @PlethoraMethod(doc = "function(): number -- Get current energy") + public static MethodResult getEnergy(IContext context) { + return MethodResult.result(context.getCostHandler().get()); + } + + @PlethoraMethod(doc = "function(): number -- Get energy limit") + public static MethodResult getMaxEnergy(IContext context) { + return MethodResult.result(context.getCostHandler().getLimit()); + } } diff --git a/src/main/java/org/squiddev/plethora/utils/NBTUtilsRecursive.java b/src/main/java/org/squiddev/plethora/utils/NBTUtilsRecursive.java new file mode 100644 index 00000000..f595b1b1 --- /dev/null +++ b/src/main/java/org/squiddev/plethora/utils/NBTUtilsRecursive.java @@ -0,0 +1,63 @@ +package org.squiddev.plethora.utils; + +import dan200.computercraft.api.lua.LuaException; +import net.minecraft.nbt.*; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import java.util.Map; +import java.util.function.Predicate; + +import static dan200.computercraft.api.lua.ArgumentHelper.getTable; + +public final class NBTUtilsRecursive { + + @Nonnull + public static NBTTagCompound encodeNBTTagCompound(Map map) throws LuaException { + NBTTagCompound nbt = new NBTTagCompound(); + + for (Object key : map.keySet()) + nbt.setTag(key.toString(), encodeObject(map.get(key))); + + return nbt; + } + + @Nonnull + public static NBTTagList encodeNBTTagList(Map map) throws LuaException { + NBTTagList nbt = new NBTTagList(); + + for (Object key : map.keySet()) + nbt.appendTag(encodeObject(map.get(key))); + return nbt; + } + + @Nonnull + public static NBTBase encodeObject(Object object) throws LuaException { + switch (object.getClass().getSimpleName()) { + case "String": + return new NBTTagString((String) object); + case "Double": + return new NBTTagDouble((Double) object); + case "Boolean": + return new NBTTagByte((byte) ((Boolean) object ? 1 : 0)); + case "HashMap": + if ( + ((Map) object) + .keySet().stream().allMatch( + (Predicate) o -> o instanceof Double // Verify if it is an NBTTagList + ) + ) { + return encodeNBTTagList((Map) object); + } else { + return encodeNBTTagCompound((Map) object); + } + default: + throw new LuaException("Unknown type " + object.getClass().getSimpleName()); + } + } + + @Nonnull + public static @NotNull NBTTagCompound encodeObjects(Object[] objects, int index) throws LuaException { + return encodeNBTTagCompound(getTable(objects, index)); + } +}