unit Game.Chivalry; interface uses System.Generics.Collections, Game.Base, Game.Intf; type TChivalryGame = class(TCustomGame, IGameNetwork, IGameName, IGameMapList) private FServerPort: Integer; FPeerPort: Integer; FQueryPort: Integer; FServerName: string; FMessageOfTheDay: string; FPredefinedMapList: TObjectList; FMapList: TObjectList; protected procedure DoLoad; override; procedure DoSave; override; procedure LoadPredefinedMapList(AList: TList); virtual; abstract; function CreateGameMap(const AMapName: string): TGameMap; virtual; public constructor Create(const ALocation: string); override; destructor Destroy; override; { IGameNetwork } function GetServerPort: Integer; function GetPeerPort: Integer; function GetQueryPort: Integer; procedure SetServerPort(const Value: Integer); procedure SetPeerPort(const Value: Integer); procedure SetQueryPort(const Value: Integer); property ServerPort: Integer read GetServerPort write SetServerPort; property PeerPort: Integer read GetPeerPort write SetPeerPort; property QueryPort: Integer read GetQueryPort write SetQueryPort; { IGameName } function GetServerName: string; function GetMessageOfTheDay: string; procedure SetServerName(const Value: string); procedure SetMessageOfTheDay(const Value: string); property ServerName: string read GetServerName write SetServerName; property MessageOfTheDay: string read GetMessageOfTheDay write SetMessageOfTheDay; { IGameMapList } function GetPredefinedMapList: TEnumerable; function GetMapList: TEnumerable; function GetMapCount: Integer; function GetMap(Index: Integer): TGameMap; procedure AddMap(AMap: TGameMap); procedure InsertMap(Index: Integer; AMap: TGameMap); procedure DeleteMap(AIndex: Integer); procedure RemoveMap(AMap: TGameMap); procedure MoveMap(ASourceIndex, ATargetIndex: Integer); property PredefinedMapList: TEnumerable read GetPredefinedMapList; property MapList: TEnumerable read GetMapList; property MapCount: Integer read GetMapCount; property Map[Index: Integer]: TGameMap read GetMap; end; implementation uses System.Classes, System.IniFiles, System.SysUtils, UDKIniFile; const GameSettingsFileName = 'UDKGame\Config\PCServer-UDKGame.ini'; GameURL = 'URL'; GameURLPort = 'Port'; GameURLPortDefault = 7777; GameURLPeerPort = 'PeerPort'; GameURLPeerPortDefault = 7778; GameReplicationInfo = 'Engine.GameReplicationInfo'; GameReplicationInfoServerName = 'ServerName'; GameReplicationInfoMessageOfTheDay = 'MessageOfTheDay'; GameAOCGame = 'AOC.AOCGame'; GameAOCGameMapList = 'Maplist'; EngineSettingsFileName = 'UDKGame\Config\PCServer-UDKEngine.ini'; EngineSteam = 'OnlineSubsystemSteamworks.OnlineSubsystemSteamworks'; EngineSteamQueryPort = 'QueryPort'; EngineSteamQueryPortDefault = 27015; { TChivalryGame } constructor TChivalryGame.Create(const ALocation: string); begin inherited Create(ALocation); FPredefinedMapList := TObjectList.Create(True); FMapList := TObjectList.Create(True); LoadPredefinedMapList(FPredefinedMapList); end; destructor TChivalryGame.Destroy; begin FreeAndNil(FMapList); FreeAndNil(FPredefinedMapList); inherited Destroy; end; procedure TChivalryGame.DoLoad; var gameSettings: TUDKIniFile; engineSettings: TUDKIniFile; mapListValues: TStringList; mapName: string; mapListChanged: Boolean; begin gameSettings := TUDKIniFile.Create(Location + GameSettingsFileName); try SetServerPort(gameSettings.ReadInteger(GameURL, GameURLPort, GameURLPortDefault)); SetPeerPort(gameSettings.ReadInteger(GameURL, GameURLPeerPort, GameURLPeerPortDefault)); SetServerName(gameSettings.ReadString(GameReplicationInfo, GameReplicationInfoServerName, '')); SetMessageOfTheDay(gameSettings.ReadString(GameReplicationInfo, GameReplicationInfoMessageOfTheDay, '')); mapListChanged := (FMapList.Count > 0); { Maplist is special; it occurs multiple times and order matters } mapListValues := TStringList.Create; try gameSettings.ReadDuplicateStrings(GameAOCGame, GameAOCGameMapList, mapListValues); for mapName in mapListValues do begin FMapList.Add(CreateGameMap(mapName)); mapListChanged := True; end; finally FreeAndNil(mapListValues); end; if mapListChanged then PropertyChanged('MapList'); finally FreeAndNil(gameSettings); end; engineSettings := TUDKIniFile.Create(Location + EngineSettingsFileName); try SetQueryPort(engineSettings.ReadInteger(EngineSteam, EngineSteamQueryPort, EngineSteamQueryPortDefault)); finally FreeAndNil(engineSettings); end; end; procedure TChivalryGame.DoSave; var gameSettings: TUDKIniFile; engineSettings: TUDKIniFile; map: TGameMap; begin gameSettings := TUDKIniFile.Create(Location + GameSettingsFileName); try gameSettings.WriteInteger(GameURL, GameURLPort, ServerPort); gameSettings.WriteInteger(GameURL, GameURLPeerPort, PeerPort); gameSettings.WriteString(GameReplicationInfo, GameReplicationInfoServerName, ServerName); gameSettings.WriteString(GameReplicationInfo, GameReplicationInfoMessageOfTheDay, MessageOfTheDay); { Remove all Maplist references before rewriting the list } gameSettings.DeleteDuplicateKeys(GameAOCGame, GameAOCGameMapList); for map in MapList do gameSettings.WriteDuplicateString(GameAOCGame, GameAOCGameMapList, map.Name); gameSettings.UpdateFile; finally FreeAndNil(gameSettings); end; engineSettings := TUDKIniFile.Create(Location + EngineSettingsFileName); try engineSettings.WriteInteger(EngineSteam, EngineSteamQueryPort, QueryPort); engineSettings.UpdateFile; finally FreeAndNil(engineSettings); end; end; function TChivalryGame.CreateGameMap(const AMapName: string): TGameMap; var map: TGameMap; begin Result := nil; for map in PredefinedMapList do if SameText(map.Name, AMapName) then begin Result := TGameMap.Create(map); break; end; if not Assigned(Result) then Result := TGameMap.Create(AMapName, '', ''); end; function TChivalryGame.GetServerPort: Integer; begin Result := FServerPort; end; function TChivalryGame.GetPeerPort: Integer; begin Result := FPeerPort; end; function TChivalryGame.GetQueryPort: Integer; begin Result := FQueryPort; end; procedure TChivalryGame.SetServerPort(const Value: Integer); begin if Value <> FServerPort then begin FServerPort := Value; PropertyChanged('ServerPort'); end; end; procedure TChivalryGame.SetPeerPort(const Value: Integer); begin if Value <> FPeerPort then begin FPeerPort := Value; PropertyChanged('PeerPort'); end; end; procedure TChivalryGame.SetQueryPort(const Value: Integer); begin if Value <> FQueryPort then begin FQueryPort := Value; PropertyChanged('QueryPort'); end; end; function TChivalryGame.GetServerName: string; begin Result := FServerName; end; function TChivalryGame.GetMessageOfTheDay: string; begin Result := FMessageOfTheDay; end; procedure TChivalryGame.SetServerName(const Value: string); begin if Value <> FServerName then begin FServerName := Value; PropertyChanged('ServerName'); end; end; procedure TChivalryGame.SetMessageOfTheDay(const Value: string); begin if Value <> FMessageOfTheDay then begin FMessageOfTheDay := Value; PropertyChanged('MessageOfTheDay'); end; end; function TChivalryGame.GetPredefinedMapList: TEnumerable; begin Result := FPredefinedMapList; end; function TChivalryGame.GetMapList: TEnumerable; begin Result := FMapList; end; function TChivalryGame.GetMapCount: Integer; begin Result := FMapList.Count; end; function TChivalryGame.GetMap(Index: Integer): TGameMap; begin Result := FMapList[Index]; end; procedure TChivalryGame.AddMap(AMap: TGameMap); begin FMapList.Add(AMap); PropertyChanged('MapList'); end; procedure TChivalryGame.InsertMap(Index: Integer; AMap: TGameMap); begin FMapList.Insert(Index, AMap); PropertyChanged('MapList'); end; procedure TChivalryGame.DeleteMap(AIndex: Integer); begin FMapList.Delete(AIndex); PropertyChanged('MapList'); end; procedure TChivalryGame.RemoveMap(AMap: TGameMap); begin if FMapList.Remove(AMap) > -1 then PropertyChanged('MapList'); end; procedure TChivalryGame.MoveMap(ASourceIndex, ATargetIndex: Integer); begin if ATargetIndex <> ASourceIndex then begin FMapList.Move(ASourceIndex, ATargetIndex); PropertyChanged('MapList'); end; end; end.