Skip to content

Commit 8dee45b

Browse files
committed
Feat: Map rotation includes current and next map index
1 parent b61b1d7 commit 8dee45b

File tree

10 files changed

+73
-27
lines changed

10 files changed

+73
-27
lines changed

rcon/commands.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from rcon.connection import HLLCommandError, HLLConnection, Handle, Response
1010
from rcon.maps import LAYERS, MAPS, UNKNOWN_MAP_NAME, Environment, GameMode, LayerType
11-
from rcon.types import MapSequenceResponse, ServerInfoType, SlotsType, VipId, GameStateType, AdminType
11+
from rcon.types import MapRotationResponse, MapSequenceResponse, ServerInfoType, SlotsType, VipId, GameStateType, AdminType
1212
from rcon.utils import exception_in_chain
1313

1414
logger = logging.getLogger(__name__)
@@ -347,8 +347,12 @@ def get_votekick_thresholds(self) -> list[list[int]]:
347347
thresholds = self.exchange("GetVoteKickThreshold", 2).content_dict["voteThresholdList"]
348348
return [[int(x["playerCount"]), int(x["voteThreshold"])] for x in thresholds]
349349

350-
def get_map_rotation(self) -> list[str]:
351-
return [x["iD"] for x in self.exchange("GetServerInformation", 2, {"Name": "maprotation", "Value": ""}).content_dict["mAPS"]]
350+
def get_map_rotation(self) -> MapRotationResponse:
351+
data = self.exchange("GetServerInformation", 2, {"Name": "maprotation", "Value": ""}).content_dict
352+
return {
353+
"maps": [x["iD"] for x in data["mAPS"]],
354+
"current_index": data["currentIndex"]
355+
}
352356

353357
def get_map_sequence(self) -> MapSequenceResponse:
354358
data = self.exchange("GetServerInformation", 2, {"Name": "mapsequence", "Value": ""}).content_dict
@@ -481,7 +485,7 @@ def add_map_to_rotation(
481485
map_name: str,
482486
after_map_name: str | None = None,
483487
):
484-
rotation = self.get_map_rotation()
488+
rotation = self.get_map_rotation()["maps"]
485489

486490
map_index = len(rotation)
487491
if after_map_name:
@@ -496,7 +500,7 @@ def add_map_to_rotation_at_index(self, map_name: str, map_index: int):
496500
self.exchange("AddMapToRotation", 2, {"MapName": map_name, "Index": map_index})
497501

498502
def remove_map_from_rotation(self, map_name: str):
499-
rotation = self.get_map_rotation()
503+
rotation = self.get_map_rotation()["maps"]
500504
try:
501505
map_index = rotation.index(map_name)
502506
except ValueError:

