| Version: | 2.3.1 |
|---|---|
| Home page: | https://github.com/sergeii/swat-julia |
| Author: | Sergei Khoroshilov <[email protected]> |
| License: | The MIT License (http://opensource.org/licenses/MIT) |
Julia is a simple yet powerful UnrealScript framework that helps you to develop SWAT 4 mods easily.
- Utils >=1.0.0
Cache is a temporary data manager that makes cached data to persist through levels.
Cache exposes very simple public API:
SetValue
public function SetValue(string Key, string Value) Store a value ``Value`` under a key ``Key``.
SetArray
public function SetArray(string Key, array<string> Array) Store an array of values ``Array`` under same key ``Key``.
GetValue
public function string GetValue(string Key) Return value of the first entry matching key ``Key``.
GetArray
public function array<string> GetArray(string Key) Return an array of values stored under the same key ``Key``.
To obtain the Cache instance you must invoke GetCache() on the Core object:
local Julia.Cache Cache;
local string Value;
// Obtain the Cache instance
Cache = self.Core.GetCache();
// Retrieve a value
Value = Cache.GetValue("foo");
// Set a value
if (Value == "")
{
Cache.SetValue("foo", "bar");
}
By default all cache entries are stored for 86400 seconds (24 hours).
To configure global cache expiration time alter the TTL value of the [Julia.Cache] section in Swat4DedicatedServer.ini:
[Julia.Cache] TTL=300
Dispatcher is a Core asset that provides an ability to register client commands. A client command is a typical chat/teamchat message that begins with a ! (exclamation sign). The builtin commands !version and !help serve as an example to the dispatcher protocol.
To register a command you have to the following:
Implement the
Julia.InterestedInCommandDispatchedinterface:class MyExtension extends Julia.Extension implements InterestedInCommandDispatched; public function OnCommandDispatched(Julia.Dispatcher Dispatcher, string Name, string Id, array<string> Args, Julia.Player Player) { // Handle dispatched commands }Obtain the
Dispatcherinstance invokingGetDispatcher()on theCoreobject:local Julia.Dispatcher Dispatcher; Dispatcher = self.Core.GetDispatcher();
Register commands:
Dispatcher.Bind("mycommand", self, "!mycommand argument1 argument2", "This command does something"); Dispatcher.Bind("myothercommand", self, "!myothercommand argument", "This command does something as well");Unregister commands before the object gets dealloacated:
Dispatcher.Unbind("mycommand", self); Dispatcher.Unbind("myothercommand", self);or
Dispatcher.UnbindAll(self);
to unregister all commands that have been tied to a particular instance.
Once a client command is dispatched, the dispatcher expects a response from the instance that has pledged to handle the command. Dispatcher provides a plain and simple public API for handling command output:
Dispatcher.Respond
public function Respond(string Id, string Response)
Dispatcher.ThrowError
public function ThrowError(string Id, string Error)
Dispatcher.ThrowUsageError
public function ThrowUsageError(string Id)
Dispatcher.ThrowPermissionError
public function ThrowPermissionError(string Id)
All of the response methods expect an Id argument. Id is a unique command identifier that is generated upon the moment a client command is placed into the dispatcher queue.
Suppose you wanted to implement !time and !date that would display the current server time and date respectively:
class MyExtension extends Julia.Extension implements InterestedInCommandDispatched;
function BeginPlay()
{
Super.BeginPlay();
// register self as the "time" command handler
// providing dispatcher with detailed usage information
self.Core.GetDispatcher().Bind("time", self, "!time", "Displays the current server time.");
self.Core.GetDispatcher().Bind("date", self, "!date", "Displays the current server date.");
}
public function OnCommandDispatched(Julia.Dispatcher Dispatcher, string Name, string Id, array<string> Args, Julia.Player Player)
{
local string TimeFormatted, DateFormatted, Response;
// A command handler is always passed the lowercase version of a registered command
switch (Name)
{
case "time":
// Display HH:MM time (eg. 19:47)
TimeFormatted = class'Utils.LevelUtils'.static.FormatTime(
class'Utils.LevelUtils'.sttaic.GetTime(self.Level),
"%H:%M"
);
Response = "Current server time is " $ TimeFormatted;
break;
case "date":
DateFormatted = class'Utils.LevelUtils'.static.FormatTime(
class'Utils.LevelUtils'.sttaic.GetTime(self.Level),
"%Y:%m:%d"
);
Response = "Current server date is " $ DateFormatted;
break;
}
Dispatcher.Respond(Id, Response);
}
event Destroyed()
{
self.Core.GetDispatcher().UnbindAll(self);
Super.Destroyed();
}
In case a designated handler does not respond in a reasonable amount of time (defined with the constant COMMAND_TIMEOUT in Dispatcher.uc), the dispatcher removes the dispatched command from its queue.
Julia provides a rich set of subscribable event handlers
OnEventBroadcast
OnEventBroadcastevent manager provides an ability to subscribe to all types of broadcast events emitted everywhere across the native and custom game code, be itSayorAdminMsg.interface InterestedInEventBroadcast; public function bool OnEventBroadcast(Julia.Player Player, Actor Sender, name Type, out string Msg, optional PlayerController Receiver, optional bool bHidden);
Playeris a reference to theJulia.Playerplayer controller of the original event broadcaster (where applicable).Senderis a reference to the original event broadcaster.Typeis an event type such asSayorTeamSaywhich may be any of the followingAllBombsDisarmed BanReferendumStarted BombExploded Caption CommandGiven Connected CoopLeaderPromoted CoopMessage CoopQMM DebugMessage DisarmBomb EquipNotAvailable GameTied Kick KickBan KickReferendumStarted LeaderReferendumStarted LeaderVoteTeamMismatch MapReferendumStarted MissionCompleted MissionEnded MissionFailed NameChange NoVote ObjectiveShown OneMinWarning PlayerConnect PlayerDisconnect PlayerImmuneFromReferendum PreGameWait ReferendumAgainstAdmin ReferendumAlreadyActive ReferendumFailed ReferendumsDisabled ReferendumStartCooldown ReferendumSucceeded Say SettingsUpdated SmashAndGrabArrestTimeDeduction SmashAndGrabDroppedItem SmashAndGrabGotItem SniperAlerted Stats StatsBadProfileMessage StatsValidatedMessage SuspectsArrest SuspectsKill SuspectsRespawnEvent SuspectsSuicide SuspectsTeamKill SuspectsWin SuspectsWinSmashAndGrab SwatArrest SwatKill SwatRespawnEvent SwatSuicide SwatTeamKill SwatWin SwatWinSmashAndGrab SwitchTeams TeamSay TenSecWarning ViewingFromEvent ViewingFromNoneEvent ViewingFromVIPEvent VIPCaptured VIPRescued VIPSafe WinSuspectsBadKill WinSuspectsGoodKill WinSwatBadKill YesVote YouAreVIP
Msgis an optional event message, which may be altered before displaying in chat (out).Receiveris a broadcast target reference (optional).bHiddenindicates whether the event has been hidden by any of the registered Julia extensions (optional).
An implemented
OnEventBroadcastmethod must returntrueif the extension does not wish to stop a particular event from broadcasting, orfalseif it does not wish to interfere with the event visibility at all.Consider the following example of an extension that has a sole purpose to stop player messages containing the word "foo" from appearing in chat:
class MySillyExtension extends Julia.Extension implements Julia.InterestedInEventBroadcast; public function BeginPlay() { Super.BeginPlay(); // Register MySillyExtension with the Julia event handler self.Core.RegisterInterestedInEventBroadcast(self); } public function bool OnEventBroadcast(Julia.Player Player, Actor Sender, name Type, out string Msg, optional PlayerController Receiver, optional bool bHidden) { // This event has already been marked hidden by some other Julia extension if (bHidden) { return true; } // Not interested in this event type if (Player == None || !(Type == 'Say' || Type == 'TeamSay')) { return true; } // Dont allow the word "foo" to appear anywhere in chat if (class'Utils.StringUtils'.static.Match(Msg, "*foo*")) { return false; } return true; } event Destroyed() { if (self.Core != None) { // Unregister MySillyExtension before deallocating self.Core.UnregisterInterestedInEventBroadcast(self); } Super.Destroyed(); }OnInternalEventBroadcast
OnInternalEventBroadcastallows you to subscribe to the Julia's internal events such asPlayerHitorPlayerArrest.interface InterestedInInternalEventBroadcast; public function OnInternalEventBroadcast(name Type, optional string Msg, optional Player PlayerOne, optional Player PlayerTwo);
Typeis an event type that may be any of the followingEnemyHostageIncap EnemyHostageKill EnemyPlayerKill PlayerArrest PlayerEnemyHit PlayerEnemyIncap PlayerEnemyIncapInvalid PlayerEnemyKill PlayerEnemyKillInvalid PlayerHit PlayerHit PlayerHostageHit PlayerHostageIncap PlayerHostageKill PlayerKill PlayerReport PlayerSelfHit PlayerSelfHit PlayerSuicide PlayerTeamHit PlayerTeamHit PlayerTeamKill
Msgis an optional event message that holds weapon friendly name (where applicable). (optional)PlayerOne,PlayerTwohold reference to players affected by the event (where applicable) (optional)
OnGameStateChanged
OnGameStateChangedwill fire whenether a game changes its state.interface InterestedInGameStateChanged; public function OnGameStateChanged(eSwatGameState OldState, eSwatGameState NewState);
OldStateis the previous game state code.NewStateis the current game state code.
Both the
OldStateandNewStatearguments may be any of the following:GAMESTATE_None // Not in game at all, GUI only GAMESTATE_EntryLoading // Currently loading the entry level GAMESTATE_LevelLoading // Currently loading a (non-entry) level GAMESTATE_PreGame // Level has loaded but round not yet begun GAMESTATE_MidGame // Game in progress GAMESTATE_PostGame // Level completed GAMESTATE_ClientTravel // Client is travelling to the new map on the server GAMESTATE_ConnectionFailed // Client failed to connect to the server (remote OR local)
OnMissionStarted
OnMissionEnded
OnMissionStarted,OnMissionEndedare convenient wrappers aroundOnGameStateChangedthat will fire whenever a game changes its state fromGAMESTATE_PreGametoGAMESTATE_MidGameor fromGAMESTATE_MidGametoGAMESTATE_PostGamerespectively.interface InterestedInMissionStarted; public function OnMissionStarted();
interface InterestedInMissionEnded; public function OnMissionEnded();
OnPlayerConnected
OnPlayerConnectedwill be invoked upon player connection.interface InterestedInPlayerConnected; public function OnPlayerConnected(Julia.Player Player);
OnPlayerDisconnected
OnPlayerDisconnectedwill be invoked upon player disconnection.interface InterestedInPlayerDisconnected; public function OnPlayerDisconnected(Julia.Player Player);
OnPlayerAdminLogged
OnPlayerAdminLoggedwill fire whenever a player logs in with admin password.interface InterestedInPlayerAdminLogged; public function OnPlayerAdminLogged(Julia.Player Player);
OnPlayerLoaded
OnPlayerLoadedwill fire upon the moment a player gets all of the local content loaded (i.e. she is able to see chat and scoreboard).interface InterestedInPlayerLoaded; public function OnPlayerLoaded(Player Player);
OnPlayerNameChanged
OnPlayerNameChangedis fired upon a player name change.interface InterestedInPlayerNameChanged; public function OnPlayerNameChanged(Julia.Player Player, string OldName);
OldNameholds the previous player name. The current name can be retrieved with aPlayer.GetNamemethod call.
OnPlayerTeamSwitched
OnPlayerTeamSwitchedwill be fired whenever a player changes their team.interface InterestedInPlayerTeamSwitched; public function OnPlayerTeamSwitched(Julia.Player Player);
OnPlayerVIPSet
OnPlayerVIPSetis fired upon the moment a player is assigned to be the VIP.interface InterestedInPlayerVIPSet; public function OnPlayerVIPSet(Player Player);
OnPlayerPawnChanged
OnPlayerPawnChangedwill fire upon a player Pawn change.interface InterestedInPlayerPawnChanged; public function OnPlayerPawnChanged(Julia.Player Player);
OnPlayerVoiceChanged
OnPlayerVoiceChangedwill fire whenever a player changes their voice type.interface InterestedInPlayerVoiceChanged; public function OnPlayerVoiceChanged(Julia.Player Player);
In order to subscribe to a specific event handler you must call RegisterInterestedIn%EventType% on an instance of Julia.Core providing it with an instance of a class that implements an assotitated InterestedIn%EventType% interface.
Suppose you had to listen to all OnGameStateChanged events. To do so you would do the following:
Subclass
Julia.Extensionand implement theJulia.InterestedInGameStateChangedinterfaceclass MyExtension extends Julia.Extension implements Julia.InterestedInGameStateChanged; import enum eSwatGameState from SwatGame.SwatGUIConfig; public function OnGameStateChanged(eSwatGameState OldState, eSwatGameState NewState) { log("old state: " $ OldState $ " | new state: " $ NewState); }Register instances of the extension class with the event handler at
Julia.Coreavailable in yourJulia.Extensionderived class asself.Corefunction BeginPlay() { Super.BeginPlay(); self.Core.RegisterInterestedInGameStateChanged(self); }Make sure to unregister from the event handler just before object destruction
event Destroyed { self.Core.UnregisterInterestedInGameStateChanged(self); Super.Destroyed(); }
The framework supports the following Swat4DedicatedServer.ini options:
| Property | Descripion | Options | Default |
|---|---|---|---|
| Enabled | Enables the framework core and all of the Julia.Extension derived extensions. |
True/False | False |
| Property | Descripion | Options | Default |
|---|---|---|---|
| TTL | Cache entry expiration time (in seconds) | Positive integer | 86400 |