OpenTTD Source  20241121-master-g67a0fccfad
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 <http://www.gnu.org/licenses/>.
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 "../core/random_func.hpp"
23 #include "../saveload/saveload.h"
24 #include "../thread.h"
25 #include "../window_func.h"
26 #include <iostream>
27 #include "dedicated_v.h"
28 
29 #if defined(UNIX)
30 # include <sys/time.h> /* gettimeofday */
31 # include <sys/types.h>
32 # include <unistd.h>
33 # include <signal.h>
34 # define STDIN 0 /* file descriptor for standard input */
35 
36 /* Signal handlers */
37 static void DedicatedSignalHandler(int sig)
38 {
39  if (_game_mode == GM_NORMAL && _settings_client.gui.autosave_on_exit) DoExitSave();
40  _exit_game = true;
41  signal(sig, DedicatedSignalHandler);
42 }
43 #endif
44 
45 #if defined(_WIN32)
46 # include <windows.h> /* GetTickCount */
47 # include <conio.h>
48 # include <time.h>
49 # include <tchar.h>
50 # include "../os/windows/win32.h"
51 
52 static HANDLE _hInputReady, _hWaitForInputHandling;
53 static HANDLE _hThread; // Thread to close
54 static std::string _win_console_thread_buffer;
55 
56 /* Windows Console thread. Just loop and signal when input has been received */
57 static void WINAPI CheckForConsoleInput()
58 {
59  SetCurrentThreadName("ottd:win-console");
60 
61  for (;;) {
62  std::getline(std::cin, _win_console_thread_buffer);
63 
64  /* Signal input waiting that input is read and wait for it being handled. */
65  SignalObjectAndWait(_hInputReady, _hWaitForInputHandling, INFINITE, FALSE);
66  }
67 }
68 
69 static void CreateWindowsConsoleThread()
70 {
71  DWORD dwThreadId;
72  /* Create event to signal when console input is ready */
73  _hInputReady = CreateEvent(nullptr, false, false, nullptr);
74  _hWaitForInputHandling = CreateEvent(nullptr, false, false, nullptr);
75  if (_hInputReady == nullptr || _hWaitForInputHandling == nullptr) UserError("Cannot create console event!");
76 
77  _hThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)CheckForConsoleInput, nullptr, 0, &dwThreadId);
78  if (_hThread == nullptr) UserError("Cannot create console thread!");
79 
80  Debug(driver, 2, "Windows console thread started");
81 }
82 
83 static void CloseWindowsConsoleThread()
84 {
85  CloseHandle(_hThread);
86  CloseHandle(_hInputReady);
87  CloseHandle(_hWaitForInputHandling);
88  Debug(driver, 2, "Windows console thread shut down");
89 }
90 
91 #endif
92 
93 #include "../safeguards.h"
94 
95 
96 static void *_dedicated_video_mem;
97 
98 /* Whether a fork has been done. */
99 bool _dedicated_forks;
100 
101 extern bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = nullptr);
102 
103 static FVideoDriver_Dedicated iFVideoDriver_Dedicated;
104 
105 
106 std::optional<std::string_view> VideoDriver_Dedicated::Start(const StringList &)
107 {
108  this->UpdateAutoResolution();
109 
111  _dedicated_video_mem = (bpp == 0) ? nullptr : MallocT<uint8_t>(static_cast<size_t>(_cur_resolution.width) * _cur_resolution.height * (bpp / 8));
112 
113  _screen.width = _screen.pitch = _cur_resolution.width;
114  _screen.height = _cur_resolution.height;
115  _screen.dst_ptr = _dedicated_video_mem;
116  ScreenSizeChanged();
118 
119 #if defined(_WIN32)
120  /* For win32 we need to allocate a console (debug mode does the same) */
121  CreateConsole();
122  CreateWindowsConsoleThread();
123  SetConsoleTitle(L"OpenTTD Dedicated Server");
124 #endif
125 
126 #ifdef _MSC_VER
127  /* Disable the MSVC assertion message box. */
128  _set_error_mode(_OUT_TO_STDERR);
129  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
130  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
131 #endif
132 
133  Debug(driver, 1, "Loading dedicated server");
134  return std::nullopt;
135 }
136 
138 {
139 #ifdef _WIN32
140  CloseWindowsConsoleThread();
141 #endif
142  free(_dedicated_video_mem);
143 }
144 
145 void VideoDriver_Dedicated::MakeDirty(int, int, int, int) {}
146 bool VideoDriver_Dedicated::ChangeResolution(int, int) { return false; }
147 bool VideoDriver_Dedicated::ToggleFullscreen(bool) { return false; }
148 
149 #if defined(UNIX)
150 static bool InputWaiting()
151 {
152  struct timeval tv;
153  fd_set readfds;
154 
155  tv.tv_sec = 0;
156  tv.tv_usec = 1;
157 
158  FD_ZERO(&readfds);
159  FD_SET(STDIN, &readfds);
160 
161  /* don't care about writefds and exceptfds: */
162  return select(STDIN + 1, &readfds, nullptr, nullptr, &tv) > 0;
163 }
164 
165 #else
166 
167 static bool InputWaiting()
168 {
169  return WaitForSingleObject(_hInputReady, 1) == WAIT_OBJECT_0;
170 }
171 
172 #endif
173 
174 static void DedicatedHandleKeyInput()
175 {
176  if (!InputWaiting()) return;
177 
178  if (_exit_game) return;
179 
180  std::string input_line;
181 #if defined(UNIX)
182  if (!std::getline(std::cin, input_line)) return;
183 #else
184  /* Handle console input, and signal console thread, it can accept input again */
185  std::swap(input_line, _win_console_thread_buffer);
186  SetEvent(_hWaitForInputHandling);
187 #endif
188 
189  /* Remove any trailing \r or \n, and ensure the string is valid. */
190  auto p = input_line.find_last_not_of("\r\n");
191  if (p != std::string::npos) p++;
192  IConsoleCmdExec(StrMakeValid(input_line.substr(0, p)));
193 }
194 
196 {
197  /* Signal handlers */
198 #if defined(UNIX)
199  signal(SIGTERM, DedicatedSignalHandler);
200  signal(SIGINT, DedicatedSignalHandler);
201  signal(SIGQUIT, DedicatedSignalHandler);
202 #endif
203 
204  /* Load the dedicated server stuff */
205  _is_network_server = true;
206  _network_dedicated = true;
208 
209  /* If SwitchMode is SM_LOAD_GAME / SM_START_HEIGHTMAP, it means that the user used the '-g' options */
212  }
213 
214  this->is_game_threaded = false;
215 
216  /* Done loading, start game! */
217 
218  while (!_exit_game) {
219  if (!_dedicated_forks) DedicatedHandleKeyInput();
220  this->DrainCommandQueue();
221 
222  this->Tick();
223  this->SleepTillNextTick();
224  }
225 }
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition: factory.hpp:138
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.
Definition: company_cmd.cpp:52
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
@ COMPANY_SPECTATOR
The client is spectating.
Definition: company_type.h:35
void IConsoleCmdExec(const std::string &command_string, const uint recurse_count)
Execute a given command passed to us.
Definition: console.cpp:291
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
Base for the dedicated video driver.
Dimension _cur_resolution
The current resolution.
Definition: driver.cpp:26
SaveLoadOperation
Operation performed on the file.
Definition: fileio_type.h:53
DetailedFileType
Kinds of files in each AbstractFileType.
Definition: fileio_type.h:29
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Definition: fileio_type.h:115
static const uint32_t GENERATE_NEW_SEED
Create a new random seed.
Definition: genworld.h:24
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:69
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:68
bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, std::shared_ptr< LoadFilter > lf=nullptr)
Load the specified savegame but on error do different things.
Definition: openttd.cpp:943
@ 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
GameMode
Mode which defines the state of the game.
Definition: openttd.h:18
void DoExitSave()
Do a save when exiting the game (_settings_client.gui.autosave_on_exit)
Definition: saveload.cpp:3206
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: stdafx.h:334
static void StrMakeValid(T &dst, const char *str, const char *last, StringValidationSettings settings)
Copies the valid (UTF-8) characters from str up to last to the dst.
Definition: string.cpp:107
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.