OpenTTD Source 20241224-master-gf74b0cf984
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 */
37static 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
52static HANDLE _hInputReady, _hWaitForInputHandling;
53static HANDLE _hThread; // Thread to close
54static std::string _win_console_thread_buffer;
55
56/* Windows Console thread. Just loop and signal when input has been received */
57static 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
69static 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
83static 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
96static void *_dedicated_video_mem;
97
98/* Whether a fork has been done. */
99bool _dedicated_forks;
100
101extern bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = nullptr);
102
103static FVideoDriver_Dedicated iFVideoDriver_Dedicated;
104
105
106std::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
145void VideoDriver_Dedicated::MakeDirty(int, int, int, int) {}
146bool VideoDriver_Dedicated::ChangeResolution(int, int) { return false; }
147bool VideoDriver_Dedicated::ToggleFullscreen(bool) { return false; }
148
149#if defined(UNIX)
150static 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
167static bool InputWaiting()
168{
169 return WaitForSingleObject(_hInputReady, 1) == WAIT_OBJECT_0;
170}
171
172#endif
173
174static 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.
CompanyID _current_company
Company currently doing an action.
@ COMPANY_SPECTATOR
The client is spectating.
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.
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
@ 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)
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.
void SetCurrentThreadName(const char *threadName)
Name the thread this function is called on for the debugger.
Definition unix.cpp:245