prototype

This commit is contained in:
GenZmeY 2022-09-02 15:54:10 +03:00
parent 5ba33cee19
commit a0fd4870fe
15 changed files with 379 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.psd
/ignore

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "tools"]
path = tools
url = https://github.com/GenZmeY/KF2-BuildTools

View File

@ -0,0 +1,8 @@
[h1]KF2-SafeMutLoader[/h1]
[h1]Description[/h1]
[b]Mutator(s):[/b] SML.Mut
[h1]Author[/h1]
[url=https://github.com/GenZmeY]GenZmeY[/url]

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View File

@ -0,0 +1 @@
Mutators

View File

@ -0,0 +1 @@
KF2-SafeMutLoader

110
SML/Classes/Mut.uc Normal file
View File

@ -0,0 +1,110 @@
class Mut extends KFMutator;
const SML = class'SafeMutLoader';
const OptAC = "AccessControl";
const OptMut = "Mutator";
var private E_LogLevel LogLevel;
public function PreBeginPlay()
{
Super.PreBeginPlay();
LogLevel = SML.default.LogLevel;
if (LogLevel == LL_WrongLevel)
{
LogLevel = LL_Info;
}
`Log_Trace();
if (CorrectLoadOrder())
{
ModifyLoad();
}
else
{
`Log_Fatal(SML.static.GetName(Self) @ "must be loaded first.");
}
}
public function AddMutator(Mutator Mut)
{
`Log_Trace();
if (CorrectLoadOrder() || Mut == Self) return;
if (Mut.Class == Class)
Mut.Destroy();
else
Super.AddMutator(Mut);
}
private function bool CorrectLoadOrder()
{
`Log_Trace();
return (
WorldInfo.Game.BaseMutator == None ||
WorldInfo.Game.BaseMutator == Self);
}
private function ModifyLoad()
{
local String LoadURL;
local String LoadParams;
local String MutatorsRaw;
local String AccessControlRaw;
local Array<String> Mutators;
local int Index;
`Log_Trace();
LoadURL = WorldInfo.GetLocalURL();
LoadParams = Mid(LoadURL, InStr(LoadURL, "?"));
MutatorsRaw = WorldInfo.Game.ParseOption(LoadParams, OptMut);
AccessControlRaw = WorldInfo.Game.ParseOption(LoadParams, OptAC);
LoadURL = Repl(LoadURL, Subst(OptMut) $ MutatorsRaw, "");
LoadURL = Repl(LoadURL, Subst(OptAC) $ AccessControlRaw, "");
SML.static.ClearMutators();
ParseStringIntoArray(MutatorsRaw, Mutators, ",", true);
Index = 0;
while (Index < Mutators.Length)
{
if (SML.static.AddMutator(Mutators[Index]) ||
Mutators[Index] ~= SML.static.GetName(Self))
{
Mutators.Remove(Index, 1);
}
else
{
++Index;
}
}
JoinArray(Mutators, MutatorsRaw);
LoadURL $= (Subst(OptMut) $ MutatorsRaw);
if (SML.static.WantsToSpawn())
{
SML.static.StaticSaveConfig();
LoadURL $= (Subst(OptAC) $ SML.static.GetName());
}
`Log_Info("Loader modified, do server travel...");
WorldInfo.ServerTravel(LoadURL, true);
}
private static function String Subst(String Option)
{
return ("?" $ Option $ "=");
}
defaultproperties
{
}

View File

