Clean up vector library, standardize parameter orders, conform to docs.

master
Nicole Collings 2020-07-22 00:46:06 -07:00
parent c00ee72529
commit c7c2e38c38
7 changed files with 145 additions and 153 deletions

View File

@ -1,9 +1,126 @@
-- Zepha Vector Library
-- Version 1.0
_G["vector"] = {}
-- create_vector
-- Create a new vector, and give it a metatable.
-- x, y, and z must all be numbers.
local function create_vector(x, y, z)
local v = {x, y, z}
setmetatable(v, vector._mt)
return v
end
-- vector.add
-- Add two vectors or a vector and number
function vector.add(v1, v2)
if not vector.is_vector(v1) then return end
if vector.is_vector(v2) then
return create_vector(rawget(v1, 1) + rawget(v2, 1), rawget(v1, 2) + rawget(v2, 2), rawget(v1, 3) + rawget(v2, 3))
elseif type(v2) == "number" then
return create_vector(rawget(v1, 1) + v2, rawget(v1, 2) + v2, rawget(v1, 3) + v2)
end
end
-- vector.negative
-- Flips a vector's content's signs
function vector.negative(v)
if not vector.is_vector(v) then return end
return create_vector(-rawget(v, 1), -rawget(v, 2), -rawget(v, 3))
end
-- vector.subtract
-- Subtract v2 from v1
function vector.subtract(v1, v2)
return vector.add(v1, vector.negative(v2))
end
-- vector.multiply
-- Multiply v1 by a vector or number
function vector.multiply(v1, m)
if not vector.is_vector(v1) then return end
if vector.is_vector(m) then
return create_vector(rawget(v1, 1) * rawget(m, 1), rawget(v1, 2) * rawget(m, 2), rawget(v1, 3) * rawget(m, 3))
elseif type(m) == "number" then
return create_vector(rawget(v1, 1) * m, rawget(v1, 2) * m, rawget(v1, 3) * m)
end
end
-- vector.divide
-- Divice v1 by a vector or number
function vector.divide(v1, m)
if not vector.is_vector(v1) then return end
if vector.is_vector(m) then
return create_vector(rawget(v1, 1) / rawget(m, 1), rawget(v1, 2) / rawget(m, 2), rawget(v1, 3) / rawget(m, 3))
elseif type(m) == "number" then
return create_vector(rawget(v1, 1) / m, rawget(v1, 2) / m, rawget(v1, 3) / m)
end
end
-- vector.pow
-- Return v to the power of p
function vector.pow(v, m)
if not vector.is_vector(v) then return end
local res = create_vector(rawget(v, 1), rawget(v, 2), rawget(v, 3))
for i = 1, power - 1 do res = res * v end
return res
end
-- vector.equal
-- Return a boolean indicating if v1 == v2
function vector.equal(v1, v2)
if not vector.is_vector(v1) or not vector.is_vector(v2) then return end
return (rawget(v1, 1) == rawget(v2, 1) and rawget(v1, 2) == rawget(v2, 2) and rawget(v1, 3) == rawget(v2, 3))
end
-- vector.abs
-- Return the absolute value of v
function vector.abs(v)
if not vector.is_vector(v) then return end
return create_vector(math.abs(rawget(v, 1)), math.abs(rawget(v, 2)), math.abs(rawget(v, 3)))
end
-- vector.round
-- Round each vector value to the nearest integer
function vector.round(v)
if not vector.is_vector(v) then return end
return create_vector(math.round(rawget(v, 1)), math.round(rawget(v, 2)), math.round(rawget(v, 3)))
end
-- vector.floor
-- Floor each vector value to the lowest integer
function vector.floor(v)
if not vector.is_vector(v) then return end
return create_vector(math.floor(rawget(v, 1)), math.floor(rawget(v, 2)), math.floor(rawget(v, 3)))
end
-- vector.ceil
-- Ceil each vector value to the highest integer
function vector.ceil(v)
if not vector.is_vector(v) then return end
return create_vector(math.ceil(rawget(v, 1)), math.ceil(rawget(v, 2)), math.ceil(rawget(v, 3)))
end
-- vector.distance_squared
-- Get the square of the distance between two vectors
-- This function is faster if you only need to compare two distances
function vector.distance_squared(v1, v2)
if not vector.is_vector(v1) or not vector.is_vector(v2) then return end
local diff = vector.abs(vector.subtract(v1, v2))
return diff.x ^ 2 + diff.y ^ 2 + diff.z ^ 2
end
-- vector.distance
-- Get the distance between two vectors
function vector.distance(v1, v2)
if not vector.is_vector(v1) or not vector.is_vector(v2) then return end
return math.sqrt(vector.distance_squared(v1, v2))
end
-- Vector metatable
-- A metatable to be assigned to vectors which applies mathematic operators
local vector_mt = {
vector._mt = {
__is_vector = true,
-- Value manipulation functions
@ -54,44 +171,23 @@ local vector_mt = {
end,
-- Higher level methods
abs = function(tbl)
return vector.abs(tbl)
end,
round = function(tbl)
return vector.round(tbl)
end,
floor = function(tbl)
return vector.floor(tbl)
end,
ceil = function(tbl)
return vector.ceil(tbl)
end,
distance_squared = function(tbl, o)
return vector.distance_squared(tbl, o)
end,
distance = function(tbl, o)
return vector.distance(tbl, o)
end
abs = vector.abs,
round = vector.round,
floor = vector.floor,
ceil = vector.ceil,
dist = vector.distance,
distance, vector.distance,
dist2 = vector.distance_squared,
distance_squared = vector.distance_squared
}
-- create_vector
-- Create a new vector, and give it a metatable.
-- x, y, and z must all be numbers.
local function create_vector(x, y, z)
local vector = {x, y, z}
setmetatable(vector, vector_mt)
return vector
end
-- check_vector
-- vector.is_vector
-- Checks if a value is a vector.
local function check_vector(v)
function vector.is_vector(v)
if type(v) ~= "table" or not v.__is_vector then return false end
return true
end
_G["vector"] = {}
-- vector.new
-- Constructor function for creating vectors from a table or 2-3 values.
-- Table constructor works with 1-3 values
@ -111,110 +207,4 @@ vector.new = function(x, y, z)
end
-- vector.new shorthand
_G["V"] = vector.new
-- vector.add
-- Add two vectors or a vector and number
vector.add = function(v1, v2)
if not check_vector(v1) then return end
if check_vector(v2) then
return create_vector(rawget(v1, 1) + rawget(v2, 1), rawget(v1, 2) + rawget(v2, 2), rawget(v1, 3) + rawget(v2, 3))
elseif type(v2) == "number" then
return create_vector(rawget(v1, 1) + v2, rawget(v1, 2) + v2, rawget(v1, 3) + v2)
end
end
-- vector.negative
-- Flips a vector's content's signs
vector.negative = function(v)
if not check_vector(v) then return end
return create_vector(-rawget(v, 1), -rawget(v, 2), -rawget(v, 3))
end
-- vector.subtract
-- Subtract v2 from v1
vector.subtract = function(v1, v2)
return vector.add(v1, vector.negative(v2))
end
-- vector.multiply
-- Multiply v1 by a vector or number
vector.multiply = function(v1, m)
if not check_vector(v1) then return end
if check_vector(m) then
return create_vector(rawget(v1, 1) * rawget(m, 1), rawget(v1, 2) * rawget(m, 2), rawget(v1, 3) * rawget(m, 3))
elseif type(m) == "number" then
return create_vector(rawget(v1, 1) * m, rawget(v1, 2) * m, rawget(v1, 3) * m)
end
end
-- vector.divide
-- Divice v1 by a vector or number
vector.divide = function(v1, m)
if not check_vector(v1) then return end
if check_vector(m) then
return create_vector(rawget(v1, 1) / rawget(m, 1), rawget(v1, 2) / rawget(m, 2), rawget(v1, 3) / rawget(m, 3))
elseif type(m) == "number" then
return create_vector(rawget(v1, 1) / m, rawget(v1, 2) / m, rawget(v1, 3) / m)
end
end
-- vector.pow
-- Return v to the power of p
vector.pow = function(v, m)
if not check_vector(v) then return end
local res = create_vector(rawget(v, 1), rawget(v, 2), rawget(v, 3))
for i = 1, power - 1 do res = res * v end
return res
end
-- vector.equal
-- Return a boolean indicating if v1 == v2
vector.equal = function(v1, v2)
if not check_vector(v1) or not check_vector(v2) then return end
return (rawget(v1, 1) == rawget(v2, 1) and rawget(v1, 2) == rawget(v2, 2) and rawget(v1, 3) == rawget(v2, 3))
end
-- vector.abs
-- Return the absolute value of v
vector.abs = function(v)
if not check_vector(v) then return end
return create_vector(math.abs(rawget(v, 1)), math.abs(rawget(v, 2)), math.abs(rawget(v, 3)))
end
-- vector.round
-- Round each vector value to the nearest integer
vector.round = function(v)
if not check_vector(v) then return end
return create_vector(math.round(rawget(v, 1)), math.round(rawget(v, 2)), math.round(rawget(v, 3)))
end
-- vector.floor
-- Floor each vector value to the lowest integer
vector.floor = function(v)
if not check_vector(v) then return end
return create_vector(math.floor(rawget(v, 1)), math.floor(rawget(v, 2)), math.floor(rawget(v, 3)))
end
-- vector.ceil
-- Ceil each vector value to the highest integer
vector.ceil = function(v)
if not check_vector(v) then return end
return create_vector(math.ceil(rawget(v, 1)), math.ceil(rawget(v, 2)), math.ceil(rawget(v, 3)))
end
-- vector.distance_squared
-- Get the square of the distance between two vectors
-- This function is faster if you only need to compare two distances
vector.distance_squared = function(v1, v2)
if not check_vector(v1) or not check_vector(v2) then return end
local diff = vector.abs(vector.subtract(v1, v2))
return diff.x ^ 2 + diff.y ^ 2 + diff.z ^ 2
end
-- vector.distance
-- Get the distance between two vectors
vector.distance = function(v1, v2)
if not check_vector(v1) or not check_vector(v2) then return end
return math.sqrt(vector.distance_squared(v1, v2))
end
_G["V"] = vector.new

View File

@ -12,9 +12,9 @@ namespace Api {
zepha.__builtin.trigger_event = function(event, ...)
if zepha.registered_callbacks[event] == nil then return nil end
for _, v in pairs(zepha.registered_callbacks[event]) do
if (type(v) == "function") then
v(...)
for _, EVENT_CALLBACK in pairs(zepha.registered_callbacks[event]) do
if (type(EVENT_CALLBACK) == "function") then
EVENT_CALLBACK(...)
end
end
end

View File

@ -17,9 +17,9 @@ namespace Api {
static void add_entity_c(sol::state& lua, sol::table& core, ClientGame& defs, LocalWorld& world) {
core["entities"] = lua.create_table();
core.set_function("add_entity", [&](sol::optional<std::string> identifier, sol::optional<sol::table> pos, sol::object staticData) {
if (!identifier || !identifier->length()) throw std::runtime_error("expected a string as the first argument.");
if (!pos) throw std::runtime_error("expected a vector as the second argument.");
core.set_function("add_entity", [&](sol::optional<sol::table> pos, sol::optional<std::string> identifier, sol::object staticData) {
if (!identifier || !identifier->length()) throw std::runtime_error("Expected an identifier as the second argument.");
if (!pos) throw std::runtime_error("Expected a position as the first argument.");
if (core["registered_entities"][*identifier] == sol::nil) throw std::runtime_error("identifier '" + *identifier + "' is not a valid entity identifier.");
sol::table entityDef = core["registered_entities"][*identifier];
@ -55,9 +55,9 @@ namespace Api {
static void add_entity_s(sol::state& lua, sol::table& core, ServerGame& defs, ServerWorld& world) {
core["entities"] = lua.create_table();
core.set_function("add_entity", [&](sol::optional<std::string> identifier, sol::optional<sol::table> pos, sol::object staticData) {
if (!identifier || !identifier->length()) throw std::runtime_error("expected a string as the first argument.");
if (!pos) throw std::runtime_error("expected a vector as the second argument.");
core.set_function("add_entity", [&](sol::optional<sol::table> pos, sol::optional<std::string> identifier, sol::object staticData) {
if (!identifier || !identifier->length()) throw std::runtime_error("Expected an identifier as the second argument.");
if (!pos) throw std::runtime_error("Expected a position as the first argument.");
if (core["registered_entities"][*identifier] == sol::nil) throw std::runtime_error("identifier '" + *identifier + "' is not a valid entity identifier.");
sol::table entityDef = core["registered_entities"][*identifier];

View File

@ -10,7 +10,9 @@
namespace Api {
static void get_block(sol::table &core, DefinitionAtlas& defs, World& world) {
core.set_function("get_block", [&](sol::table pos) -> std::string {
if (!pos["x"] || !pos["y"] || !pos["z"]) throw std::runtime_error("expected a vector as the first argument.");
if (!pos.get<sol::optional<float>>("x") || !pos.get<sol::optional<float>>("y") || !pos.get<sol::optional<float>>("z"))
throw std::runtime_error("Expected a vector as the first argument.");
return defs.fromId(world.getBlock({pos.get<float>("x"), pos.get<float>("y"), pos.get<float>("z")})).identifier;
});
}

View File

@ -1,5 +1,5 @@
local function collides(entity)
return zepha.get_block(entity.pos + V{0, 0.5, 0}) ~= "air"
return zepha.get_block((entity.pos - V{0, 0.5, 0}):floor()) ~= "air"
end
zepha.register_entity("@aurailus:item_collection:dropped_item", {
@ -73,7 +73,7 @@ zepha.register_entity("@aurailus:item_collection:dropped_item", {
end,
check_collect = function(self)
for _,p in pairs(zepha.players) do
if vector.distance(p.pos, self.object.pos) < 2 then
if p.pos:dist(self.object.pos) < 2 then
self.object.pos = p.pos + V{0, 0.90, 0}
self.scooping = true

View File

@ -5,6 +5,6 @@ if zepha.server then
local yields = get_yield(pos)
if yields == nil then return end
zepha.add_entity("@aurailus:item_collection:dropped_item", pos + 0.5, { item = yields });
zepha.add_entity(pos + 0.5, "@aurailus:item_collection:dropped_item", { item = yields });
end)
end

View File

@ -18,5 +18,5 @@ zepha.register_entity("zeus:default:test", {
})
if zepha.client then
local entity = zepha.add_entity("zeus:default:test", V{})
local entity = zepha.add_entity(V{}, "zeus:default:test")
end