OpenTTD Source 20251213-master-g1091fa6071
dedicated_v.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "../stdafx.h"
11
12#include "../gfx_func.h"
13#include "../error_func.h"
14#include "../network/network.h"
15#include "../network/network_internal.h"
16#include "../console_func.h"
17#include "../genworld.h"
18#include "../fileio_type.h"
19#include "../fios.h"
20#include "../blitter/factory.hpp"
21#include "../company_func.h"
22#include "../saveload/saveload.h"
23#include "../thread.h"
24#include "../window_func.h"
25#include <iostream>
26#include "dedicated_v.h"
27
28#if defined(UNIX)
29# include <sys/time.h> /* gettimeofday */
30# include <sys/types.h>
31# include <unistd.h>
32# include <signal.h>
33# define STDIN 0 /* file descriptor for standard input */
34
35/* Signal handlers */
36static void DedicatedSignalHandler(int sig)
37{
38 if (_game_mode == GM_NORMAL && _settings_client.gui.autosave_on_exit) DoExitSave();
39 _exit_game = true;
40 signal(sig, DedicatedSignalHandler);
41}
42#endif
43
44#if defined(_WIN32)
45# include <windows.h> /* GetTickCount */
46# include <conio.h>
47# include <time.h>
48# include <tchar.h>
49# include "../os/windows/win32.h"
50
51static HANDLE _hInputReady, _hWaitForInputHandling;
52static HANDLE _hThread; // Thread to close
53static std::string _win_console_thread_buffer;
54
55/* Windows Console thread. Just loop and signal when input has been received */
56static void WINAPI CheckForConsoleInput()
57{
58 SetCurrentThreadName("ottd:win-console");
59
60 for (;;) {
61 std::getline(std::cin, _win_console_thread_buffer);
62
63 /* Signal input waiting that input is read and wait for it being handled. */
64 SignalObjectAndWait(_hInputReady, _hWaitForInputHandling, INFINITE, FALSE);
65 }
66}
67
68static void CreateWindowsConsoleThread()
69{
70 DWORD dwThreadId;
71 /* Create event to signal when console input is ready */
72 _hInputReady = CreateEvent(nullptr, false, false, nullptr);
73 _hWaitForInputHandling = CreateEvent(nullptr, false, false, nullptr);
74 if (_hInputReady == nullptr || _hWaitForInputHandling == nullptr) UserError("Cannot create console event!");
75
76 _hThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)CheckForConsoleInput, nullptr, 0, &dwThreadId);
77 if (_hThread == nullptr) UserError("Cannot create console thread!");
78
79 Debug(driver, 2, "Windows console thread started");
80}
81
82static void CloseWindowsConsoleThread()
83{
84 CloseHandle(_hThread);
85 CloseHandle(_hInputReady);
86 CloseHandle(_hWaitForInputHandling);
87 Debug(driver, 2, "Windows console thread shut down");
88}
89
90#endif
91
92#include "../safeguards.h"
93
94
95static std::unique_ptr<uint8_t[]> _dedicated_video_mem;
96
97/* Whether a fork has been done. */
98bool _dedicated_forks;
99
100extern bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = nullptr);
101
102static FVideoDriver_Dedicated iFVideoDriver_Dedicated;
103
104
105std::optional<std::string_view> VideoDriver_Dedicated::Start(const StringList &)
106{
107 this->UpdateAutoResolution();
108
110 if (bpp != 0) _dedicated_video_mem = std::make_unique<uint8_t[]>(static_cast<size_t>(_cur_resolution.width) * _cur_resolution.height * (bpp / 8));
111
112 _screen.width = _screen.pitch = _cur_resolution.width;
113 _screen.height = _cur_resolution.height;
114 _screen.dst_ptr = _dedicated_video_mem.get();
115 ScreenSizeChanged();
117
118#if defined(_WIN32)
119 /* For win32 we need to allocate a console (debug mode does the same) */
120 CreateConsole();
121 CreateWindowsConsoleThread();
122 SetConsoleTitle(L"OpenTTD Dedicated Server");
123#endif
124
125#ifdef _MSC_VER
126 /* Disable the MSVC assertion message box. */
127 _set_error_mode(_OUT_TO_STDERR);
128 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
129 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
130#endif
131
132 Debug(driver, 1, "Loading dedicated server");
133 return std::nullopt;
134}
135
137{
138#ifdef _WIN32
139 CloseWindowsConsoleThread();
140#endif
141 _dedicated_video_mem = nullptr;
142}
143
144void VideoDriver_Dedicated::MakeDirty(int, int, int, int) {}
145bool VideoDriver_Dedicated::ChangeResolution(int, int) { return false; }
146bool VideoDriver_Dedicated::ToggleFullscreen(bool) { return false; }
147
148#if defined(UNIX)
149static bool InputWaiting()
150{
151 struct timeval tv;
152 fd_set readfds;
153
154 tv.tv_sec = 0;
155 tv.tv_usec = 1;
156
157 FD_ZERO(&readfds);
158 FD_SET(STDIN, &readfds);
159
160 /* don't care about writefds and exceptfds: */
161 return select(STDIN + 1, &readfds, nullptr, nullptr, &tv) > 0;
162}
163
164#else
165
166static bool InputWaiting()
167{
168 return WaitForSingleObject(_hInputReady, 1) == WAIT_OBJECT_0;
169}
170
171#endif
172
173static void DedicatedHandleKeyInput()
174{
175 if (!InputWaiting()) return;
176
177 if (_exit_game) return;
178
179 std::string input_line;
180#if defined(UNIX)
181 if (!std::getline(std::cin, input_line)) return;
182#else
183 /* Handle console input, and signal console thread, it can accept input again */
184 std::swap(input_line, _win_console_thread_buffer);
185 SetEvent(_hWaitForInputHandling);
186#endif
187
188 /* Remove any trailing \r or \n, and ensure the string is valid. */
189 auto p = input_line.find_last_not_of("\r\n");
190 if (p != std::string::npos) p++;
191 IConsoleCmdExec(StrMakeValid(input_line.substr(0, p)));
192}
193
195{
196 /* Signal handlers */
197#if defined(UNIX)
198 signal(SIGTERM, DedicatedSignalHandler);
199 signal(SIGINT, DedicatedSignalHandler);
200 signal(SIGQUIT, DedicatedSignalHandler);
201#endif
202
203 /* Load the dedicated server stuff */
204 _is_network_server = true;
205 _network_dedicated = true;
207
208 /* If SwitchMode is SM_LOAD_GAME / SM_START_HEIGHTMAP, it means that the user used the '-g' options */
211 }
212
213 this->is_game_threaded = false;
214
215 /* Done loading, start game! */
216
217 while (!_exit_game) {
218 if (!_dedicated_forks) DedicatedHandleKeyInput();
219 this->DrainCommandQueue();
220
221 this->Tick();
222 this->SleepTillNextTick();
223 }
224}
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition factory.hpp:136
virtual uint8_t GetScreenDepth()=0
Get the screen depth this blitter works for.
virtual void PostResize()
Post resize event.
Definition base.hpp:205
Factory for the dedicated server video driver.
Definition dedicated_v.h:34
std::optional< std::string_view > Start(const StringList &param) override
Start this driver.
void MainLoop() override
Perform the actual drawing.
void Stop() override
Stop this driver.
bool ToggleFullscreen(bool fullscreen) override
Change the full screen setting.
void MakeDirty(int left, int top, int width, int height) override
Mark a particular area dirty.
bool ChangeResolution(int w, int h) override
Change the resolution of the window.
void Tick()
Give the video-driver a tick.
void SleepTillNextTick()
Sleep till the next tick is about to happen.
void DrainCommandQueue()
Execute all queued commands.
void UpdateAutoResolution()
Apply resolution auto-detection and clamp to sensible defaults.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
CompanyID _current_company
Company currently doing an action.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
void IConsoleCmdExec(std::string_view command_string, const uint recurse_count)
Execute a given command passed to us.
Definition console.cpp:269
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
Base for the dedicated video driver.
Dimension _cur_resolution
The current resolution.
Definition driver.cpp:29
SaveLoadOperation
Operation performed on the file.
Definition fileio_type.h:52
DetailedFileType
Kinds of files in each AbstractFileType.
Definition fileio_type.h:28
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Definition fileio_type.h:88
static const uint32_t GENERATE_NEW_SEED
Create a new random seed.
Definition genworld.h:25
void StartNewGameWithoutGUI(uint32_t seed)
Start a normal game without the GUI.
SwitchMode _switch_mode
The next mainloop command.
Definition gfx.cpp:49
bool _is_network_server
Does this client wants to be a network-server?
Definition network.cpp:70
bool _network_dedicated
are we a dedicated server?
Definition network.cpp:69
GameMode
Mode which defines the state of the game.
Definition openttd.h:18
@ SM_START_HEIGHTMAP
Load a heightmap and start a new game from it.
Definition openttd.h:38
@ SM_LOAD_GAME
Load game, Play Scenario.
Definition openttd.h:32
void DoExitSave()
Do a save when exiting the game (_settings_client.gui.autosave_on_exit)
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
static void StrMakeValid(Builder &builder, StringConsumer &consumer, StringValidationSettings settings)
Copies the valid (UTF-8) characters from consumer to the builder.
Definition string.cpp:119
std::vector< std::string > StringList
Type for a list of strings.
Definition string_type.h:60
GUISettings gui
settings related to the GUI
bool autosave_on_exit
save an autosave when you quit the game, but do not ask "Do you really want to quit?...
Interface for filtering a savegame till it is loaded.
void SetCurrentThreadName(const std::string &thread_name)
Name the thread this function is called on for the debugger.
Definition unix.cpp:245