OpenTTD Source 20260531-master-g0e951f3528
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
9
10#include "../stdafx.h"
11
12#include "../gfx_func.h"
13#include "../error_func.h"
14#include "../network/network.h"
16#include "../console_func.h"
17#include "../genworld.h"
18#include "../fileio_type.h"
19#include "../fios.h"
21#include "../company_func.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
36std::atomic<bool> _dedicated_exit_requested;
37
38/* Signal handlers */
39static void DedicatedSignalHandler(int sig)
40{
41 _dedicated_exit_requested = true;
42 signal(sig, DedicatedSignalHandler);
43}
44#endif
45
46#if defined(_WIN32)
47# include <windows.h> /* GetTickCount */
48# include <conio.h>
49# include <time.h>
50# include <tchar.h>
51# include "../os/windows/win32.h"
52
53static HANDLE _hInputReady, _hWaitForInputHandling;
54static HANDLE _hThread; // Thread to close
55static std::string _win_console_thread_buffer;
56
57/* Windows Console thread. Just loop and signal when input has been received */
58static void WINAPI CheckForConsoleInput()
59{
60 SetCurrentThreadName("ottd:win-console");
61
62 for (;;) {
63 std::getline(std::cin, _win_console_thread_buffer);
64
65 /* Signal input waiting that input is read and wait for it being handled. */
66 SignalObjectAndWait(_hInputReady, _hWaitForInputHandling, INFINITE, FALSE);
67 }
68}
69
70static void CreateWindowsConsoleThread()
71{
72 DWORD dwThreadId;
73 /* Create event to signal when console input is ready */
74 _hInputReady = CreateEvent(nullptr, false, false, nullptr);
75 _hWaitForInputHandling = CreateEvent(nullptr, false, false, nullptr);
76 if (_hInputReady == nullptr || _hWaitForInputHandling == nullptr) UserError("Cannot create console event!");
77
78 _hThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)CheckForConsoleInput, nullptr, 0, &dwThreadId);
79 if (_hThread == nullptr) UserError("Cannot create console thread!");
80
81 Debug(driver, 2, "Windows console thread started");
82}
83
84static void CloseWindowsConsoleThread()
85{
86 CloseHandle(_hThread);
87 CloseHandle(_hInputReady);
88 CloseHandle(_hWaitForInputHandling);
89 Debug(driver, 2, "Windows console thread shut down");
90}
91
92#endif
93
94#include "../safeguards.h"
95
96
97static std::unique_ptr<uint8_t[]> _dedicated_video_mem;
98
101
102extern bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = nullptr);
103
104static FVideoDriver_Dedicated iFVideoDriver_Dedicated;
105
106
107std::optional<std::string_view> VideoDriver_Dedicated::Start(const StringList &)
108{
109 this->UpdateAutoResolution();
110
112 if (bpp != 0) _dedicated_video_mem = std::make_unique<uint8_t[]>(static_cast<size_t>(_cur_resolution.width) * _cur_resolution.height * (bpp / 8));
113
114 _screen.width = _screen.pitch = _cur_resolution.width;
115 _screen.height = _cur_resolution.height;
116 _screen.dst_ptr = _dedicated_video_mem.get();
117 ScreenSizeChanged();
119
120#if defined(_WIN32)
121 /* For win32 we need to allocate a console (debug mode does the same) */
122 CreateConsole();
123 CreateWindowsConsoleThread();
124 SetConsoleTitle(L"OpenTTD Dedicated Server");
125#endif
126
127#ifdef _MSC_VER
128 /* Disable the MSVC assertion message box. */
129 _set_error_mode(_OUT_TO_STDERR);
130 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
131 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
132#endif
133
134 Debug(driver, 1, "Loading dedicated server");
135 return std::nullopt;
136}
137
139{
140#ifdef _WIN32
141 CloseWindowsConsoleThread();
142#endif
143 _dedicated_video_mem = nullptr;
144}
145
146void VideoDriver_Dedicated::MakeDirty(int, int, int, int) {}
147bool VideoDriver_Dedicated::ChangeResolution(int, int) { return false; }
148bool VideoDriver_Dedicated::ToggleFullscreen(bool) { return false; }
149
150#if defined(UNIX)
151static bool InputWaiting()
152{
153 struct timeval tv;
154 fd_set readfds;
155
156 tv.tv_sec = 0;
157 tv.tv_usec = 1;
158
159 FD_ZERO(&readfds);
160 FD_SET(STDIN, &readfds);
161
162 /* don't care about writefds and exceptfds: */
163 return select(STDIN + 1, &readfds, nullptr, nullptr, &tv) > 0;
164}
165
166#else
167
168static bool InputWaiting()
169{
170 return WaitForSingleObject(_hInputReady, 1) == WAIT_OBJECT_0;
171}
172
173#endif
174
175static void DedicatedHandleKeyInput()
176{
177 if (!InputWaiting()) return;
178
179 if (_exit_game) return;
180
181 std::string input_line;
182#if defined(UNIX)
183 if (!std::getline(std::cin, input_line)) return;
184#else
185 /* Handle console input, and signal console thread, it can accept input again */
186 std::swap(input_line, _win_console_thread_buffer);
187 SetEvent(_hWaitForInputHandling);
188#endif
189
190 /* Remove any trailing \r or \n, and ensure the string is valid. */
191 auto p = input_line.find_last_not_of("\r\n");
192 if (p != std::string::npos) p++;
193 IConsoleCmdExec(StrMakeValid(input_line.substr(0, p)));
194}
195
197{
198 /* Signal handlers */
199#if defined(UNIX)
200 signal(SIGTERM, DedicatedSignalHandler);
201 signal(SIGINT, DedicatedSignalHandler);
202 signal(SIGQUIT, DedicatedSignalHandler);
203#endif
204
205 /* Load the dedicated server stuff */
206 _is_network_server = true;
207 _network_dedicated = true;
209
210 /* If SwitchMode is SwitchMode::LoadGame / SwitchMode::StartHeightmap, it means that the user used the '-g' options */
213 }
214
215 this->is_game_threaded = false;
216
217 /* Done loading, start game! */
218
219 while (!_exit_game) {
220 if (!_dedicated_forks) DedicatedHandleKeyInput();
221 this->DrainCommandQueue();
222
223 this->Tick();
224 this->SleepTillNextTick();
225
226#if defined(UNIX)
227 if (_dedicated_exit_requested) {
228 if (_game_mode == GameMode::Normal && _settings_client.gui.autosave_on_exit) DoExitSave();
229 _exit_game = true;
230 }
231#endif
232 }
233}
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition factory.hpp:139
virtual uint8_t GetScreenDepth()=0
Get the screen depth this blitter works for.
virtual void PostResize()
Post resize event.
Definition base.hpp:211
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.
Functions related to companies.
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:271
Console functions used outside of the console code.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
bool _dedicated_forks
Whether a fork has been done.
Base for the dedicated video driver.
Dimension _cur_resolution
The current resolution.
Definition driver.cpp:29
Error reporting related functions.
Factory to 'query' all available blitters.
Types for standard in/out file operations.
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
Declarations for savegames operations.
Functions related to world/map generation.
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:50
Functions related to the gfx engine.
bool _is_network_server
Does this client wants to be a network-server?
Definition network.cpp:71
bool _network_dedicated
are we a dedicated server?
Definition network.cpp:70
Basic functions/variables used all over the place.
bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir, std::shared_ptr< LoadFilter > lf)
Load the specified savegame but on error do different things.
Definition openttd.cpp:939
Variables and function used internally.
GameMode
Mode which defines the state of the game.
Definition openttd.h:18
@ Normal
Playing a game.
Definition openttd.h:20
@ LoadGame
Load game, Play Scenario.
Definition openttd.h:32
@ StartHeightmap
Load a heightmap and start a new game from it.
Definition openttd.h:38
A number of safeguards to prevent using unsafe methods.
void DoExitSave()
Do a save when exiting the game (_settings_client.gui.autosave_on_exit).
Functions/types related to saving and loading games.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
Definition of base types and functions in a cross-platform compatible way.
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
Interface for filtering a savegame till it is loaded.
Base of all threads.
void SetCurrentThreadName(const std::string &thread_name)
Name the thread this function is called on for the debugger.
Definition unix.cpp:245
Declarations of functions for MS windows systems.
Window functions not directly related to making/drawing windows.