Compare commits

..

8 Commits

19 changed files with 208 additions and 77 deletions

1
.gitattributes vendored
View File

@@ -13,6 +13,7 @@
*.jpg filter=lfs diff=lfs merge=lfs -text *.jpg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text *.psd filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.sln filter=lfs diff=lfs merge=lfs -text *.sln filter=lfs diff=lfs merge=lfs -text
*.uasset filter=lfs diff=lfs merge=lfs -text *.uasset filter=lfs diff=lfs merge=lfs -text
*.umap filter=lfs diff=lfs merge=lfs -text *.umap filter=lfs diff=lfs merge=lfs -text

View File

@@ -1,20 +0,0 @@
[/Script/UnrealEd.EditorStyleSettings]
AssetEditorOpenLocation=MainWindow
[/Script/BlueprintGraph.BlueprintEditorSettings]
SaveOnCompile=SoC_SuccessOnly
[/Script/UnrealEd.EditorLoadingSavingSettings]
RestoreOpenAssetTabsOnRestart=AlwaysRestore
AutoSaveWarningInSeconds=0
[/Script/Integration.lxProjectSettings]
ActiveServer=/Game/Luprex/KnownServers/SS_Standalone.SS_Standalone
[/Script/Integration.lxEditorSettings]
ActiveServer=/Game/Luprex/KnownServers/SS_Localhost.SS_Localhost

Binary file not shown.

Binary file not shown.

View File

