mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
Improve luaentity sprite functionality (and add some random stuff)
This commit is contained in:
parent
b4e6ca63b5
commit
82a460ec90
@ -49,6 +49,9 @@
|
|||||||
-- - setpos(pos); pos={x=num, y=num, z=num}
|
-- - setpos(pos); pos={x=num, y=num, z=num}
|
||||||
-- - moveto(pos, continuous=false): interpolated move
|
-- - moveto(pos, continuous=false): interpolated move
|
||||||
-- - add_to_inventory(itemstring): add an item to object inventory
|
-- - add_to_inventory(itemstring): add an item to object inventory
|
||||||
|
-- - settexturemod(mod)
|
||||||
|
-- - setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2,
|
||||||
|
-- - select_horiz_by_yawpitch=false)
|
||||||
--
|
--
|
||||||
-- Registered entities:
|
-- Registered entities:
|
||||||
-- - Functions receive a "luaentity" as self:
|
-- - Functions receive a "luaentity" as self:
|
||||||
@ -1171,8 +1174,6 @@ local TNT = {
|
|||||||
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||||
visual = "cube",
|
visual = "cube",
|
||||||
textures = {"tnt_top.png","tnt_bottom.png","tnt_side.png","tnt_side.png","tnt_side.png","tnt_side.png"},
|
textures = {"tnt_top.png","tnt_bottom.png","tnt_side.png","tnt_side.png","tnt_side.png","tnt_side.png"},
|
||||||
--visual = "single_sprite",
|
|
||||||
--textures = {"mese.png^[forcesingle"},
|
|
||||||
-- Initial value for our timer
|
-- Initial value for our timer
|
||||||
timer = 0,
|
timer = 0,
|
||||||
-- Number of punches required to defuse
|
-- Number of punches required to defuse
|
||||||
@ -1227,6 +1228,36 @@ print("TNT dump: "..dump(TNT))
|
|||||||
print("Registering TNT");
|
print("Registering TNT");
|
||||||
minetest.register_entity("TNT", TNT)
|
minetest.register_entity("TNT", TNT)
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_entity("testentity", {
|
||||||
|
-- Static definition
|
||||||
|
physical = true, -- Collides with things
|
||||||
|
-- weight = 5,
|
||||||
|
collisionbox = {-0.7,-1.35,-0.7, 0.7,1.0,0.7},
|
||||||
|
--collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||||
|
visual = "sprite",
|
||||||
|
visual_size = {x=2, y=3},
|
||||||
|
textures = {"dungeon_master.png^[makealpha:128,0,0^[makealpha:128,128,0"},
|
||||||
|
spritediv = {x=6, y=5},
|
||||||
|
initial_sprite_basepos = {x=0, y=0},
|
||||||
|
|
||||||
|
on_activate = function(self, staticdata)
|
||||||
|
print("testentity.on_activate")
|
||||||
|
self.object:setsprite({x=0,y=0}, 1, 0, true)
|
||||||
|
--self.object:setsprite({x=0,y=0}, 4, 0.3, true)
|
||||||
|
|
||||||
|
-- Set gravity
|
||||||
|
self.object:setacceleration({x=0, y=-10, z=0})
|
||||||
|
-- Jump a bit upwards
|
||||||
|
self.object:setvelocity({x=0, y=10, z=0})
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_punch = function(self, hitter)
|
||||||
|
self.object:remove()
|
||||||
|
hitter:add_to_inventory('CraftItem testobject1 1')
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Falling stuff
|
-- Falling stuff
|
||||||
--
|
--
|
||||||
|
@ -72,11 +72,16 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Go through every node around the object
|
Go through every node around the object
|
||||||
TODO: Calculate the range of nodes that need to be checked
|
|
||||||
*/
|
*/
|
||||||
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
s16 min_x = (box_0.MinEdge.X / BS) - 2;
|
||||||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
s16 min_y = (box_0.MinEdge.Y / BS) - 2;
|
||||||
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
|
s16 min_z = (box_0.MinEdge.Z / BS) - 2;
|
||||||
|
s16 max_x = (box_0.MaxEdge.X / BS) + 1;
|
||||||
|
s16 max_y = (box_0.MaxEdge.Y / BS) + 1;
|
||||||
|
s16 max_z = (box_0.MaxEdge.Z / BS) + 1;
|
||||||
|
for(s16 y = oldpos_i.Y + min_y; y <= oldpos_i.Y + max_y; y++)
|
||||||
|
for(s16 z = oldpos_i.Z + min_z; z <= oldpos_i.Z + max_z; z++)
|
||||||
|
for(s16 x = oldpos_i.X + min_x; x <= oldpos_i.X + max_x; x++)
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
// Object collides into walkable nodes
|
// Object collides into walkable nodes
|
||||||
|
@ -899,8 +899,8 @@ void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
|||||||
|
|
||||||
/*infostream<<"MobV2CAO::addToScene using texture_name="<<
|
/*infostream<<"MobV2CAO::addToScene using texture_name="<<
|
||||||
m_texture_name<<std::endl;*/
|
m_texture_name<<std::endl;*/
|
||||||
std::string texture_string = "[makealpha2:128,0,0;128,128,0:";
|
std::string texture_string = m_texture_name +
|
||||||
texture_string += m_texture_name;
|
"^[makealpha:128,0,0^[makealpha:128,128,0";
|
||||||
|
|
||||||
scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
|
scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
|
||||||
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
|
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
|
||||||
@ -1281,8 +1281,81 @@ private:
|
|||||||
float m_yaw;
|
float m_yaw;
|
||||||
struct LuaEntityProperties *m_prop;
|
struct LuaEntityProperties *m_prop;
|
||||||
SmoothTranslator pos_translator;
|
SmoothTranslator pos_translator;
|
||||||
|
// Spritesheet/animation stuff
|
||||||
|
v2f m_tx_size;
|
||||||
|
v2s16 m_tx_basepos;
|
||||||
|
bool m_tx_select_horiz_by_yawpitch;
|
||||||
|
int m_anim_frame;
|
||||||
|
int m_anim_num_frames;
|
||||||
|
float m_anim_framelength;
|
||||||
|
float m_anim_timer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
CLuaEntityCAO(IGameDef *gamedef):
|
||||||
|
LuaEntityCAO(gamedef),
|
||||||
|
m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
|
||||||
|
m_meshnode(NULL),
|
||||||
|
m_spritenode(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_velocity(v3f(0,0,0)),
|
||||||
|
m_acceleration(v3f(0,0,0)),
|
||||||
|
m_yaw(0),
|
||||||
|
m_prop(new LuaEntityProperties),
|
||||||
|
m_tx_size(1,1),
|
||||||
|
m_tx_basepos(0,0),
|
||||||
|
m_tx_select_horiz_by_yawpitch(false),
|
||||||
|
m_anim_frame(0),
|
||||||
|
m_anim_num_frames(1),
|
||||||
|
m_anim_framelength(0.2),
|
||||||
|
m_anim_timer(0)
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
infostream<<"CLuaEntityCAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
// properties
|
||||||
|
std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
|
||||||
|
m_prop->deSerialize(prop_is);
|
||||||
|
|
||||||
|
infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
|
||||||
|
|
||||||
|
m_selection_box = m_prop->collisionbox;
|
||||||
|
m_selection_box.MinEdge *= BS;
|
||||||
|
m_selection_box.MaxEdge *= BS;
|
||||||
|
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
|
||||||
|
m_tx_size.X = 1.0 / m_prop->spritediv.X;
|
||||||
|
m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
|
||||||
|
m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
|
||||||
|
m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
~CLuaEntityCAO()
|
||||||
|
{
|
||||||
|
delete m_prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create(IGameDef *gamedef)
|
||||||
|
{
|
||||||
|
return new CLuaEntityCAO(gamedef);
|
||||||
|
}
|
||||||
|
|
||||||
u8 getType() const
|
u8 getType() const
|
||||||
{
|
{
|
||||||
return ACTIVEOBJECT_TYPE_LUAENTITY;
|
return ACTIVEOBJECT_TYPE_LUAENTITY;
|
||||||
@ -1296,30 +1369,6 @@ public:
|
|||||||
return pos_translator.vect_show;
|
return pos_translator.vect_show;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLuaEntityCAO(IGameDef *gamedef):
|
|
||||||
LuaEntityCAO(gamedef),
|
|
||||||
m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
|
|
||||||
m_meshnode(NULL),
|
|
||||||
m_spritenode(NULL),
|
|
||||||
m_position(v3f(0,10*BS,0)),
|
|
||||||
m_velocity(v3f(0,0,0)),
|
|
||||||
m_acceleration(v3f(0,0,0)),
|
|
||||||
m_yaw(0),
|
|
||||||
m_prop(new LuaEntityProperties)
|
|
||||||
{
|
|
||||||
ClientActiveObject::registerType(getType(), create);
|
|
||||||
}
|
|
||||||
|
|
||||||
~CLuaEntityCAO()
|
|
||||||
{
|
|
||||||
delete m_prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClientActiveObject* create(IGameDef *gamedef)
|
|
||||||
{
|
|
||||||
return new CLuaEntityCAO(gamedef);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
|
||||||
{
|
{
|
||||||
if(m_meshnode != NULL || m_spritenode != NULL)
|
if(m_meshnode != NULL || m_spritenode != NULL)
|
||||||
@ -1327,7 +1376,7 @@ public:
|
|||||||
|
|
||||||
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
//video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
if(m_prop->visual == "single_sprite"){
|
if(m_prop->visual == "sprite"){
|
||||||
infostream<<"CLuaEntityCAO::addToScene(): single_sprite"<<std::endl;
|
infostream<<"CLuaEntityCAO::addToScene(): single_sprite"<<std::endl;
|
||||||
m_spritenode = new scene::MyBillboardSceneNode(
|
m_spritenode = new scene::MyBillboardSceneNode(
|
||||||
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
|
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
|
||||||
@ -1339,7 +1388,7 @@ public:
|
|||||||
m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
||||||
m_spritenode->setColor(video::SColor(255,0,0,0));
|
m_spritenode->setColor(video::SColor(255,0,0,0));
|
||||||
m_spritenode->setVisible(false); /* Set visible when brightness is known */
|
m_spritenode->setVisible(false); /* Set visible when brightness is known */
|
||||||
m_spritenode->setSize(v2f(1,1)*1.0*BS);
|
m_spritenode->setSize(m_prop->visual_size*BS);
|
||||||
{
|
{
|
||||||
const float txs = 1.0 / 1;
|
const float txs = 1.0 / 1;
|
||||||
const float tys = 1.0 / 1;
|
const float tys = 1.0 / 1;
|
||||||
@ -1387,6 +1436,9 @@ public:
|
|||||||
|
|
||||||
for(u32 i=0; i<24; ++i){
|
for(u32 i=0; i<24; ++i){
|
||||||
vertices[i].Pos *= BS;
|
vertices[i].Pos *= BS;
|
||||||
|
vertices[i].Pos.Y *= m_prop->visual_size.Y;
|
||||||
|
vertices[i].Pos.X *= m_prop->visual_size.X;
|
||||||
|
vertices[i].Pos.Z *= m_prop->visual_size.X;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 indices[6] = {0,1,2,2,3,0};
|
u16 indices[6] = {0,1,2,2,3,0};
|
||||||
@ -1487,6 +1539,66 @@ public:
|
|||||||
pos_translator.translate(dtime);
|
pos_translator.translate(dtime);
|
||||||
updateNodePos();
|
updateNodePos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_anim_timer += dtime;
|
||||||
|
if(m_anim_timer >= m_anim_framelength){
|
||||||
|
m_anim_timer -= m_anim_framelength;
|
||||||
|
m_anim_frame++;
|
||||||
|
if(m_anim_frame >= m_anim_num_frames)
|
||||||
|
m_anim_frame = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTexturePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTexturePos()
|
||||||
|
{
|
||||||
|
if(m_spritenode){
|
||||||
|
scene::ICameraSceneNode* camera =
|
||||||
|
m_spritenode->getSceneManager()->getActiveCamera();
|
||||||
|
if(!camera)
|
||||||
|
return;
|
||||||
|
v3f cam_to_entity = m_spritenode->getAbsolutePosition()
|
||||||
|
- camera->getAbsolutePosition();
|
||||||
|
cam_to_entity.normalize();
|
||||||
|
|
||||||
|
int row = m_tx_basepos.Y;
|
||||||
|
int col = m_tx_basepos.X;
|
||||||
|
|
||||||
|
if(m_tx_select_horiz_by_yawpitch)
|
||||||
|
{
|
||||||
|
if(cam_to_entity.Y > 0.75)
|
||||||
|
col += 5;
|
||||||
|
else if(cam_to_entity.Y < -0.75)
|
||||||
|
col += 4;
|
||||||
|
else{
|
||||||
|
float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
|
||||||
|
float dir = mob_dir - m_yaw;
|
||||||
|
dir = wrapDegrees_180(dir);
|
||||||
|
//infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
|
||||||
|
if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
|
||||||
|
col += 2;
|
||||||
|
else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
|
||||||
|
col += 3;
|
||||||
|
else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
|
||||||
|
col += 0;
|
||||||
|
else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
|
||||||
|
col += 1;
|
||||||
|
else
|
||||||
|
col += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animation goes downwards
|
||||||
|
row += m_anim_frame;
|
||||||
|
|
||||||
|
float txs = m_tx_size.X;
|
||||||
|
float tys = m_tx_size.Y;
|
||||||
|
m_spritenode->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
|
||||||
|
m_spritenode->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
|
||||||
|
m_spritenode->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
|
||||||
|
m_spritenode->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateTextures(const std::string &mod)
|
void updateTextures(const std::string &mod)
|
||||||
@ -1562,35 +1674,20 @@ public:
|
|||||||
std::string mod = deSerializeString(is);
|
std::string mod = deSerializeString(is);
|
||||||
updateTextures(mod);
|
updateTextures(mod);
|
||||||
}
|
}
|
||||||
}
|
else if(cmd == 2) // set sprite
|
||||||
|
{
|
||||||
|
v2s16 p = readV2S16(is);
|
||||||
|
int num_frames = readU16(is);
|
||||||
|
float framelength = readF1000(is);
|
||||||
|
bool select_horiz_by_yawpitch = readU8(is);
|
||||||
|
|
||||||
void initialize(const std::string &data)
|
m_tx_basepos = p;
|
||||||
{
|
m_anim_num_frames = num_frames;
|
||||||
infostream<<"CLuaEntityCAO: Got init data"<<std::endl;
|
m_anim_framelength = framelength;
|
||||||
|
m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
|
||||||
|
|
||||||
std::istringstream is(data, std::ios::binary);
|
updateTexturePos();
|
||||||
// version
|
}
|
||||||
u8 version = readU8(is);
|
|
||||||
// check version
|
|
||||||
if(version != 0)
|
|
||||||
return;
|
|
||||||
// pos
|
|
||||||
m_position = readV3F1000(is);
|
|
||||||
// yaw
|
|
||||||
m_yaw = readF1000(is);
|
|
||||||
// properties
|
|
||||||
std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
|
|
||||||
m_prop->deSerialize(prop_is);
|
|
||||||
|
|
||||||
infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
|
|
||||||
|
|
||||||
m_selection_box = m_prop->collisionbox;
|
|
||||||
m_selection_box.MinEdge *= BS;
|
|
||||||
m_selection_box.MaxEdge *= BS;
|
|
||||||
|
|
||||||
pos_translator.init(m_position);
|
|
||||||
|
|
||||||
updateNodePos();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ ServerActiveObject* item_craft_create_object(const std::string &subname,
|
|||||||
}
|
}
|
||||||
else if(subname == "testobject1")
|
else if(subname == "testobject1")
|
||||||
{
|
{
|
||||||
ServerActiveObject *obj = new LuaEntitySAO(env, pos, "TNT", "");
|
ServerActiveObject *obj = new LuaEntitySAO(env, pos, "testentity", "");
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1748,6 +1748,11 @@ void LuaEntitySAO::setAcceleration(v3f acceleration)
|
|||||||
m_acceleration = acceleration;
|
m_acceleration = acceleration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v3f LuaEntitySAO::getAcceleration()
|
||||||
|
{
|
||||||
|
return m_acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
void LuaEntitySAO::setTextureMod(const std::string &mod)
|
void LuaEntitySAO::setTextureMod(const std::string &mod)
|
||||||
{
|
{
|
||||||
std::ostringstream os(std::ios::binary);
|
std::ostringstream os(std::ios::binary);
|
||||||
@ -1760,6 +1765,22 @@ void LuaEntitySAO::setTextureMod(const std::string &mod)
|
|||||||
m_messages_out.push_back(aom);
|
m_messages_out.push_back(aom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
|
||||||
|
bool select_horiz_by_yawpitch)
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (2 = set sprite)
|
||||||
|
writeU8(os, 2);
|
||||||
|
// parameters
|
||||||
|
writeV2S16(os, p);
|
||||||
|
writeU16(os, num_frames);
|
||||||
|
writeF1000(os, framelength);
|
||||||
|
writeU8(os, select_horiz_by_yawpitch);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
|
||||||
void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||||
{
|
{
|
||||||
m_last_sent_move_precision = m_base_position.getDistanceFrom(
|
m_last_sent_move_precision = m_base_position.getDistanceFrom(
|
||||||
|
@ -219,7 +219,10 @@ public:
|
|||||||
/* LuaEntitySAO-specific */
|
/* LuaEntitySAO-specific */
|
||||||
void setVelocity(v3f velocity);
|
void setVelocity(v3f velocity);
|
||||||
void setAcceleration(v3f acceleration);
|
void setAcceleration(v3f acceleration);
|
||||||
|
v3f getAcceleration();
|
||||||
void setTextureMod(const std::string &mod);
|
void setTextureMod(const std::string &mod);
|
||||||
|
void setSprite(v2s16 p, int num_frames, float framelength,
|
||||||
|
bool select_horiz_by_yawpitch);
|
||||||
private:
|
private:
|
||||||
void sendPosition(bool do_interpolate, bool is_movement_end);
|
void sendPosition(bool do_interpolate, bool is_movement_end);
|
||||||
|
|
||||||
|
@ -22,12 +22,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
#define PP2(x) "("<<(x).X<<","<<(x).Y<<")"
|
||||||
|
|
||||||
LuaEntityProperties::LuaEntityProperties():
|
LuaEntityProperties::LuaEntityProperties():
|
||||||
physical(false),
|
physical(false),
|
||||||
weight(5),
|
weight(5),
|
||||||
collisionbox(-0.5,-0.5,-0.5, 0.5,0.5,0.5),
|
collisionbox(-0.5,-0.5,-0.5, 0.5,0.5,0.5),
|
||||||
visual("single_sprite")
|
visual("single_sprite"),
|
||||||
|
visual_size(1,1),
|
||||||
|
spritediv(1,1),
|
||||||
|
initial_sprite_basepos(0,0)
|
||||||
{
|
{
|
||||||
textures.push_back("unknown_object.png");
|
textures.push_back("unknown_object.png");
|
||||||
}
|
}
|
||||||
@ -39,11 +43,14 @@ std::string LuaEntityProperties::dump()
|
|||||||
os<<", weight="<<weight;
|
os<<", weight="<<weight;
|
||||||
os<<", collisionbox="<<PP(collisionbox.MinEdge)<<","<<PP(collisionbox.MaxEdge);
|
os<<", collisionbox="<<PP(collisionbox.MinEdge)<<","<<PP(collisionbox.MaxEdge);
|
||||||
os<<", visual="<<visual;
|
os<<", visual="<<visual;
|
||||||
|
os<<", visual_size="<<PP2(visual_size);
|
||||||
os<<", textures=[";
|
os<<", textures=[";
|
||||||
for(u32 i=0; i<textures.size(); i++){
|
for(u32 i=0; i<textures.size(); i++){
|
||||||
os<<"\""<<textures[i]<<"\" ";
|
os<<"\""<<textures[i]<<"\" ";
|
||||||
}
|
}
|
||||||
os<<"]";
|
os<<"]";
|
||||||
|
os<<", spritediv="<<PP2(spritediv);
|
||||||
|
os<<", initial_sprite_basepos="<<PP2(initial_sprite_basepos);
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +62,13 @@ void LuaEntityProperties::serialize(std::ostream &os)
|
|||||||
writeV3F1000(os, collisionbox.MinEdge);
|
writeV3F1000(os, collisionbox.MinEdge);
|
||||||
writeV3F1000(os, collisionbox.MaxEdge);
|
writeV3F1000(os, collisionbox.MaxEdge);
|
||||||
os<<serializeString(visual);
|
os<<serializeString(visual);
|
||||||
|
writeV2F1000(os, visual_size);
|
||||||
writeU16(os, textures.size());
|
writeU16(os, textures.size());
|
||||||
for(u32 i=0; i<textures.size(); i++){
|
for(u32 i=0; i<textures.size(); i++){
|
||||||
os<<serializeString(textures[i]);
|
os<<serializeString(textures[i]);
|
||||||
}
|
}
|
||||||
|
writeV2S16(os, spritediv);
|
||||||
|
writeV2S16(os, initial_sprite_basepos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaEntityProperties::deSerialize(std::istream &is)
|
void LuaEntityProperties::deSerialize(std::istream &is)
|
||||||
@ -71,11 +81,14 @@ void LuaEntityProperties::deSerialize(std::istream &is)
|
|||||||
collisionbox.MinEdge = readV3F1000(is);
|
collisionbox.MinEdge = readV3F1000(is);
|
||||||
collisionbox.MaxEdge = readV3F1000(is);
|
collisionbox.MaxEdge = readV3F1000(is);
|
||||||
visual = deSerializeString(is);
|
visual = deSerializeString(is);
|
||||||
|
visual_size = readV2F1000(is);
|
||||||
textures.clear();
|
textures.clear();
|
||||||
u32 texture_count = readU16(is);
|
u32 texture_count = readU16(is);
|
||||||
for(u32 i=0; i<texture_count; i++){
|
for(u32 i=0; i<texture_count; i++){
|
||||||
textures.push_back(deSerializeString(is));
|
textures.push_back(deSerializeString(is));
|
||||||
}
|
}
|
||||||
|
spritediv = readV2S16(is);
|
||||||
|
initial_sprite_basepos = readV2S16(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,7 +31,10 @@ struct LuaEntityProperties
|
|||||||
float weight;
|
float weight;
|
||||||
core::aabbox3d<f32> collisionbox;
|
core::aabbox3d<f32> collisionbox;
|
||||||
std::string visual;
|
std::string visual;
|
||||||
|
v2f visual_size;
|
||||||
core::array<std::string> textures;
|
core::array<std::string> textures;
|
||||||
|
v2s16 spritediv;
|
||||||
|
v2s16 initial_sprite_basepos;
|
||||||
|
|
||||||
LuaEntityProperties();
|
LuaEntityProperties();
|
||||||
std::string dump();
|
std::string dump();
|
||||||
|
@ -142,6 +142,18 @@ static v3f readFloatPos(lua_State *L, int index)
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pushFloatPos(lua_State *L, v3f p)
|
||||||
|
{
|
||||||
|
p /= BS;
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushnumber(L, p.X);
|
||||||
|
lua_setfield(L, -2, "x");
|
||||||
|
lua_pushnumber(L, p.Y);
|
||||||
|
lua_setfield(L, -2, "y");
|
||||||
|
lua_pushnumber(L, p.Z);
|
||||||
|
lua_setfield(L, -2, "z");
|
||||||
|
}
|
||||||
|
|
||||||
static void pushpos(lua_State *L, v3s16 p)
|
static void pushpos(lua_State *L, v3s16 p)
|
||||||
{
|
{
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
@ -239,6 +251,32 @@ static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
|
|||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static v2s16 read_v2s16(lua_State *L, int index)
|
||||||
|
{
|
||||||
|
v2s16 p;
|
||||||
|
luaL_checktype(L, index, LUA_TTABLE);
|
||||||
|
lua_getfield(L, index, "x");
|
||||||
|
p.X = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
lua_getfield(L, index, "y");
|
||||||
|
p.Y = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static v2f read_v2f(lua_State *L, int index)
|
||||||
|
{
|
||||||
|
v2f p;
|
||||||
|
luaL_checktype(L, index, LUA_TTABLE);
|
||||||
|
lua_getfield(L, index, "x");
|
||||||
|
p.X = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
lua_getfield(L, index, "y");
|
||||||
|
p.Y = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
static bool getstringfield(lua_State *L, int table,
|
static bool getstringfield(lua_State *L, int table,
|
||||||
const char *fieldname, std::string &result)
|
const char *fieldname, std::string &result)
|
||||||
{
|
{
|
||||||
@ -307,6 +345,14 @@ static int getintfield_default(lua_State *L, int table,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*static float getfloatfield_default(lua_State *L, int table,
|
||||||
|
const char *fieldname, float default_)
|
||||||
|
{
|
||||||
|
float result = default_;
|
||||||
|
getfloatfield(L, table, fieldname, result);
|
||||||
|
return result;
|
||||||
|
}*/
|
||||||
|
|
||||||
static bool getboolfield_default(lua_State *L, int table,
|
static bool getboolfield_default(lua_State *L, int table,
|
||||||
const char *fieldname, bool default_)
|
const char *fieldname, bool default_)
|
||||||
{
|
{
|
||||||
@ -1235,6 +1281,18 @@ private:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getacceleration(self)
|
||||||
|
static int l_getacceleration(lua_State *L)
|
||||||
|
{
|
||||||
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
|
LuaEntitySAO *co = getluaobject(ref);
|
||||||
|
if(co == NULL) return 0;
|
||||||
|
// Do it
|
||||||
|
v3f v = co->getAcceleration();
|
||||||
|
pushFloatPos(L, v);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// add_to_inventory(self, itemstring)
|
// add_to_inventory(self, itemstring)
|
||||||
// returns: true if item was added, false otherwise
|
// returns: true if item was added, false otherwise
|
||||||
static int l_add_to_inventory(lua_State *L)
|
static int l_add_to_inventory(lua_State *L)
|
||||||
@ -1272,6 +1330,30 @@ private:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
|
||||||
|
// select_horiz_by_yawpitch=false)
|
||||||
|
static int l_setsprite(lua_State *L)
|
||||||
|
{
|
||||||
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
|
LuaEntitySAO *co = getluaobject(ref);
|
||||||
|
if(co == NULL) return 0;
|
||||||
|
// Do it
|
||||||
|
v2s16 p(0,0);
|
||||||
|
if(!lua_isnil(L, 2))
|
||||||
|
p = read_v2s16(L, 2);
|
||||||
|
int num_frames = 1;
|
||||||
|
if(!lua_isnil(L, 3))
|
||||||
|
num_frames = lua_tonumber(L, 3);
|
||||||
|
float framelength = 0.2;
|
||||||
|
if(!lua_isnil(L, 4))
|
||||||
|
framelength = lua_tonumber(L, 4);
|
||||||
|
bool select_horiz_by_yawpitch = false;
|
||||||
|
if(!lua_isnil(L, 5))
|
||||||
|
select_horiz_by_yawpitch = lua_toboolean(L, 5);
|
||||||
|
co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjectRef(ServerActiveObject *object):
|
ObjectRef(ServerActiveObject *object):
|
||||||
m_object(object)
|
m_object(object)
|
||||||
@ -1343,6 +1425,7 @@ const luaL_reg ObjectRef::methods[] = {
|
|||||||
method(ObjectRef, setacceleration),
|
method(ObjectRef, setacceleration),
|
||||||
method(ObjectRef, add_to_inventory),
|
method(ObjectRef, add_to_inventory),
|
||||||
method(ObjectRef, settexturemod),
|
method(ObjectRef, settexturemod),
|
||||||
|
method(ObjectRef, setsprite),
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1859,23 +1942,22 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
|
|||||||
luaentity_get(L, id);
|
luaentity_get(L, id);
|
||||||
//int object = lua_gettop(L);
|
//int object = lua_gettop(L);
|
||||||
|
|
||||||
lua_getfield(L, -1, "physical");
|
/* Read stuff */
|
||||||
if(lua_isboolean(L, -1))
|
|
||||||
prop->physical = lua_toboolean(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_getfield(L, -1, "weight");
|
getboolfield(L, -1, "physical", prop->physical);
|
||||||
prop->weight = lua_tonumber(L, -1);
|
|
||||||
lua_pop(L, 1);
|
getfloatfield(L, -1, "weight", prop->weight);
|
||||||
|
|
||||||
lua_getfield(L, -1, "collisionbox");
|
lua_getfield(L, -1, "collisionbox");
|
||||||
if(lua_istable(L, -1))
|
if(lua_istable(L, -1))
|
||||||
prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
|
prop->collisionbox = read_aabbox3df32(L, -1, 1.0);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
lua_getfield(L, -1, "visual");
|
getstringfield(L, -1, "visual", prop->visual);
|
||||||
if(lua_isstring(L, -1))
|
|
||||||
prop->visual = lua_tostring(L, -1);
|
lua_getfield(L, -1, "visual_size");
|
||||||
|
if(lua_istable(L, -1))
|
||||||
|
prop->visual_size = read_v2f(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
lua_getfield(L, -1, "textures");
|
lua_getfield(L, -1, "textures");
|
||||||
@ -1895,6 +1977,15 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
|
|||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
lua_getfield(L, -1, "spritediv");
|
||||||
|
if(lua_istable(L, -1))
|
||||||
|
prop->spritediv = read_v2s16(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
lua_getfield(L, -1, "initial_sprite_basepos");
|
||||||
|
if(lua_istable(L, -1))
|
||||||
|
prop->initial_sprite_basepos = read_v2s16(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
|
void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime)
|
||||||
|
113
src/tile.cpp
113
src/tile.cpp
@ -1361,14 +1361,14 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
"[makealpha:R,G,B:filename.png"
|
"[makealpha:R,G,B"
|
||||||
Use an image with converting one color to transparent.
|
Convert one color to transparent.
|
||||||
*/
|
*/
|
||||||
else if(part_of_name.substr(0,11) == "[makealpha:")
|
else if(part_of_name.substr(0,11) == "[makealpha:")
|
||||||
{
|
{
|
||||||
if(baseimg != NULL)
|
if(baseimg == NULL)
|
||||||
{
|
{
|
||||||
errorstream<<"generate_image(): baseimg!=NULL "
|
errorstream<<"generate_image(): baseimg==NULL "
|
||||||
<<"for part_of_name=\""<<part_of_name
|
<<"for part_of_name=\""<<part_of_name
|
||||||
<<"\", cancelling."<<std::endl;
|
<<"\", cancelling."<<std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -1377,99 +1377,28 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
|||||||
Strfnd sf(part_of_name.substr(11));
|
Strfnd sf(part_of_name.substr(11));
|
||||||
u32 r1 = stoi(sf.next(","));
|
u32 r1 = stoi(sf.next(","));
|
||||||
u32 g1 = stoi(sf.next(","));
|
u32 g1 = stoi(sf.next(","));
|
||||||
u32 b1 = stoi(sf.next(":"));
|
u32 b1 = stoi(sf.next(""));
|
||||||
std::string filename = sf.next("");
|
std::string filename = sf.next("");
|
||||||
|
|
||||||
/*infostream<<"generate_image(): Loading file \""<<filename
|
core::dimension2d<u32> dim = baseimg->getDimension();
|
||||||
<<"\""<<std::endl;*/
|
|
||||||
|
|
||||||
video::IImage *image = sourcecache->getOrLoad(filename, device);
|
/*video::IImage *oldbaseimg = baseimg;
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
oldbaseimg->copyTo(baseimg);
|
||||||
|
oldbaseimg->drop();*/
|
||||||
|
|
||||||
if(image == NULL)
|
// Set alpha to full
|
||||||
|
for(u32 y=0; y<dim.Height; y++)
|
||||||
|
for(u32 x=0; x<dim.Width; x++)
|
||||||
{
|
{
|
||||||
errorstream<<"generate_image(): Loading file \""
|
video::SColor c = baseimg->getPixel(x,y);
|
||||||
<<filename<<"\" failed"<<std::endl;
|
u32 r = c.getRed();
|
||||||
}
|
u32 g = c.getGreen();
|
||||||
else
|
u32 b = c.getBlue();
|
||||||
{
|
if(!(r == r1 && g == g1 && b == b1))
|
||||||
core::dimension2d<u32> dim = image->getDimension();
|
continue;
|
||||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
c.setAlpha(0);
|
||||||
|
baseimg->setPixel(x,y,c);
|
||||||
// Blit
|
|
||||||
image->copyTo(baseimg);
|
|
||||||
|
|
||||||
image->drop();
|
|
||||||
|
|
||||||
for(u32 y=0; y<dim.Height; y++)
|
|
||||||
for(u32 x=0; x<dim.Width; x++)
|
|
||||||
{
|
|
||||||
video::SColor c = baseimg->getPixel(x,y);
|
|
||||||
u32 r = c.getRed();
|
|
||||||
u32 g = c.getGreen();
|
|
||||||
u32 b = c.getBlue();
|
|
||||||
if(!(r == r1 && g == g1 && b == b1))
|
|
||||||
continue;
|
|
||||||
c.setAlpha(0);
|
|
||||||
baseimg->setPixel(x,y,c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
"[makealpha2:R,G,B;R2,G2,B2:filename.png"
|
|
||||||
Use an image with converting two colors to transparent.
|
|
||||||
*/
|
|
||||||
else if(part_of_name.substr(0,12) == "[makealpha2:")
|
|
||||||
{
|
|
||||||
if(baseimg != NULL)
|
|
||||||
{
|
|
||||||
errorstream<<"generate_image(): baseimg!=NULL "
|
|
||||||
<<"for part_of_name=\""<<part_of_name
|
|
||||||
<<"\", cancelling."<<std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Strfnd sf(part_of_name.substr(12));
|
|
||||||
u32 r1 = stoi(sf.next(","));
|
|
||||||
u32 g1 = stoi(sf.next(","));
|
|
||||||
u32 b1 = stoi(sf.next(";"));
|
|
||||||
u32 r2 = stoi(sf.next(","));
|
|
||||||
u32 g2 = stoi(sf.next(","));
|
|
||||||
u32 b2 = stoi(sf.next(":"));
|
|
||||||
std::string filename = sf.next("");
|
|
||||||
|
|
||||||
/*infostream<<"generate_image(): Loading filename \""<<filename
|
|
||||||
<<"\""<<std::endl;*/
|
|
||||||
|
|
||||||
video::IImage *image = sourcecache->getOrLoad(filename, device);
|
|
||||||
|
|
||||||
if(image == NULL)
|
|
||||||
{
|
|
||||||
errorstream<<"generate_image(): Loading file \""
|
|
||||||
<<filename<<"\" failed"<<std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core::dimension2d<u32> dim = image->getDimension();
|
|
||||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
|
||||||
|
|
||||||
// Blit
|
|
||||||
image->copyTo(baseimg);
|
|
||||||
|
|
||||||
image->drop();
|
|
||||||
|
|
||||||
for(u32 y=0; y<dim.Height; y++)
|
|
||||||
for(u32 x=0; x<dim.Width; x++)
|
|
||||||
{
|
|
||||||
video::SColor c = baseimg->getPixel(x,y);
|
|
||||||
u32 r = c.getRed();
|
|
||||||
u32 g = c.getGreen();
|
|
||||||
u32 b = c.getBlue();
|
|
||||||
if(!(r == r1 && g == g1 && b == b1) &&
|
|
||||||
!(r == r2 && g == g2 && b == b2))
|
|
||||||
continue;
|
|
||||||
c.setAlpha(0);
|
|
||||||
baseimg->setPixel(x,y,c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -148,6 +148,19 @@ inline v3f readV3F1000(u8 *data)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void writeV2F1000(u8 *data, v2f p)
|
||||||
|
{
|
||||||
|
writeF1000(&data[0], p.X);
|
||||||
|
writeF1000(&data[4], p.Y);
|
||||||
|
}
|
||||||
|
inline v2f readV2F1000(u8 *data)
|
||||||
|
{
|
||||||
|
v2f p;
|
||||||
|
p.X = (float)readF1000(&data[0]);
|
||||||
|
p.Y = (float)readF1000(&data[4]);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
inline void writeV2S16(u8 *data, v2s16 p)
|
inline void writeV2S16(u8 *data, v2s16 p)
|
||||||
{
|
{
|
||||||
writeS16(&data[0], p.X);
|
writeS16(&data[0], p.X);
|
||||||
@ -274,6 +287,45 @@ inline v3f readV3F1000(std::istream &is)
|
|||||||
return readV3F1000((u8*)buf);
|
return readV3F1000((u8*)buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void writeV2F1000(std::ostream &os, v2f p)
|
||||||
|
{
|
||||||
|
char buf[8];
|
||||||
|
writeV2F1000((u8*)buf, p);
|
||||||
|
os.write(buf, 8);
|
||||||
|
}
|
||||||
|
inline v2f readV2F1000(std::istream &is)
|
||||||
|
{
|
||||||
|
char buf[8];
|
||||||
|
is.read(buf, 8);
|
||||||
|
return readV2F1000((u8*)buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void writeV2S16(std::ostream &os, v2s16 p)
|
||||||
|
{
|
||||||
|
char buf[4];
|
||||||
|
writeV2S16((u8*)buf, p);
|
||||||
|
os.write(buf, 4);
|
||||||
|
}
|
||||||
|
inline v2s16 readV2S16(std::istream &is)
|
||||||
|
{
|
||||||
|
char buf[4];
|
||||||
|
is.read(buf, 4);
|
||||||
|
return readV2S16((u8*)buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void writeV3S16(std::ostream &os, v3s16 p)
|
||||||
|
{
|
||||||
|
char buf[6];
|
||||||
|
writeV3S16((u8*)buf, p);
|
||||||
|
os.write(buf, 6);
|
||||||
|
}
|
||||||
|
inline v3s16 readV3S16(std::istream &is)
|
||||||
|
{
|
||||||
|
char buf[6];
|
||||||
|
is.read(buf, 6);
|
||||||
|
return readV3S16((u8*)buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
None of these are used at the moment
|
None of these are used at the moment
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user