Merge branch 'master' of github.com:traintastic/traintastic

Dieser Commit ist enthalten in:
Reinder Feenstra 2022-05-28 10:44:45 +02:00
Commit feab3a6c52
6 geänderte Dateien mit 244 neuen und 6 gelöschten Zeilen

Datei anzeigen

@ -157,7 +157,7 @@ bool Session::processMessage(const Message& message)
{
if(ObjectPtr object = m_handles.getItem(message.read<Handle>()))
{
if(AbstractProperty* property = object->getProperty(message.read<std::string>()))
if(AbstractProperty* property = object->getProperty(message.read<std::string>()); property && !property->isInternal())
{
try
{
@ -206,7 +206,7 @@ bool Session::processMessage(const Message& message)
{
if(ObjectPtr object = m_handles.getItem(message.read<Handle>()))
{
if(AbstractUnitProperty* property = dynamic_cast<AbstractUnitProperty*>(object->getProperty(message.read<std::string>())))
if(AbstractUnitProperty* property = dynamic_cast<AbstractUnitProperty*>(object->getProperty(message.read<std::string>())); property && !property->isInternal())
{
try
{
@ -225,7 +225,7 @@ bool Session::processMessage(const Message& message)
{
if(ObjectPtr object = m_handles.getItem(message.read<Handle>()))
{
if(AbstractObjectProperty* property = dynamic_cast<AbstractObjectProperty*>(object->getProperty(message.read<std::string>())))
if(AbstractObjectProperty* property = dynamic_cast<AbstractObjectProperty*>(object->getProperty(message.read<std::string>())); property && !property->isInternal())
{
try
{
@ -253,7 +253,7 @@ bool Session::processMessage(const Message& message)
{
if(ObjectPtr object = m_handles.getItem(message.read<Handle>()))
{
if(AbstractMethod* method = object->getMethod(message.read<std::string>()))
if(AbstractMethod* method = object->getMethod(message.read<std::string>()); method && !method->isInternal())
{
const ValueType resultType = message.read<ValueType>();
const uint8_t argumentCount = message.read<uint8_t>();

Datei anzeigen

@ -0,0 +1,97 @@
/**
* server/src/os/windows/registry.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2022 Reinder Feenstra
*
* This program 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; either version 2
* of the License, or (at your option) any later version.
*
* This program 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "registry.hpp"
#include <string>
#include <windows.h>
namespace Windows::Registry {
const char* runKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
//const char* runTraintasticServerKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\TraintasticServer";
const char* startupApprovedKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\Run";
const char* traintasticServerKey = "TraintasticServer";
const WCHAR* traintasticServerKeyW = L"TraintasticServer";
const DWORD startupEnabled = 2;
const DWORD startupDisabled = 3;
bool addRun()
{
bool success = false;
HKEY key;
LSTATUS r = RegOpenKeyExA(HKEY_CURRENT_USER, runKey, 0, KEY_WRITE, &key);
if(r == ERROR_SUCCESS)
{
std::basic_string<WCHAR> path;
path.resize(MAX_PATH);
path[0] = '"';
const DWORD l = GetModuleFileNameW(nullptr, path.data() + 1, path.size() - 1);
if(l > 0)
{
path.resize(1 + l);
path.append(L"\" --tray");
r = RegSetValueExW(key, traintasticServerKeyW, 0, REG_SZ, reinterpret_cast<const BYTE*>(path.c_str()), (path.size() + 1) * sizeof(WCHAR));
success = (r == ERROR_SUCCESS);
}
RegCloseKey(key);
}
return success;
}
bool getStartUpApproved(bool& enabled)
{
bool success = false;
HKEY key;
LSTATUS r = RegOpenKeyExA(HKEY_CURRENT_USER, startupApprovedKey, 0, KEY_READ, &key);
if(r == ERROR_SUCCESS)
{
DWORD data[3];
DWORD size = sizeof(data);
r = RegGetValueA(key, nullptr, traintasticServerKey, RRF_RT_REG_BINARY, nullptr, &data, &size);
if(r == ERROR_SUCCESS)
{
enabled = (data[0] == startupEnabled);
success = true;
}
RegCloseKey(key);
}
return success;
}
bool setStartUpApproved(bool enabled)
{
bool success = false;
HKEY key;
LSTATUS r = RegOpenKeyExA(HKEY_CURRENT_USER, startupApprovedKey, 0, KEY_WRITE, &key);
if(r == ERROR_SUCCESS)
{
DWORD data[3] = {enabled ? startupEnabled : startupDisabled, 0, 0};
DWORD size = sizeof(data);
r = RegSetValueExA(key, traintasticServerKey, 0, REG_BINARY, reinterpret_cast<const BYTE*>(&data), size);
success = (r == ERROR_SUCCESS);
RegCloseKey(key);
}
return success;
}
}

Datei anzeigen

@ -0,0 +1,35 @@
/**
* server/src/os/windows/registry.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2022 Reinder Feenstra
*
* This program 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; either version 2
* of the License, or (at your option) any later version.
*
* This program 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_OS_WINDOWS_REGISTRY_HPP
#define TRAINTASTIC_SERVER_OS_WINDOWS_REGISTRY_HPP
namespace Windows::Registry {
bool addRun();
bool getStartUpApproved(bool& enabled);
bool setStartUpApproved(bool enabled);
}
#endif

Datei anzeigen

@ -25,8 +25,10 @@
#include <version.hpp>
#include <traintastic/codename.hpp>
#include "consolewindow.hpp"
#include "registry.hpp"
#include "../../core/eventloop.hpp"
#include "../../traintastic/traintastic.hpp"
#include "../../utils/setthreadname.hpp"
namespace Windows {
@ -50,6 +52,8 @@ void TrayIcon::remove()
void TrayIcon::run()
{
setThreadName("trayicon");
const LPCSTR windowClassName = "TraintasticServerTrayIcon";
// register window class:
@ -73,9 +77,18 @@ void TrayIcon::run()
s_menu = CreatePopupMenu();
menuAddItem(MenuItem::ShowHideConsole, "Show/hide console", hasConsoleWindow());
menuAddSeperator();
menuAddItem(MenuItem::AllowClientServerRestart, "Allow client to restart server");
menuAddItem(MenuItem::AllowClientServerShutdown, "Allow client to shutdown server");
menuAddSeperator();
menuAddItem(MenuItem::StartAutomaticallyAtLogon, "Start automatically at logon");
menuAddSeperator();
menuAddItem(MenuItem::Restart, "Restart");
menuAddItem(MenuItem::Shutdown, "Shutdown");
bool startUpApproved = false;
Registry::getStartUpApproved(startUpApproved);
menuSetItemChecked(MenuItem::StartAutomaticallyAtLogon, startUpApproved);
// setup tray icon:
static NOTIFYICONDATA notifyIconData;
memset(&notifyIconData, 0, sizeof(notifyIconData));
@ -97,6 +110,9 @@ void TrayIcon::run()
Shell_NotifyIcon(NIM_ADD, &notifyIconData);
// Get settings:
EventLoop::call(getSettings);
// message loop:
while(true)
{
@ -166,8 +182,57 @@ LRESULT CALLBACK TrayIcon::windowProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARA
case MenuItem::ShowHideConsole:
setConsoleWindowVisible(!isConsoleWindowVisible());
return 0;
case MenuItem::AllowClientServerRestart:
{
bool value;
{
std::lock_guard lock{s_settings.mutex};
value = !s_settings.allowClientServerRestart;
}
EventLoop::call(
[value]()
{
Traintastic::instance->settings->allowClientServerRestart = value;
getSettings();
});
break;
}
case MenuItem::AllowClientServerShutdown:
{
bool value;
{
std::lock_guard lock{s_settings.mutex};
value = !s_settings.allowClientServerShutdown;
}
EventLoop::call(
[value]()
{
Traintastic::instance->settings->allowClientServerShutdown = value;
getSettings();
});
break;
}
case MenuItem::StartAutomaticallyAtLogon:
{
bool startUpApproved = !menuGetItemChecked(MenuItem::StartAutomaticallyAtLogon);
if(startUpApproved)
Registry::addRun();
Registry::setStartUpApproved(startUpApproved);
if(Registry::getStartUpApproved(startUpApproved))
menuSetItemChecked(MenuItem::StartAutomaticallyAtLogon, startUpApproved);
break;
}
}
break;
case WM_TRAINTASTIC_SETTINGS:
{
std::lock_guard lock{s_settings.mutex};
menuSetItemChecked(MenuItem::AllowClientServerRestart, s_settings.allowClientServerRestart);
menuSetItemChecked(MenuItem::AllowClientServerShutdown, s_settings.allowClientServerShutdown);
break;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
@ -197,4 +262,28 @@ void TrayIcon::menuAddSeperator()
InsertMenuItem(s_menu, GetMenuItemCount(s_menu), TRUE, &item);
}
bool TrayIcon::menuGetItemChecked(MenuItem id)
{
assert(s_menu);
return GetMenuState(s_menu, static_cast<UINT>(id), MF_BYCOMMAND) & MF_CHECKED;
}
void TrayIcon::menuSetItemChecked(MenuItem id, bool checked)
{
assert(s_menu);
CheckMenuItem(s_menu, static_cast<UINT>(id), checked ? MF_CHECKED : MF_UNCHECKED);
}
void TrayIcon::getSettings()
{
assert(isEventLoopThread());
const auto& settings = *Traintastic::instance->settings.value();
{
std::lock_guard lock{s_settings.mutex};
s_settings.allowClientServerRestart = settings.allowClientServerRestart;
s_settings.allowClientServerShutdown = settings.allowClientServerShutdown;
}
PostMessage(s_window, WM_TRAINTASTIC_SETTINGS, 0, 0);
}
}

Datei anzeigen

@ -25,6 +25,7 @@
#include <memory>
#include <thread>
#include <mutex>
#include <string>
#define _WINSOCKAPI_ // prevent windows.h including winsock.h
#include <windows.h>
@ -43,19 +44,35 @@ class TrayIcon
Shutdown = 1,
Restart = 2,
ShowHideConsole = 3,
AllowClientServerRestart = 4,
AllowClientServerShutdown = 5,
StartAutomaticallyAtLogon = 6,
};
struct TraintasticSettings
{
std::mutex mutex;
bool allowClientServerRestart;
bool allowClientServerShutdown;
};
static constexpr UINT WM_NOTIFYICON_CALLBACK = WM_USER + 1;
static constexpr UINT WM_TRAINTASTIC_SETTINGS = WM_USER + 2;
static std::unique_ptr<std::thread> s_thread;
static HWND s_window;
static HMENU s_menu;
inline static TraintasticSettings s_settings = {{}, false, false};
static void run();
static LRESULT CALLBACK windowProc(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
static void menuAddItem(MenuItem id, const LPSTR text, bool enabled = true);
static void menuAddSeperator();
static bool menuGetItemChecked(MenuItem id);
static void menuSetItemChecked(MenuItem id, bool checked);
static void getSettings();
public:
static void add();

Datei anzeigen

@ -54,8 +54,8 @@ Settings::Settings(const std::filesystem::path& path)
, loadLastWorldOnStartup{this, "load_last_world_on_startup", true, PropertyFlags::ReadWrite, [this](const bool& /*value*/){ saveToFile(); }}
, autoSaveWorldOnExit{this, "auto_save_world_on_exit", false, PropertyFlags::ReadWrite, [this](const bool& /*value*/){ saveToFile(); }}
, saveWorldUncompressed{this, "save_world_uncompressed", false, PropertyFlags::ReadWrite, [this](const bool& /*value*/){ saveToFile(); }}
, allowClientServerRestart{this, "allow_client_server_restart", false, PropertyFlags::ReadWrite, [this](const bool& /*value*/){ saveToFile(); }}
, allowClientServerShutdown{this, "allow_client_server_shutdown", false, PropertyFlags::ReadWrite, [this](const bool& /*value*/){ saveToFile(); }}
, allowClientServerRestart{this, "allow_client_server_restart", false, PropertyFlags::ReadWrite | PropertyFlags::Internal, [this](const bool& /*value*/){ saveToFile(); }}
, allowClientServerShutdown{this, "allow_client_server_shutdown", false, PropertyFlags::ReadWrite | PropertyFlags::Internal, [this](const bool& /*value*/){ saveToFile(); }}
, memoryLoggerSize{this, Name::memoryLoggerSize, Default::memoryLoggerSize, PropertyFlags::ReadWrite, [this](const uint32_t& /*value*/){ saveToFile(); }}
, enableFileLogger{this, Name::enableFileLogger, Default::enableFileLogger, PropertyFlags::ReadWrite, [this](const bool& /*value*/){ saveToFile(); }}
{