@@ -2,6 +2,7 @@
#include "BreakToDebugger.h" #include "BreakToDebugger.h"
#include "Blueprint/BlueprintExceptionInfo.h" #include "Blueprint/BlueprintExceptionInfo.h"
#include "Kismet2/KismetDebugUtilities.h" #include "Kismet2/KismetDebugUtilities.h"
#include "LuprexEditorSettings.h"
ELogVerbosity::Type FlxBreakToDebuggerOutputDevice::ConvertThreshold(ElxBreakToDebuggerThreshold Verbosity) { ELogVerbosity::Type FlxBreakToDebuggerOutputDevice::ConvertThreshold(ElxBreakToDebuggerThreshold Verbosity) {
switch (Verbosity) { switch (Verbosity) {
@@ -15,8 +16,8 @@ ELogVerbosity::Type FlxBreakToDebuggerOutputDevice::ConvertThreshold(ElxBreakToD
} }
} }
FlxBreakToDebuggerOutputDevice::FlxBreakToDebuggerOutputDevice(const ElxBreakToDebuggerThreshold &SensitivityRef) FlxBreakToDebuggerOutputDevice::FlxBreakToDebuggerOutputDevice()
: Sensitivity(SensitivityRef) : Settings(GetDefault<UlxEditorSettings>())
{ {
GLog->AddOutputDevice(this); GLog->AddOutputDevice(this);
} }
@@ -48,7 +49,7 @@ void FlxBreakToDebuggerOutputDevice::Serialize(const TCHAR* V, ELogVerbosity::Ty
{ {
// If the error isn't serious enough, do nothing. // If the error isn't serious enough, do nothing.
// //
if (Verbosity > ConvertThreshold(Sensitivity)) if (Verbosity > ConvertThreshold(Settings->BreakToDebuggerLogVerbosity))
{ {
return; return;
} }
@@ -67,6 +68,13 @@ void FlxBreakToDebuggerOutputDevice::Serialize(const TCHAR* V, ELogVerbosity::Ty
UObject *TopObject = Frame->Object; UObject *TopObject = Frame->Object;
if (TopObject == nullptr) return; if (TopObject == nullptr) return;
// If the category is in the exclude list, do nothing.
//
if (Settings->BreakToDebuggerExcludeCategories.Contains(Category))
{
return;
}
// Notify the debugger that there's been an exception. // Notify the debugger that there's been an exception.
// //
FBlueprintExceptionInfo ExceptionInfo(EBlueprintExceptionType::Breakpoint, FText::FromStringView(FStringView(V))); FBlueprintExceptionInfo ExceptionInfo(EBlueprintExceptionType::Breakpoint, FText::FromStringView(FStringView(V)));

View File

@@ -79,19 +79,15 @@ enum class ElxBreakToDebuggerThreshold : uint8 {
}; };
class UlxEditorSettings;
struct FlxBreakToDebuggerOutputDevice : public FOutputDevice struct FlxBreakToDebuggerOutputDevice : public FOutputDevice
{ {
public: public:
// The constructor and destructor automatically register // The constructor and destructor automatically register
// this output device with GLog. // this output device with GLog.
// //
// This struct doesn't store the sensitivity threshold. FlxBreakToDebuggerOutputDevice();
// It relies on the LuprexGameMode class to do that, so
// that the threshold can be easily edited with the
// blueprint editor. This struct must be initialized
// with a reference to the threshold variable.
//
FlxBreakToDebuggerOutputDevice(const ElxBreakToDebuggerThreshold &SensitivityRef);
~FlxBreakToDebuggerOutputDevice(); ~FlxBreakToDebuggerOutputDevice();
// Inspect a log message. // Inspect a log message.
@@ -109,5 +105,5 @@ public:
private: private:
static ELogVerbosity::Type ConvertThreshold(ElxBreakToDebuggerThreshold Verbosity); static ELogVerbosity::Type ConvertThreshold(ElxBreakToDebuggerThreshold Verbosity);
const ElxBreakToDebuggerThreshold &Sensitivity; const UlxEditorSettings *Settings = nullptr;
}; };

View File

@@ -2,3 +2,4 @@
DEFINE_LOG_CATEGORY(LogLuprex); DEFINE_LOG_CATEGORY(LogLuprex);
DEFINE_LOG_CATEGORY(LogLuprexIntegration); DEFINE_LOG_CATEGORY(LogLuprexIntegration);
DEFINE_LOG_CATEGORY(LogLuprexConsole);

View File

@@ -153,3 +153,7 @@ DECLARE_LOG_CATEGORY_EXTERN(LogLuprex, Display, All);
// Messages about the Luprex integration with Unreal. // Messages about the Luprex integration with Unreal.
// //
DECLARE_LOG_CATEGORY_EXTERN(LogLuprexIntegration, Display, All); DECLARE_LOG_CATEGORY_EXTERN(LogLuprexIntegration, Display, All);
// Messages from the Luprex console.
//
DECLARE_LOG_CATEGORY_EXTERN(LogLuprexConsole, Display, All);

View File

@@ -1 +1,7 @@
#include "LuprexEditorSettings.h" #include "LuprexEditorSettings.h"
#include "Common.h"
UlxEditorSettings::UlxEditorSettings()
{
BreakToDebuggerExcludeCategories.Add(LogLuprexConsole.GetCategoryName());
}

View File

@@ -25,6 +25,8 @@ class INTEGRATION_API UlxEditorSettings : public UDeveloperSettings
GENERATED_BODY() GENERATED_BODY()
public: public:
UlxEditorSettings();
virtual FName GetContainerName() const override { return TEXT("Editor"); } virtual FName GetContainerName() const override { return TEXT("Editor"); }
virtual FName GetCategoryName() const override { return TEXT("Luprex"); } virtual FName GetCategoryName() const override { return TEXT("Luprex"); }
virtual FName GetSectionName() const override { return TEXT("Settings"); } virtual FName GetSectionName() const override { return TEXT("Settings"); }
@@ -39,5 +41,9 @@ public:
// severity, the blueprint debugger will automatically pause with a breakpoint. // severity, the blueprint debugger will automatically pause with a breakpoint.
UPROPERTY(Config, EditAnywhere, Category="Debugging Tools") UPROPERTY(Config, EditAnywhere, Category="Debugging Tools")
ElxBreakToDebuggerThreshold BreakToDebuggerLogVerbosity; ElxBreakToDebuggerThreshold BreakToDebuggerLogVerbosity;
// Log categories in this set are excluded from BreakToDebugger triggering.
UPROPERTY(Config, EditAnywhere, Category="Debugging Tools")
TSet<FName> BreakToDebuggerExcludeCategories;
}; };

View File

@@ -238,7 +238,7 @@ void ALuprexGameModeBase::InitializeGlobalState()
// If somebody generates a log message that's severe enough, break to debugger. // If somebody generates a log message that's severe enough, break to debugger.
BreakToDebuggerLogVerbosityDevice.Reset( BreakToDebuggerLogVerbosityDevice.Reset(
new FlxBreakToDebuggerOutputDevice(GetDefault<UlxEditorSettings>()->BreakToDebuggerLogVerbosity)); new FlxBreakToDebuggerOutputDevice());
} }
void ALuprexGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) void ALuprexGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason)

View File