@ -0,0 +1,148 @@
class SafeMutLoader extends KFAccessControl
config(SML);
var private Array<Actor> ServerActors;
var public config E_LogLevel LogLevel;
var private config Array<String> Mutators;
public function PreBeginPlay()
{
`Log_Trace();
if (LogLevel == LL_WrongLevel)
{
LogLevel = LL_Info;
StaticSaveConfig();
}
LoadActors();
Super.PreBeginPlay();
}
private function LoadActors()
{
local String MutString;
local class<Mutator> MutClass;
local class<Actor> ActClass;
local Actor ServerActor;
`Log_Trace();
foreach Mutators(MutString)
{
MutClass = class<Mutator>(DynamicLoadObject(MutString, class'Class'));
if (MutClass == None)
{
`Log_Error("Can't load mutator:" @ MutString);
continue;
}
ActClass = GetMutReplacement(MutClass);
if (ActClass == None)
{
`Log_Warn("Incompatible:" @ MutString @ "(skip)");
continue;
}
ServerActor = WorldInfo.Spawn(ActClass);
if (ServerActor == None)
{
`Log_Error("Can't spawn:" @ MutString);
continue;
}
ServerActors.AddItem(ServerActor);
`Log_Info("Loaded:" @ MutString);
}
}
public static function bool AddMutator(String MutString)
{
if (GetMutStringReplacement(MutString) != None)
{
if (default.Mutators.Find(MutString) == INDEX_NONE)
{
default.Mutators.AddItem(MutString);
}
return true;
}
return false;
}
public static function ClearMutators()
{
default.Mutators.Length = 0;
}
public static function bool WantsToSpawn()
{
return (default.Mutators.Length > 0);
}
public static function String GetName(optional Object O)
{
if (O == None)
{
return (default.class.GetPackageName() $ "." $ String(default.class));
}
else
{
return (O.class.GetPackageName() $ "." $ String(O.class));
}
}
public function PostLogin(PlayerController C)
{
local Actor A;
`Log_Trace();
if (C != None)
{
foreach ServerActors(A)
{
A.GetTargetLocation(C, false);
}
}
Super.PostLogin(C);
}
public function OnClientConnectionClose(Player ClientConnection)
{
local Controller C;
local Actor A;
`Log_Trace();
C = ClientConnection.Actor;
if (C != None)
{
foreach ServerActors(A)
{
A.GetTargetLocation(C, true);
}
}
Super.OnClientConnectionClose(ClientConnection);
}
private static function class<Actor> GetMutReplacement(class<Mutator> MutClass)
{
if (MutClass == None || MutClass.static.GetLocalString() == "") return None;
return class<Actor>(DynamicLoadObject(
MutClass.GetPackageName() $ "." $
MutClass.static.GetLocalString(), class'Class'));
}
private static function class<Actor> GetMutStringReplacement(String MutString)
{
return GetMutReplacement(class<Mutator>(DynamicLoadObject(MutString, class'Class')));
}
defaultproperties
{
}

View File

@ -0,0 +1,4 @@
[Flags]
AllowDownload=False
ClientOptional=False
ServerSideOnly=True

20
SML/Classes/_Logger.uc Normal file
View File

@ -0,0 +1,20 @@
class _Logger extends Object
abstract;
enum E_LogLevel
{
LL_WrongLevel,
LL_None,
LL_Fatal,
LL_Error,
LL_Warning,
LL_Info,
LL_Debug,
LL_Trace,
LL_All
};
defaultproperties
{
}

2
SML/Constants.uci Normal file
View File

@ -0,0 +1,2 @@
// Constants
`define NO_CONFIG 0

3
SML/Globals.uci Normal file
View File

@ -0,0 +1,3 @@
// Imports
`include(Logger.uci)
`include(Constants.uci)

15
SML/Logger.uci Normal file
View File

@ -0,0 +1,15 @@
// Logger
`define Log_Tag 'SML'
`define LocationStatic "`{ClassName}::" $ GetFuncName()
`define Log_Base(msg, cond) `log(`msg `if(`cond), `cond`{endif}, `Log_Tag)
`define Log_Fatal(msg) `log("FATAL:" @ `msg, (LogLevel >= LL_Fatal), `Log_Tag)
`define Log_Error(msg) `log("ERROR:" @ `msg, (LogLevel >= LL_Error), `Log_Tag)
`define Log_Warn(msg) `log("WARN:" @ `msg, (LogLevel >= LL_Warning), `Log_Tag)
`define Log_Info(msg) `log("INFO:" @ `msg, (LogLevel >= LL_Info), `Log_Tag)
`define Log_Debug(msg) `log("DEBUG:" @ `msg, (LogLevel >= LL_Debug), `Log_Tag)
`define Log_Trace(msg) `log("TRACE:" @ `Location `if(`msg) @ `msg`{endif}, (LogLevel >= LL_Trace), `Log_Tag)
`define Log_TraceStatic(msg) `log("TRACE:" @ `LocationStatic `if(`msg) @ `msg`{endif}, (LogLevel >= LL_Trace), `Log_Tag)

61
builder.cfg Normal file
View File

@ -0,0 +1,61 @@
### Build parameters ###
# If True - compresses the mutator when compiling
# Scripts will be stored in binary form
# (reduces the size of the output file)
StripSource="True"
# Mutators to be compiled
# Specify them with a space as a separator,
# Mutators will be compiled in the specified order
PackageBuildOrder="SML"
### Brew parameters ###
# Packages you want to brew using @peelz's patched KFEditor.
# Useful for cases where regular brew doesn't put *.upk inside the package.
# Specify them with a space as a separator,
# The order doesn't matter
PackagePeelzBrew=""
### Steam Workshop upload parameters ###
# Mutators that will be uploaded to the workshop
# Specify them with a space as a separator,
# The order doesn't matter
PackageUpload="SML"
### Test parameters ###
# Map:
Map="KF-Nuked"
# Game:
# Survival: KFGameContent.KFGameInfo_Survival
# WeeklyOutbreak: KFGameContent.KFGameInfo_WeeklySurvival
# Endless: KFGameContent.KFGameInfo_Endless
# Objective: KFGameContent.KFGameInfo_Objective
# Versus: KFGameContent.KFGameInfo_VersusSurvival
Game="KFGameContent.KFGameInfo_Survival"
# Difficulty:
# Normal: 0
# Hard: 1
# Suicide: 2
# Hell: 3
Difficulty="0"
# GameLength:
# 4 waves: 0
# 7 waves: 1
# 10 waves: 2
GameLength="0"
# Mutators
Mutators="SML.Mut"
# Additional parameters
Args=""

1
tools Submodule

@ -0,0 +1 @@
Subproject commit 3efdb9f4d13cb730264cf17498ed1e1ee908934c