Invoke can now only invoke method in class 'invoke', likewise for 'probe'
This commit is contained in:
@@ -13,5 +13,5 @@ RestoreOpenAssetTabsOnRestart=AlwaysRestore
|
|||||||
AutoSaveWarningInSeconds=0
|
AutoSaveWarningInSeconds=0
|
||||||
|
|
||||||
[/Script/Integration.lxProjectSettings]
|
[/Script/Integration.lxProjectSettings]
|
||||||
ActiveServer=/Game/Luprex/KnownServers/SS_Localhost.SS_Localhost
|
ActiveServer=/Game/Luprex/KnownServers/SS_Standalone.SS_Standalone
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/Widgets/WB_Menu.uasset
LFS
BIN
Content/Widgets/WB_Menu.uasset
LFS
Binary file not shown.
@@ -15,7 +15,7 @@ The goal of this patch is to achieve a more consistent state of affairs. First,
|
|||||||
Second, since the traceback will always contain the file and line number, and since there will always be a traceback, there's no reason to put the file and line number into the error message itself. We have taken steps to remove that feature. To accomplish this, the following patches to lua were made:
|
Second, since the traceback will always contain the file and line number, and since there will always be a traceback, there's no reason to put the file and line number into the error message itself. We have taken steps to remove that feature. To accomplish this, the following patches to lua were made:
|
||||||
|
|
||||||
- removed calls to 'lua_where' (replacing them with 'lua_no_where')
|
- removed calls to 'lua_where' (replacing them with 'lua_no_where')
|
||||||
- removed calls to 'addinfo' (replacing them with 'no_addinfo')
|
- removed calls to 'addinfo' (just commented out)
|
||||||
|
|
||||||
This patch is live and functioning.
|
This patch is live and functioning.
|
||||||
|
|
||||||
@@ -74,17 +74,16 @@ This patch is live and is used implicitly whenever you iterate over a lua table.
|
|||||||
|
|
||||||
## The Table Length Patch
|
## The Table Length Patch
|
||||||
|
|
||||||
I've changed the lua length operator so that when it is
|
I've changed the lua length operator so that when it is applied to a table, it
|
||||||
applied to a table, it returns the number of keys in the
|
returns the number of keys in the table. It does this in constant time. This
|
||||||
table. It does this in constant time. This change affects
|
change affects lua_len, lua_rawlen, and the lua # operator.
|
||||||
lua_len, lua_rawlen, and the lua # operator.
|
|
||||||
|
|
||||||
You might be wondering what the lua length operator
|
You might be wondering what the lua length operator used to do? The lua
|
||||||
used to do? The lua documentation says this:
|
documentation says this:
|
||||||
|
|
||||||
> The length operator applied on a table returns a border in
|
> The length operator applied on a table returns a border in that table. A
|
||||||
> that table. A border in a table t is any non-negative
|
> border in a table t is any non-negative integer that satisfies the following
|
||||||
> integer that satisfies the following condition:
|
> condition:
|
||||||
>
|
>
|
||||||
> (border == 0 or t[border] ~= nil) and
|
> (border == 0 or t[border] ~= nil) and
|
||||||
> (t[border + 1] == nil or border == math.maxinteger)
|
> (t[border + 1] == nil or border == math.maxinteger)
|
||||||
@@ -93,63 +92,53 @@ Those are *terrible* semantics:
|
|||||||
|
|
||||||
- They're not useful for anything.
|
- They're not useful for anything.
|
||||||
- It's not deterministic.
|
- It's not deterministic.
|
||||||
- In no sense of the word "length" is this the
|
- In no sense of the word "length" is this the length of the table.
|
||||||
length of the table.
|
|
||||||
|
|
||||||
Let me explain how that mess happened. They obviously
|
Let me explain how that mess happened. They obviously wanted the length
|
||||||
wanted the length operator to return the number of keys in
|
operator to return the number of keys in the table. Unfortunately, to count
|
||||||
the table. Unfortunately, to count the number of keys in a
|
the number of keys in a lua table actually takes O(N) time. So they came up
|
||||||
lua table actually takes O(N) time. So they came up with a
|
with a hack to make it faster: O(1). Unfortunately, the hack relies on the
|
||||||
hack to make it faster: O(1). Unfortunately, the hack relies
|
table being a vector. That is, the table must have numbered keys starting with
|
||||||
on the table being a vector. That is, the table must have
|
1. As long as you apply their hack to a vector, it works perfectly and returns
|
||||||
numbered keys starting with 1. As long as you apply their
|
the number of keys.
|
||||||
hack to a vector, it works perfectly and returns the
|
|
||||||
number of keys.
|
|
||||||
|
|
||||||
Unfortunately, if you apply the hacked length algorithm to a
|
Unfortunately, if you apply the hacked length algorithm to a table that isn't
|
||||||
table that isn't a vector, it doesn't work at all.
|
a vector, it doesn't work at all.
|
||||||
|
|
||||||
But I think the lua documentation didn't want to admit, "it
|
But I think the lua documentation didn't want to admit, "it doesn't work at
|
||||||
doesn't work at all." So instead, they invented this
|
all." So instead, they invented this concept of "a border" and pretended that
|
||||||
concept of "a border" and pretended that was in some way a
|
was in some way a helpful result. They should have just said, "the result is
|
||||||
helpful result. They should have just said, "the result is
|
|
||||||
undefined."
|
undefined."
|
||||||
|
|
||||||
I had to change the table internal representation
|
I had to change the table internal representation for the table iterator patch
|
||||||
for the table iterator patch (above). With the modified
|
(above). With the modified table representation, returning the number of keys
|
||||||
table representation, returning the number of keys in the
|
in the table can be done in constant time, whether it's a vector or not. So I
|
||||||
table can be done in constant time, whether it's a vector or
|
changed the length operator to just return the number of keys, full stop.
|
||||||
not. So I changed the length operator to just return
|
|
||||||
the number of keys, full stop.
|
|
||||||
|
|
||||||
I've also added another function, lua_nkeys. This also
|
I've also added another function, lua_nkeys. This also returns the number of
|
||||||
returns the number of keys in the table. It doesn't add any
|
keys in the table. It doesn't add any functionality - I could use lua_rawlen
|
||||||
functionality - I could use lua_rawlen and that would work
|
and that would work just as well. However, using lua_nkeys emphasizes the
|
||||||
just as well. However, using lua_nkeys emphasizes the fact
|
fact that my code needs the *real* table length, not the "border" bullshit
|
||||||
that my code needs the *real* table length, not the "border"
|
that lua used to provide.
|
||||||
bullshit that lua used to provide.
|
|
||||||
|
|
||||||
This patch is live, and is necessary to the determinism of
|
This patch is live, and is necessary to the determinism of the system.
|
||||||
the system.
|
|
||||||
|
|
||||||
## The Table Flag Bits Patch
|
## The Table Flag Bits Patch
|
||||||
|
|
||||||
Our difference transmission algorithm does a recursive walk
|
Our difference transmission algorithm does a recursive walk of the tables in a
|
||||||
of the tables in a given tangible. That recursive walk
|
given tangible. That recursive walk requires a *visited* bit in each table. Of
|
||||||
requires a *visited* bit in each table. Of course, the lua
|
course, the lua way of doing this would be to store the set of visited tables
|
||||||
way of doing this would be to store the set of visited
|
as a separate table. But that would be a lot slower than just setting a bit,
|
||||||
tables as a separate table. But that would be a lot slower
|
and difference transmission is the core of our system's performance
|
||||||
than just setting a bit, and difference transmission is the
|
bottleneck.
|
||||||
core of our system's performance bottleneck.
|
|
||||||
|
|
||||||
We also need to store, in each table, a *table-type* enum.
|
We also need to store, in each table, a *table-type* enum. We have several
|
||||||
We have several subtypes of tables: general tables, tangible
|
subtypes of tables: general tables, tangible tables, class tables, and so
|
||||||
tables, class tables, and so forth. The difference
|
forth. The difference transmitter treats different types of tables
|
||||||
transmitter treats different types of tables differently.
|
differently.
|
||||||
|
|
||||||
This patch adds a 16-bit "flagbits" field to every Lua
|
This patch adds a 16-bit "flagbits" field to every Lua table. We have added
|
||||||
table. We have added these lua API functions to access these
|
these lua API functions to access these flag bits:
|
||||||
flag bits:
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
uint16_t lua_getflagbits(lua_State *L, int index);
|
uint16_t lua_getflagbits(lua_State *L, int index);
|
||||||
@@ -159,87 +148,74 @@ void lua_setflagbits(lua_State *L, int index, uint16_t flagbits);
|
|||||||
void lua_modflagbits(lua_State *L, int index, uint16_t clearbits, uint16_t setbits);
|
void lua_modflagbits(lua_State *L, int index, uint16_t clearbits, uint16_t setbits);
|
||||||
```
|
```
|
||||||
|
|
||||||
The eris code for serializing the lua data structures has
|
The eris code for serializing the lua data structures has been modified to
|
||||||
been modified to save and restore the flagbits. Aside from
|
save and restore the flagbits. Aside from simply storing them, and saving and
|
||||||
simply storing them, and saving and restoring them with
|
restoring them with eris, the lua runtime doesn't do anything at all with the
|
||||||
eris, the lua runtime doesn't do anything at all with the
|
|
||||||
flagbits.
|
flagbits.
|
||||||
|
|
||||||
The Luprex engine has set aside four of the bits to store
|
The Luprex engine has set aside four of the bits to store the table-type enum.
|
||||||
the table-type enum. It has set aside one of the bits for
|
It has set aside one of the bits for the 'visited' bit of the difference
|
||||||
the 'visited' bit of the difference transmission algorithm.
|
transmission algorithm. The rest of the bits are currently unused.
|
||||||
The rest of the bits are currently unused.
|
|
||||||
|
|
||||||
This patch is live and in-use.
|
This patch is live and in-use.
|
||||||
|
|
||||||
## The Insert Frame Patch
|
## The Insert Frame Patch
|
||||||
|
|
||||||
When we write C functions for Lua, we allocate a "stack
|
When we write C functions for Lua, we allocate a "stack frame" on the lua
|
||||||
frame" on the lua stack. This is accomplished by class
|
stack. This is accomplished by class LuaDefStack. See the document "Our
|
||||||
LuaDefStack. See the document "Our In-House Lua API" for
|
In-House Lua API" for more information.
|
||||||
more information.
|
|
||||||
|
|
||||||
This function has to insert some "nils" into the base of the
|
This function has to insert some "nils" into the base of the stack. The lua
|
||||||
stack. The lua API does have a function that can do this,
|
API does have a function that can do this, but using it would be O(N^2). Since
|
||||||
but using it would be O(N^2). Since this functionality is
|
this functionality is used in every single C function for Lua, we decided to
|
||||||
used in every single C function for Lua, we decided to
|
optimize things a little. We added a function to the lua API that can do it in
|
||||||
optimize things a little. We added a function to the lua API
|
O(N) time. The name of the function is lua_insert_frame, which sounds fancy,
|
||||||
that can do it in O(N) time. The name of the function is
|
but all it does is insert N "nils" at the bottom of the stack.
|
||||||
lua_insert_frame, which sounds fancy, but all it does is
|
|
||||||
insert N "nils" at the bottom of the stack.
|
|
||||||
|
|
||||||
This patch is live and is used in class LuaDefStack.
|
This patch is live and is used in class LuaDefStack.
|
||||||
|
|
||||||
## The C++ Exceptions Patch
|
## The C++ Exceptions Patch
|
||||||
|
|
||||||
We've compiled lua to use C++ exceptions instead of longjmp.
|
We've compiled lua to use C++ exceptions instead of longjmp. The advantage of
|
||||||
The advantage of this is that if you do a lua_yield or
|
this is that if you do a lua_yield or lua_error, any C++ destructors on the
|
||||||
lua_error, any C++ destructors on the stack will get called.
|
stack will get called.
|
||||||
|
|
||||||
Although lua_yield and lua_error both throw C++ exceptions,
|
Although lua_yield and lua_error both throw C++ exceptions, Lua cannot *deal
|
||||||
Lua cannot *deal with* C++ exceptions except for those it
|
with* C++ exceptions except for those it generates itself. Therefore:
|
||||||
generates itself. Therefore:
|
|
||||||
|
|
||||||
- Never call the lua interpreter inside a C++ catch-block!
|
- Never call the lua interpreter inside a C++ catch-block!
|
||||||
- Never throw an exception from inside a LuaDefine!
|
- Never throw an exception from inside a LuaDefine!
|
||||||
|
|
||||||
Exception 1: If you throw an uncaught exception, all that
|
Exception 1: If you throw an uncaught exception, all that does is terminate
|
||||||
does is terminate the program. It's always legal to
|
the program. It's always legal to terminate the program.
|
||||||
terminate the program.
|
|
||||||
|
|
||||||
Exception 2: If you throw an exception inside a LuaDefine
|
Exception 2: If you throw an exception inside a LuaDefine and then catch it
|
||||||
and then catch it inside the same LuaDefine, that's OK,
|
inside the same LuaDefine, that's OK, because the lua interpreter is not
|
||||||
because the lua interpreter is not getting unwound.
|
getting unwound.
|
||||||
|
|
||||||
Using C++ exceptions in lua_yield and lua_error means that
|
Using C++ exceptions in lua_yield and lua_error means that C++ destructors get
|
||||||
C++ destructors get called. Normally, calling destructors is
|
called. Normally, calling destructors is a good thing. However, there is one
|
||||||
a good thing. However, there is one known case where this
|
known case where this causes issues: class LuaExtStack. Class LuaExtStack
|
||||||
causes issues: class LuaExtStack. Class LuaExtStack pushes
|
pushes values onto the lua stack in its constructor, and later, in its
|
||||||
values onto the lua stack in its constructor, and later, in
|
destructor, it pops those values back off. Straightforward enough. But if you
|
||||||
its destructor, it pops those values back off.
|
throw an error using the lua_error function, then the error message is pushed
|
||||||
Straightforward enough. But if you throw an error using the
|
on top of the lua stack. If the throw triggers the LuaExtStack destructor,
|
||||||
lua_error function, then the error message is pushed on top
|
then LuaExtStack will pop the stack, and in doing so, it will unintentionally
|
||||||
of the lua stack. If the throw triggers the LuaExtStack
|
throw out the error message. Oops.
|
||||||
destructor, then LuaExtStack will pop the stack, and in
|
|
||||||
doing so, it will unintentionally throw out the error
|
|
||||||
message. Oops.
|
|
||||||
|
|
||||||
To fix this, we had to add a lua patch, which adds a new API
|
To fix this, we had to add a lua patch, which adds a new API function
|
||||||
function "lua_isthrowing." This API function is used by the
|
"lua_isthrowing." This API function is used by the LuaExtStack destructor, to
|
||||||
LuaExtStack destructor, to decide whether to clean up the
|
decide whether to clean up the stack or not. This new API function is not used
|
||||||
stack or not. This new API function is not used anywhere
|
anywhere else in Luprex, and I do not expect it will ever be needed anywhere
|
||||||
else in Luprex, and I do not expect it will ever be needed
|
else.
|
||||||
anywhere else.
|
|
||||||
|
|
||||||
This patch is live and is needed to keep lua error messages
|
This patch is live and is needed to keep lua error messages working.
|
||||||
working.
|
|
||||||
|
|
||||||
## The Object-Oriented Lua Patch
|
## The Object-Oriented Lua Patch
|
||||||
|
|
||||||
We have a patch to make lua object-oriented. To
|
We have a patch to make lua object-oriented. To really explain this patch, we
|
||||||
really understand this patch, we need a separate
|
need a separate markdown file, "Object-Oriented-Lua.md". See that file for an
|
||||||
markdown file, "Object-Oriented-Lua.md". See
|
explanation.
|
||||||
that file for an explanation.
|
|
||||||
|
|
||||||
## The Print No Address Patch (Unimplemented)
|
## The Print No Address Patch (Unimplemented)
|
||||||
|
|
||||||
@@ -267,11 +243,10 @@ Update 2: I don't remember using userdata objects at all. I am not sure that Upd
|
|||||||
|
|
||||||
## Token Literal Syntax Patch
|
## Token Literal Syntax Patch
|
||||||
|
|
||||||
Tokens are lightuserdata values encoding short alphanumeric
|
Tokens are lightuserdata values encoding short alphanumeric strings as base38
|
||||||
strings as base38 numbers (see `Tokens-A-New-Lua-Type.md`).
|
numbers (see `Tokens-A-New-Lua-Type.md`). This patch adds a literal syntax to
|
||||||
This patch adds a literal syntax to the Lua parser so that
|
the Lua parser so that tokens can be written directly in Lua source code using
|
||||||
tokens can be written directly in Lua source code using the
|
the `@` prefix:
|
||||||
`@` prefix:
|
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local x = @null
|
local x = @null
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ meant to be used for rapid update after the player invokes a thread on that one
|
|||||||
|
|
||||||
* Do we really need can_be_controlled?
|
* Do we really need can_be_controlled?
|
||||||
|
|
||||||
* Replace engio with 'invoke.' and 'probe.'
|
|
||||||
|
|
||||||
Secret / semi-secret variables
|
Secret / semi-secret variables
|
||||||
|
|
||||||
Secret functions
|
Secret functions
|
||||||
|
|||||||
@@ -43,9 +43,6 @@ bool UlxViewportClient::TryBringToFront(const FWidgetPath &Path)
|
|||||||
|
|
||||||
bool UlxViewportClient::InputKey(const FInputKeyEventArgs &EventArgs)
|
bool UlxViewportClient::InputKey(const FInputKeyEventArgs &EventArgs)
|
||||||
{
|
{
|
||||||
UE_LOG(LogLuprexIntegration, Display, TEXT("UlxViewportClient::InputKey key=%s event=%d"),
|
|
||||||
*EventArgs.Key.ToString(), (int32)EventArgs.Event);
|
|
||||||
|
|
||||||
// Only act on left mouse button presses that bubbled up to the
|
// Only act on left mouse button presses that bubbled up to the
|
||||||
// viewport unhandled. If the click landed on a descendant of a
|
// viewport unhandled. If the click landed on a descendant of a
|
||||||
// top-level widget in the root canvas, bring that top-level widget
|
// top-level widget in the root canvas, bring that top-level widget
|
||||||
|
|||||||
@@ -461,6 +461,11 @@ void World::probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (classname != "probe") {
|
||||||
|
retvals->write_lua_value_type(LuaValueType::STRING);
|
||||||
|
retvals->write_string("currently, can only probe functions in class 'probe'");
|
||||||
|
}
|
||||||
|
|
||||||
LuaVar lclass, lfunc, actor, place, mt, tangibles, retvec, retval;
|
LuaVar lclass, lfunc, actor, place, mt, tangibles, retvec, retval;
|
||||||
LuaExtStack LS(L, lclass, lfunc, actor, place, mt, tangibles, retvec, retval);
|
LuaExtStack LS(L, lclass, lfunc, actor, place, mt, tangibles, retvec, retval);
|
||||||
|
|
||||||
@@ -944,6 +949,9 @@ void World::invoke_lua_call(int64_t actor_id, int64_t place_id, std::string_view
|
|||||||
} catch (const StreamException &ex) {
|
} catch (const StreamException &ex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Currently, we only allow calling functions in class 'invoke'.
|
||||||
|
if (classname != "invoke") return;
|
||||||
|
|
||||||
{
|
{
|
||||||
lua_State *L = state();
|
lua_State *L = state();
|
||||||
@@ -966,8 +974,6 @@ void World::invoke_lua_call(int64_t actor_id, int64_t place_id, std::string_view
|
|||||||
classname = LS.classname(lclass);
|
classname = LS.classname(lclass);
|
||||||
if (classname.empty()) return;
|
if (classname.empty()) return;
|
||||||
|
|
||||||
// TODO: CHECK FOR PERMIT_INVOKE.
|
|
||||||
|
|
||||||
// Get the function from the class.
|
// Get the function from the class.
|
||||||
LS.rawget(lfunc, lclass, funcname);
|
LS.rawget(lfunc, lclass, funcname);
|
||||||
if (!LS.isfunction(lfunc)) return;
|
if (!LS.isfunction(lfunc)) return;
|
||||||
|
|||||||
@@ -29,9 +29,10 @@
|
|||||||
--
|
--
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
makeclass('engio')
|
makeclass('probe')
|
||||||
|
makeclass('invoke')
|
||||||
|
|
||||||
function engio.gethotkeys()
|
function probe.gethotkeys()
|
||||||
local class = tangible.getclass(place)
|
local class = tangible.getclass(place)
|
||||||
|
|
||||||
-- if the tangible doesn't have a 'lookhotkeys' function, do nothing
|
-- if the tangible doesn't have a 'lookhotkeys' function, do nothing
|
||||||
@@ -48,7 +49,7 @@ function engio.gethotkeys()
|
|||||||
return keys
|
return keys
|
||||||
end
|
end
|
||||||
|
|
||||||
function engio.presshotkey(pressed)
|
function invoke.presshotkey(pressed)
|
||||||
local class = tangible.getclass(place)
|
local class = tangible.getclass(place)
|
||||||
|
|
||||||
-- if the tangible doesn't have a 'lookhotkeys' function, do nothing
|
-- if the tangible doesn't have a 'lookhotkeys' function, do nothing
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
makeclass("world")
|
makeclass('world')
|
||||||
makeclass('login')
|
makeclass('login')
|
||||||
makeclass("engio")
|
makeclass('probe')
|
||||||
|
makeclass('invoke')
|
||||||
makeclass('cube')
|
makeclass('cube')
|
||||||
makeclass('sphere')
|
makeclass('sphere')
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ function world.init()
|
|||||||
login.init()
|
login.init()
|
||||||
end
|
end
|
||||||
|
|
||||||
function engio.move(action, xyz, facing)
|
function invoke.move(action, xyz, facing)
|
||||||
-- todo: sanity check the parameters.
|
-- todo: sanity check the parameters.
|
||||||
tangible.animate{tan=actor, anim={action=action, interactive=true, xyz=xyz, facing=facing}}
|
tangible.animate{tan=actor, anim={action=action, interactive=true, xyz=xyz, facing=facing}}
|
||||||
end
|
end
|
||||||
@@ -54,7 +55,7 @@ function sphere.lookhotkeys(add)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function engio.getlookat()
|
function probe.getlookat()
|
||||||
local class = tangible.getclass(place)
|
local class = tangible.getclass(place)
|
||||||
|
|
||||||
-- if the tangible is not of any class, return empty string.
|
-- if the tangible is not of any class, return empty string.
|
||||||
|
|||||||
@@ -29,9 +29,10 @@
|
|||||||
--
|
--
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
makeclass('engio')
|
makeclass('probe')
|
||||||
|
makeclass('invoke')
|
||||||
|
|
||||||
function engio.getmenu()
|
function probe.getmenu()
|
||||||
local class = tangible.getclass(place)
|
local class = tangible.getclass(place)
|
||||||
|
|
||||||
-- if the tangible doesn't have a 'lookmenu' function, do nothing
|
-- if the tangible doesn't have a 'lookmenu' function, do nothing
|
||||||
@@ -47,7 +48,7 @@ function engio.getmenu()
|
|||||||
return items
|
return items
|
||||||
end
|
end
|
||||||
|
|
||||||
function engio.pressmenu(label)
|
function invoke.pressmenu(label)
|
||||||
local class = tangible.getclass(place)
|
local class = tangible.getclass(place)
|
||||||
|
|
||||||
-- if the tangible doesn't have a 'lookmenu' function, do nothing
|
-- if the tangible doesn't have a 'lookmenu' function, do nothing
|
||||||
|
|||||||
Reference in New Issue
Block a user