@@ -242,3 +242,8 @@ void UlxUtilityLibrary::ValidateLuaExpr(
Status = w.ValidateLuaExpr(Code, ErrorMessage); Status = w.ValidateLuaExpr(Code, ErrorMessage);
} }
void UlxUtilityLibrary::LogLuprexConsoleMessage(const FString &Message)
{
UE_LOG(LogLuprexConsole, Warning, TEXT("%s"), *Message);
}

View File

@@ -144,4 +144,9 @@ public:
// //
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Utility") UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Utility")
static void ValidateLuaExpr(ElxLuaSyntaxCheck &Status, FString &ErrorMessage, UObject *context, const FString &Code); static void ValidateLuaExpr(ElxLuaSyntaxCheck &Status, FString &ErrorMessage, UObject *context, const FString &Code);
// Log a message to the LogLuprexConsole category.
//
UFUNCTION(BlueprintCallable, Category = "Luprex|Utility")
static void LogLuprexConsoleMessage(const FString &Message);
}; };

4
TeppyNotes.txt Normal file
View File

@@ -0,0 +1,4 @@
- To run a server:
- cd luprex
- ./build/Linux/luprexstatic lpxserver

View File

@@ -171,6 +171,7 @@ public:
LuaExtraArgs(int i, int s) : index_(i), size_(s) {} LuaExtraArgs(int i, int s) : index_(i), size_(s) {}
LuaSpecial operator[] (int n) const { return LuaSpecial(index_ + n); } LuaSpecial operator[] (int n) const { return LuaSpecial(index_ + n); }
int index(int n) const { return index_ + n; }
int size() const { return size_; } int size() const { return size_; }
friend class LuaCoreStack; friend class LuaCoreStack;

View File

