Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
Iterate to next node in Rotation OnMapEnd;  this will fix a bug where
the first node is skipped
remove cache and history pruning logic out of Iterate;  move to
OnMapStart
Iterate and pruning logic do not get called if NextMapIsForced
  • Loading branch information
CrimsonTautology committed Mar 12, 2021
1 parent 057788d commit 7bbb97e
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 64 deletions.
41 changes: 21 additions & 20 deletions addons/sourcemod/scripting/dmr/rotation.sp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ methodmap Rotation < DMRKeyValues
return this.GetValueOfKeyOfNode(node, "title", value, length);
}

// get the map of the given node if it exists
// return false if node does not have a map or if node does not exist
public bool GetMap(const char[] node, char[] value, int length)
{
return this.GetValueOfKeyOfNode(node, "map", value, length);
}

// get the group of the given node if it exists
// return false if node does not have a group or if node does not exist
public bool GetGroup(const char[] node, char[] value, int length)
{
return this.GetValueOfKeyOfNode(node, "group", value, length);
}

// execute the value of a given command_key as if it were a server command
// return false if node does not have the given command_key or if node does
// not exist
Expand Down Expand Up @@ -103,7 +117,7 @@ methodmap Rotation < DMRKeyValues

// given a node, determine the nextnode in the rotation we should jump to
// return false if the current node does not have a nextnode
public bool GetNextNode(const char[] node, char[] nextnode, int length)
public bool DetermineNextNode(const char[] node, char[] nextnode, int length)
{
// save a copy of node in case we overwrite it
char currentnode[MAX_KEY_LENGTH];
Expand Down Expand Up @@ -142,11 +156,11 @@ methodmap Rotation < DMRKeyValues
// be an actual map in the "map" key or it may be a random map from a map
// group specified by the "group" key
// return false if a map cannot be determined
public bool GetMap(const char[] node, char[] map, int length, MapGroups groups=null,
public bool DetermineMap(const char[] node, char[] map, int length, MapGroups groups=null,
StringMap cache=null, MapHistory history=null)
{
// simply return the map value if it exists
if (this.GetValueOfKeyOfNode(node, "map", map, length))
if (this.GetMap(node, map, length))
{
return true;
}
Expand All @@ -169,22 +183,10 @@ methodmap Rotation < DMRKeyValues
// updates the node and map fields to the nextnode and nextmap
// return false if we are unable to iterate
public bool Iterate(char[] node, int nlength, char[] map, int mlength, MapGroups groups=null,
StringMap cache=null, MapHistory history=null, int history_limit=-1)
StringMap cache=null, MapHistory history=null)
{
char group[MAX_KEY_LENGTH];

if (!this.GetNextNode(node, node, nlength)) return false;
if (!this.GetMap(node, map, mlength, groups, cache, history)) return false;

// add this map to our history
if (history != null) history.PushMap(map, history_limit);

// remove current group from cache
if (cache != null && groups != null &&
this.GetValueOfKeyOfNode(node, "group", group, sizeof(group)))
{
cache.Remove(group);
}
if (!this.DetermineNextNode(node, node, nlength)) return false;
if (!this.DetermineMap(node, map, mlength, groups, cache, history)) return false;

return true;
}
Expand Down Expand Up @@ -217,8 +219,7 @@ methodmap Rotation < DMRKeyValues
// impossible to know what the random map will be past the first
// iteration. Instead we simply display the map group past the
// first iteration.
has_group = this.GetValueOfKeyOfNode(currentnode, "group", group,
sizeof(group));
has_group = this.GetGroup(currentnode, group, sizeof(group));
if (has_group)
{
if (visited_groups.GetValue(group, junk))
Expand Down
72 changes: 47 additions & 25 deletions addons/sourcemod/scripting/dmr_plus.sp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

#include <sourcemod>

#define PLUGIN_VERSION "1.10.0"
#define PLUGIN_VERSION "1.10.1"
#define PLUGIN_NAME "Dynamic Map Rotations Plus"

public Plugin myinfo =
Expand Down Expand Up @@ -43,7 +43,7 @@ MapGroups g_MapGroups;
MapHistory g_MapHistory;
StringMap g_CachedRandomMapTrie;

bool g_ForceNextMap = false;
bool g_NextMapIsForced = false;

char g_Node[MAX_KEY_LENGTH];

Expand Down Expand Up @@ -96,19 +96,23 @@ public void OnPluginStart()

public void OnMapStart()
{
char currentmap[MAX_KEY_LENGTH];
char currentmap[MAX_KEY_LENGTH], currentgroup[MAX_KEY_LENGTH];

if (!ForcedNextMap())
if (!NextMapIsForced())
{
// iterate to the next node in our rotation
g_Rotation.Iterate(
g_Node, sizeof(g_Node), currentmap, sizeof(currentmap),
g_MapGroups, g_CachedRandomMapTrie, g_MapHistory,
g_ExcludeMapsCvar.IntValue);
// add this map to our history
GetCurrentMap(currentmap, sizeof(currentmap));
g_MapHistory.PushMap(currentmap, g_ExcludeMapsCvar.IntValue);

// if current node holds a map group; clear it from the cache
if (g_Rotation.GetGroup(g_Node, currentgroup, sizeof(currentgroup)))
{
g_CachedRandomMapTrie.Remove(currentgroup);
}
}

// reset globals
g_ForceNextMap = false;
g_NextMapIsForced = false;

// set up repeating timer
CreateTimer(60.0, Timer_UpdateNextMap, .flags = TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
Expand All @@ -120,6 +124,20 @@ public void OnMapStart()
g_Rotation.RunNodePreCommand(g_Node);
}

public void OnMapEnd()
{
// needed for Iterate, not actually used
char nextmap[MAX_KEY_LENGTH];

if (!NextMapIsForced())
{
// iterate to the next node in our rotation
g_Rotation.Iterate(
g_Node, sizeof(g_Node), nextmap, sizeof(nextmap),
g_MapGroups, g_CachedRandomMapTrie, g_MapHistory);
}
}

public void OnAutoConfigsBuffered()
{
g_Rotation.RunNodeCommand(g_Node);
Expand Down Expand Up @@ -173,22 +191,22 @@ Action Command_SetNextmap(int client, int args)

ShowActivity(client, "%t", "Cvar changed", "sm_nextmap", map);

g_ForceNextMap = true;
g_NextMapIsForced = true;
SetNextMap(map);

return Plugin_Handled;
}

Action Command_UnsetNextmap(int client, int args)
{
if (!ForcedNextMap())
if (!NextMapIsForced())
{
ReplyToCommand(client, "[DMR] There was no forced nextmap to unset");

}
else
{
g_ForceNextMap = false;
g_NextMapIsForced = false;
UpdateNextMap();
ReplyToCommand(client, "[DMR] Forced nextmap unset");
}
Expand Down Expand Up @@ -237,7 +255,7 @@ Action Command_ValidateDMR(int client, int args)
Action Timer_UpdateNextMap(Handle timer)
{
// skip this we have forced the next map
if (ForcedNextMap()) return Plugin_Continue;
if (NextMapIsForced()) return Plugin_Continue;

UpdateNextMap();

Expand Down Expand Up @@ -332,18 +350,22 @@ void ValidateDMR()

void UpdateNextMap()
{
char nextmap[MAX_KEY_LENGTH], nextnode[MAX_KEY_LENGTH];

g_Rotation.GetNextNode(g_Node, nextnode, sizeof(nextnode));
g_Rotation.GetMap(nextnode, nextmap, sizeof(nextmap), g_MapGroups,
g_CachedRandomMapTrie, g_MapHistory);

SetNextMap(nextmap);
char nextnode[MAX_KEY_LENGTH], nextmap[MAX_KEY_LENGTH];
strcopy(nextnode, sizeof(nextnode), g_Node);

// iterate to the next node in our rotation with current server conditions
// and update the nextmap
if(g_Rotation.Iterate(
nextnode, sizeof(nextnode), nextmap, sizeof(nextmap), g_MapGroups,
g_CachedRandomMapTrie, g_MapHistory))
{
SetNextMap(nextmap);
}
}

bool ForcedNextMap()
bool NextMapIsForced()
{
return g_ForceNextMap;
return g_NextMapIsForced;
}

void PrintNextItems(int amount=7, bool as_nodes=false, bool show_title=true)
Expand All @@ -357,7 +379,7 @@ void PrintNextItems(int amount=7, bool as_nodes=false, bool show_title=true)
Format(nextmaps, sizeof(nextmaps), as_nodes ? "Next Nodes:" : "Next Maps:");

// prepend nexmap if we set a forced nextmap
if (ForcedNextMap())
if (NextMapIsForced())
{
GetNextMap(map, sizeof(map));
Format(nextmaps, sizeof(nextmaps), "%s %s", nextmaps, map);
Expand All @@ -366,7 +388,7 @@ void PrintNextItems(int amount=7, bool as_nodes=false, bool show_title=true)
for (int i = 0; i < maps.Length; i++)
{
maps.GetString(i, map, sizeof(map));
if (i > 0 || ForcedNextMap())
if (i > 0 || NextMapIsForced())
{
Format(nextmaps, sizeof(nextmaps), "%s, %s", nextmaps, map);
}
Expand Down
39 changes: 20 additions & 19 deletions addons/sourcemod/scripting/testsuite/test_dmr.sp
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,17 @@ void test_dmr_rotation()
Test_AssertStringsEqual("GetStartNode is node_a", "node_a", node)

// expect that we can iterate on default_node
rotation.GetNextNode("node_a", node, sizeof(node));
Test_AssertStringsEqual("GetNextNode node_a -> node_b", "node_b", node);
rotation.DetermineNextNode("node_a", node, sizeof(node));
Test_AssertStringsEqual("DetermineNextNode node_a -> node_b", "node_b", node);

rotation.GetNextNode("node_b", node, sizeof(node));
Test_AssertStringsEqual("GetNextNode node_b -> node_c", "node_c", node);
rotation.DetermineNextNode("node_b", node, sizeof(node));
Test_AssertStringsEqual("DetermineNextNode node_b -> node_c", "node_c", node);

rotation.GetNextNode("node_c", node, sizeof(node));
Test_AssertStringsEqual("GetNextNode node_c -> node_a", "node_a", node);
rotation.DetermineNextNode("node_c", node, sizeof(node));
Test_AssertStringsEqual("DetermineNextNode node_c -> node_a", "node_a", node);

rotation.GetNextNode("node_d", node, sizeof(node));
Test_AssertStringsEqual("GetNextNode node_d -> node_d", "node_d", node);
rotation.DetermineNextNode("node_d", node, sizeof(node));
Test_AssertStringsEqual("DetermineNextNode node_d -> node_d", "node_d", node);

// expect that we can retrieve values of specific keys of a given node
exists = rotation.GetValueOfKeyOfNode("node_a", "test_key", val, sizeof(val));
Expand Down Expand Up @@ -125,6 +125,12 @@ void test_dmr_rotation()
// expect that we can get the map of a node (without a map groups structure)
rotation.GetMap("node_a", val, sizeof(val));
Test_AssertStringsEqual("GetMap cp_map_a1", "cp_map_a1", val);
rotation.DetermineMap("node_a", val, sizeof(val));
Test_AssertStringsEqual("DetermineMap cp_map_a1", "cp_map_a1", val);

// expect that we can get the group of a node (without a map groups structure)
rotation.GetGroup("node_c", val, sizeof(val));
Test_AssertStringsEqual("GetGroup single", "single", val);

delete rotation;
}
Expand Down Expand Up @@ -183,26 +189,21 @@ void test_dmr_integration() {
// iterate over the rotation
rotation.GetStartNode(node, sizeof(node));

rotation.Iterate(node, sizeof(node), map, sizeof(map), groups, cache, history, 10)
rotation.Iterate(node, sizeof(node), map, sizeof(map), groups, cache, history)
Test_AssertStringsEqual("iterate rotation on node node_b", "node_b", node);
Test_AssertStringsEqual("iterate rotation on map tp_map_b2", "tp_map_b2", map);

rotation.Iterate(node, sizeof(node), map, sizeof(map), groups, cache, history, 10)
rotation.Iterate(node, sizeof(node), map, sizeof(map), groups, cache, history)
Test_AssertStringsEqual("iterate rotation on node node_c", "node_c", node);
Test_AssertStringsEqual("iterate rotation on map pl_single", "pl_single", map);

rotation.Iterate(node, sizeof(node), map, sizeof(map), groups, cache, history, 10)
rotation.Iterate(node, sizeof(node), map, sizeof(map), groups, cache, history)
Test_AssertStringsEqual("iterate rotation on node node_a", "node_a", node);
Test_AssertStringsEqual("iterate rotation on map cp_map_a1", "cp_map_a1", map);

// expect history to be updated
Test_AssertEqual("iteration updated history 3", history.Length, 3);

// test a dry run iteration that will not update history
rotation.Iterate(node, sizeof(node), map, sizeof(map), groups)
Test_AssertStringsEqual("dry iterate rotation on node node_b", "node_b", node);
Test_AssertStringsEqual("dry iterate rotation on map tp_map_b2", "tp_map_b2", map);
Test_AssertEqual("dry iteration did not update history 3", 3, history.Length);
// test the random map cache worked
Test_AssertTrue("single was added to the cache", cache.GetString("single", map, sizeof(map)))
Test_AssertStringsEqual("pl_single was added under the single group", "pl_single", map);

// test GetNextItems as maps
items = rotation.GetNextItems("node_a", 10, groups, cache);
Expand Down

0 comments on commit 7bbb97e

Please sign in to comment.