rcon/rcon.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
GameStateType,
2727
GetDetailedPlayer,
2828
GetDetailedPlayers,
29+
GetMapRotation,
2930
GetMapSequence,
3031
GetPlayersType,
3132
ParsedLogsType,
@@ -1120,16 +1121,27 @@ def perma_ban(self, player_id: str, reason="", by="", player_name: str | None =
11201121
return res
11211122

11221123
@ttl_cache(60 * 5)
1123-
def get_map_rotation(self) -> list[Layer]:
1124-
l = super().get_map_rotation()
1124+
def get_map_rotation(self) -> GetMapRotation:
1125+
map_rotation = super().get_map_rotation()
1126+
map_sequence = super().get_map_sequence()
1127+
map_rotation_list = map_rotation["maps"]
11251128

11261129
maps: list[Layer] = []
1127-
for map_ in l:
1130+
for map_ in map_rotation_list:
11281131
if not self.map_regexp.match(map_):
11291132
raise HLLCommandFailedError("Server returned wrong data")
11301133

11311134
maps.append(parse_layer(map_))
1132-
return maps
1135+
1136+
next_map_index = map_sequence["current_index"] + 1
1137+
if (next_map_index >= len(map_sequence["maps"])):
1138+
next_map_index = 0
1139+
1140+
return {
1141+
"maps": maps,
1142+
"current_index": map_sequence["current_index"],
1143+
"next_index": next_map_index,
1144+
}
11331145

11341146
@ttl_cache(60 * 5)
11351147
def get_map_sequence(self) -> GetMapSequence:
@@ -1187,7 +1199,7 @@ def remove_map_from_rotation(self, map_name: str):
11871199

11881200
def remove_map_from_rotation_at_index(self, map_index: int):
11891201
if map_index < 0:
1190-
rotation = self.get_map_rotation()
1202+
rotation = self.get_map_rotation()["maps"]
11911203
map_index = len(rotation) + map_index + 1
11921204

11931205
with invalidates(
@@ -1208,7 +1220,7 @@ def remove_maps_from_rotation(self, map_names: list[str]):
12081220

12091221
def add_maps_to_rotation(self, map_names: list[str]):
12101222
"""Add the given maps to the rotation, returns the game server response for each map"""
1211-
rotation = self.get_map_rotation()
1223+
rotation = self.get_map_rotation()["maps"]
12121224
results = []
12131225
with invalidates(
12141226
Rcon.get_map_rotation,
@@ -1229,7 +1241,7 @@ def set_map_rotation(self, map_names: list[str]):
12291241
map_names = list(map_names)
12301242
logger.info("Apply map rotation %s", map_names)
12311243

1232-
rotation = self.get_map_rotation()
1244+
rotation = self.get_map_rotation()["maps"]
12331245
rotation_size = len(rotation)
12341246

12351247
with invalidates(

rcon/scoreboard.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ def build_map_rotation_embed(
319319
embed = DiscordEmbed()
320320
embed.set_url(str(config.public_scoreboard_url))
321321

322-
rotation: list[Layer] = rcon_api.get_map_rotation()
322+
rotation: list[Layer] = rcon_api.get_map_rotation()["maps"]
323323
gamestate: GameStateType = rcon_api.get_gamestate()
324324

325325
title = ""

rcon/types.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,3 +894,12 @@ class MapSequenceResponse(TypedDict):
894894
class GetMapSequence(TypedDict):
895895
maps: list[Layer]
896896
current_index: int
897+
898+
class MapRotationResponse(TypedDict):
899+
maps: list[str]
900+
current_index: int
901+
902+
class GetMapRotation(TypedDict):
903+
maps: list[Layer]
904+
current_index: int
905+
next_index: int

rcon/vote_map.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ def apply_results(self):
795795
rcon.set_map_rotation([next_map.id])
796796

797797
# Check that it worked
798-
current_rotation = rcon.get_map_rotation()
798+
current_rotation = rcon.get_map_rotation()["maps"]
799799
if len(current_rotation) != 1 or current_rotation[0] != next_map:
800800
raise ValueError(
801801
f"Applying the winning map {next_map=} failed: {current_rotation=}"

rcongui/src/components/cards/MapRotationCard.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const MapRotationCard = () => {
1313
return (
1414
<ScrollableCard sx={{ height: "100%" }} title="Map Rotation">
1515
<Stack divider={<Divider sx={{ my: 0.2 }} />}>
16-
{mapRotation.map((map) => (
16+
{mapRotation.maps.map((map) => (
1717
<MapDetailsCardCompact key={map.id} mapLayer={map} />
1818
))}
1919
</Stack>

rcongui/src/pages/settings/maps/MapListBuilder.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export function MapListBuilder({
3939
isSaving,
4040
exclusive = false,
4141
actions,
42+
params = {},
4243
}) {
4344
const [mapSelection, setMapSelection] = useState(
4445
selectedMaps.map(withSelectionId)
@@ -192,6 +193,7 @@ export function MapListBuilder({
192193
isDisabled={isSaveDisabled}
193194
isSaving={isSaving}
194195
actions={actions}
196+
params={params}
195197
/>
196198
</Grid>
197199
)}

rcongui/src/pages/settings/maps/rotation/builder/SortableRotationItem.jsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { Box, IconButton, Tooltip } from "@mui/material";
1+
import { Box, Chip, IconButton, Stack, Tooltip } from "@mui/material";
22
import CloseIcon from "@mui/icons-material/Close";
33
import { useSortable } from "@dnd-kit/sortable";
44
import { CSS } from "@dnd-kit/utilities";
55
import { MapDetailsCard } from "../../MapDetailsCard";
66

7-
function SortableRotationItem({ item, onRemove }) {
7+
function SortableRotationItem({ item, onRemove, isNext }) {
88
const {
99
attributes,
1010
listeners,
@@ -64,13 +64,14 @@ function SortableRotationItem({ item, onRemove }) {
6464
</Box>
6565
<MapDetailsCard mapLayer={mapLayer} />
6666
</Box>
67-
<Box sx={{ display: "flex", gap: 1 }}>
67+
<Stack direction={"row"} gap={0.25} alignItems={"center"}>
68+
{isNext && <Chip color="secondary" label="Next" />}
6869
<Tooltip title="Remove from rotation">
6970
<IconButton size="small" onClick={() => onRemove(mapLayer)} color="error">
7071
<CloseIcon fontSize="small" />
7172
</IconButton>
7273
</Tooltip>
73-
</Box>
74+
</Stack>
7475
</Box>
7576
);
7677
}

rcongui/src/pages/settings/maps/rotation/builder/SortableRotationList.jsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export function SortableRotationList({
3030
onSave,
3131
isDisabled,
3232
actions,
33+
params,
3334
}) {
3435
// Set up DnD sensors
3536
const sensors = useSensors(
@@ -173,13 +174,26 @@ export function SortableRotationList({
173174
items={maps.map((item) => item.selectionId)}
174175
strategy={verticalListSortingStrategy}
175176
>
176-
{maps.map((item, index) => (
177-
<SortableRotationItem
178-
key={item.selectionId}
179-
item={item}
180-
onRemove={onRemove}
181-
/>
182-
))}
177+
{maps.map((item, index, tempRotation) => {
178+
console.log(tempRotation, params, index)
179+
let isNext = false;
180+
if (tempRotation.length === 1) {
181+
isNext = true
182+
} else if (params.currentMapIndex === params.nextMapIndex) {
183+
isNext = (index + 1) === params.nextMapIndex
184+
} else {
185+
isNext = index === params.nextMapIndex
186+
}
187+
188+
return (
189+
<SortableRotationItem
190+
key={item.selectionId}
191+
item={item}
192+
onRemove={onRemove}
193+
isNext={isNext}
194+
/>
195+
)
196+
})}
183197
</SortableContext>
184198
</DndContext>
185199
) : (

rcongui/src/pages/settings/maps/rotation/builder/index.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,18 @@ function MapRotationBuilder() {
5757
)}
5858
<MapListBuilder
5959
maps={maps}
60-
selectedMaps={currentRotation}
60+
selectedMaps={currentRotation.maps}
6161
slots={{
6262
SelectedMapList: SortableRotationList,
6363
MapListItem: MapBuilderListItem,
6464
}}
6565
onSave={saveRotation}
6666
isSaving={isRotationSaving}
6767
isSaveDisabled={isRotationSaving}
68+
params={{
69+
nextMapIndex: currentRotation.next_index,
70+
currentMapIndex: currentRotation.current_index,
71+
}}
6872
/>
6973
</>
7074
);

0 commit comments

Comments
 (0)