@@ -607,20 +607,13 @@ LuaDefine(tangible_start, "tangible,function,arg1,arg2...",
"|to continue running until it blocks. But from that point" "|to continue running until it blocks. But from that point"
"|forward, the thread will never be resumed for any reason.") { "|forward, the thread will never be resumed for any reason.") {
int top = lua_gettop(L);
if (top < 2) {
luaL_error(L, "Not enough arguments to tangible.start");
return 0;
}
int varlen = top - 2;
World *w = World::fetch_global_pointer(L); World *w = World::fetch_global_pointer(L);
w->guard_blockable(L, "tangible.start"); w->guard_blockable(L, "tangible.start");
LuaArg place, fname;
LuaExtraArgs extra;
LuaVar mt, classtab, plthreads, thread, thinfo, func, tanlist; LuaVar mt, classtab, plthreads, thread, thinfo, func, tanlist;
LuaDefStack LS(L, mt, classtab, plthreads, thread, thinfo, func, tanlist); LuaDefStack LS(L, place, fname, extra, mt, classtab, plthreads, thread, thinfo, func, tanlist);
LuaSpecial place(1);
LuaSpecial fname(2);
// If they passed in a single tangible, convert it to a tangible list. // If they passed in a single tangible, convert it to a tangible list.
int64_t place_id = LS.tanid(place); int64_t place_id = LS.tanid(place);
@@ -677,10 +670,10 @@ LuaDefine(tangible_start, "tangible,function,arg1,arg2...",
// Create a new thread, set up function and arguments. // Create a new thread, set up function and arguments.
lua_State *CO = LS.newthread(thread); lua_State *CO = LS.newthread(thread);
lua_pushvalue(L, func.index()); lua_pushvalue(L, func.index());
for (int i = 0; i < varlen; i++) { for (int i = 0; i < extra.size(); i++) {
lua_pushvalue(L, i + 3); lua_pushvalue(L, extra.index(i));
} }
lua_xmove(L, CO, varlen + 1); lua_xmove(L, CO, extra.size() + 1);
// Create the thread info table. // Create the thread info table.
LS.newtable(thinfo); LS.newtable(thinfo);

View File

@@ -310,10 +310,13 @@ int64_t World::connection_create() {
assert(stack_is_clear()); assert(stack_is_clear());
int64_t id = id_global_pool_.get_one(); int64_t id = id_global_pool_.get_one();
{ {
LuaVar database, classtab, mt, func; LuaVar database, classtab, config, mt, func;
LuaExtStack LS(state(), database, classtab, mt, func); LuaExtStack LS(state(), database, classtab, config, mt, func);
Tangible *tan = tangible_make(LS, database, id); Tangible *tan = tangible_make(LS, database, id);
// A blank config table to pass to 'init'
LS.newtable(config);
// Set the login flags. // Set the login flags.
if (is_authoritative()) { if (is_authoritative()) {
tan->client_id_ = id; tan->client_id_ = id;
@@ -327,7 +330,9 @@ int64_t World::connection_create() {
if (is_authoritative()) { if (is_authoritative()) {
LS.rawget(func, classtab, "init"); LS.rawget(func, classtab, "init");
spawn(LS, id, id, func, 0, false); lua_pushvalue(state(), database.index());
lua_pushvalue(state(), config.index());
spawn(LS, id, id, func, 2, false);
} }
} }
connections_.emplace(id, id); connections_.emplace(id, id);
@@ -977,13 +982,18 @@ void World::invoke_lua_source(int64_t actor_id, int64_t place_id, std::string_vi
if (errors.empty()) { if (errors.empty()) {
{ {
lua_State *L = state(); lua_State *L = state();
LuaVar lclass, lfunc; LuaVar lclass, lfunc, tangibles, actor, config;
LuaExtStack LS(L, lclass, lfunc); LuaExtStack LS(L, lclass, lfunc, tangibles, actor, config);
LS.rawget(tangibles, LuaRegistry, "tangibles");
LS.rawget(actor, tangibles, actor_id);
LS.newtable(config);
LS.getclass(lclass, "world"); LS.getclass(lclass, "world");
if (LS.classname(lclass) != "") { if (LS.classname(lclass) != "") {
LS.rawget(lfunc, lclass, "init"); LS.rawget(lfunc, lclass, "init");
spawn(LS, actor_id, place_id, lfunc, 0, false); lua_pushvalue(L, actor.index());
lua_pushvalue(L, config.index());
spawn(LS, actor_id, place_id, lfunc, 2, false);
} }
} }
run_scheduled_threads(); run_scheduled_threads();

View File

@@ -4,24 +4,94 @@ makeclass('probe')
makeclass('invoke') makeclass('invoke')
makeclass('cube') makeclass('cube')
makeclass('sphere') makeclass('sphere')
makeclass('pylon')
makeclass('roster')
function pretty(t, indent, seen)
indent = indent or 0
seen = seen or {}
if type(t) ~= "table" then return tostring(t) end
if seen[t] then return "<cycle>" end
seen[t] = true
local spacing = string.rep(" ", indent)
local out = "{\n"
for k, v in pairs(t) do
out = out .. spacing .. " [" .. tostring(k) .. "] = "
out = out .. pretty(v, indent + 1, seen) .. ",\n"
end
return out .. spacing .. "}"
end
-- tangible.redirect(actor1,actor2)
-- tangible.forcedisconnect(actor)
-- tangible.keepactor(actor) -- Do not autodelete upon disconnect
-- tangible.delete(actor) -- If actor is a connected player it will disconnect
-- This gets called on every login except the admin user. -- This gets called on every login except the admin user.
function login.init() function login.init(self, config)
local player = global.get("nextplayer") local player = global.get("nextplayer")
global.set("nextplayer", player + 1) global.set("nextplayer", player + 1)
dprint("login.init initializing player ", player) printf("login.init initializing %p, player %d", self, player)
actor.player = player self.player = player
tangible.keepactor(actor) -- do not delete this login when the client disconnects self.color={0,0,0,0,0,0,0,0,0,0,0,0}
tangible.animinit{tan=actor, anim={bp="character", mesh="manny", plane="earth", xyz={player * 100, 0, 90}}} self.kills=0
self.killed=0
tangible.animinit{tan=self, anim={bp="character", mesh="manny", plane="earth", xyz={player * 100, 0, 90}}}
tangible.start(self, login.startscanning)
end
function login.startscanning()
printf("Scanning started. Actor=%p Place=%p", actor, place)
while true do
login.onescan()
wait(1)
end
end
function login.onescan()
local nearby=tangible.find{plane=tangible.animfinal(actor).plane,center=tangible.animfinal(actor).xyz,radius=1000,shape="cylinder"}
for k,v in pairs(nearby) do
if classname(v)=="pylon" then actor.color[v.color]=time()+30 end
if classname(v)=="player" then
if actor.team==v.team then
for ck,cv in v.color do actor.color[ck]=math.max(actor.color[ck],cv) end
else
local score1=0
local score2=0
for ck,cv in actor.color do if time()-cv<0 then score1=score1+1 end end
for ck,cv in v.color do if time()-cv<0 then score2=score2+1 end end
if score1-score2>0 then
-- kill player 2
end
end
end
end
end end
-- This gets called on the admin user. You can call login.init in here if you want. -- This gets called on the admin user. You can call login.init in here if you want.
function world.init() function world.init(self, config)
dprint("world.init") print("world.init")
global.set("nextplayer", 0) global.set("nextplayer", 0)
tangible.build{class=roster, anim={plane="earth", xyz={2000,0,0} } }
tangible.build{class=cube, anim={plane="earth", xyz={500,-100,0}, mat_color={1,0,0}}} tangible.build{class=cube, anim={plane="earth", xyz={500,-100,0}, mat_color={1,0,0}}}
tangible.build{class=sphere, anim={plane="earth", xyz={500,100,0}, mat_color={0,0,1}}} tangible.build{class=sphere, anim={plane="earth", xyz={500,100,0}, mat_color={0,0,1}}}
login.init() login.init(self, config)
end
function roster.init(self,config)
self.character={}
end
function world.buildpylon()
print("Building pylon")
local radius=1000
tangible.build{class=pylon,plane="earth",xyz={math.random(-radius,radius),math.random(-radius,radius),0}}.color=math.random(1,12)
end end
function invoke.move(action, xyz, facing) function invoke.move(action, xyz, facing)
@@ -38,22 +108,63 @@ function login.lookmenu(add)
add("Redirect", function() tangible.redirect(actor, place) end) add("Redirect", function() tangible.redirect(actor, place) end)
end end
function cube.lookmenu(add) -- Four cases: Unnamed to new, Unnamed to existing, Named to new, Named to Existing
add("Cube A", function () dprint("Doing Cube A") end) function playas(who)
add("Cube B", function () dprint("Doing Cube B") end) printf("Playas %lP",place)
add("Cube C", function () dprint("Doing Cube C") end) if not actor.name and not place.character[who] then -- Unnamed to new
add("Cube Hi", function () dprint("Doing Cube Hi") end) printf("Case 1: Naming this character "..who)
add("Cube Bye", function () dprint("Doing Cube Bye") end) actor.name=who
add("Cube Yo", function () dprint("Doing Cube Yo") end) tangible.keepactor(actor)
add("Cube Z", function () dprint("Doing Cube Z") end) place.character[who]=actor
elseif actor.name and not place.character[who] then -- Named to new (Hard one)
printf("Case 2: Creating new character "..who)
printf("Case 2.0")
local nc=tangible.build{class=login, anim={plane="earth", xyz={0,0,0} } }
printf("Case 2.1")
nc.name=who
printf("Case 2.2")
tangible.keepactor(nc)
printf("Case 2.3")
place.character[who]=nc
printf("Case 2.4: ...Place is now "..place)
tangible.redirect(actor,nc)
elseif not actor.name and place.character[who] then
printf("Case 3: Logging in from unnamed to existing character "..who)
tangible.redirect(actor,place.character[who])
elseif actor.name and place.character[who] then
printf("Case 4: Logging in from "..actor.name.." to existing character "..who)
tangible.redirect(actor,place.character[who])
end
end end
function sphere.lookhotkeys(add) function roster.lookmenu(add)
add("FaceL", "Sphere Hi", function () dprint("Doing Sphere Hi") end) for _,name in ipairs { "Albert", "Betty", "Cornelius" } do
add("FaceM", "Sphere Bye", function () dprint("Doing Sphere Bye") end) add("Play as "..name..(place.character[name] and "" or "*"), function() playas(name) end)
add("FaceR", "Sphere Yo", function () dprint("Doing Sphere Yo") end) end
end end
function cube.lookmenu(add)
add("Cube A", function () print("Doing Cube A") end)
add("Cube B", function () print("Doing Cube B") end)
add("Cube C", function () print("Doing Cube C") end)
add("Cube Hi", function () print("Doing Cube Hi") end)
add("Cube Bye", function () print("Doing Cube Bye") end)
add("Cube Yo", function () print("Doing Cube Yo") end)
add("Cube Z", function () print("Doing Cube Z") end)
end
function sphere.lookhotkeys(add)
add("FaceL", "Sphere Hi", function () print("Doing Sphere Hi") end)
add("FaceM", "Sphere Bye", function () print("Doing Sphere Bye") end)
add("FaceR", "Sphere Yo", function () print("Doing Sphere Yo") end)
end
function sphere.tick(foo)
print("Tick")
end
function probe.getlookat() function probe.getlookat()
local class = tangible.getclass(place) local class = tangible.getclass(place)

View File