File detail.h¶
File List > endstone > detail.h
Go to the documentation of this file
// Copyright (c) 2024, The Endstone Project. (https://endstone.dev) All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdexcept>
#if defined(_WIN32) || defined(_WIN64)
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#else
#include <dlfcn.h>
#endif
#define ENDSTONE_STRINGIFY(x) #x
#define ENDSTONE_TOSTRING(x) ENDSTONE_STRINGIFY(x)
#define ENDSTONE_VERSION_MAJOR 0
#define ENDSTONE_VERSION_MINOR 11
#define ENDSTONE_VERSION_PATCH 0
#define NETWORK_PROTOCOL_VERSION 859
#define ENDSTONE_API_VERSION ENDSTONE_TOSTRING(ENDSTONE_VERSION_MAJOR) "." ENDSTONE_TOSTRING(ENDSTONE_VERSION_MINOR)
#ifndef ENDSTONE_VERSION
#define ENDSTONE_VERSION \
ENDSTONE_TOSTRING(ENDSTONE_VERSION_MAJOR) \
"." ENDSTONE_TOSTRING(ENDSTONE_VERSION_MINOR) "." ENDSTONE_TOSTRING(ENDSTONE_VERSION_PATCH)
#endif
namespace endstone {
class Server;
namespace detail {
template <typename Return, typename... Args>
void *fp_cast(Return (*fp)(Args...))
{
union {
Return (*p)(Args...);
void *v;
} temp;
temp.p = fp;
return temp.v;
}
template <typename Return, typename Class, typename... Args>
void *fp_cast(Return (Class::*fp)(Args...))
{
union {
Return (Class::*p)(Args...);
void *v;
} temp;
temp.p = fp;
return temp.v;
}
template <typename Return, typename Class, typename... Args>
void *fp_cast(Return (Class::*fp)(Args...) const)
{
union {
Return (Class::*p)(Args...) const;
void *v;
} temp;
temp.p = fp;
return temp.v;
}
template <typename Return, typename... Arg>
Return (*fp_cast(Return (*fp)(Arg...), void *func))(Arg...)
{
return *reinterpret_cast<decltype(&fp)>(&func);
}
template <typename Return, typename Class, typename... Arg>
Return (Class::*fp_cast(Return (Class::*fp)(Arg...), void *address))(Arg...)
{
struct { // https://doi.org/10.1145/3660779
void *ptr;
std::size_t adj = 0;
} temp;
temp.ptr = address;
return *reinterpret_cast<decltype(&fp)>(&temp);
}
template <typename Return, typename Class, typename... Arg>
Return (Class::*fp_cast(Return (Class::*fp)(Arg...) const, void *address))(Arg...) const
{
struct { // https://doi.org/10.1145/3660779
void *ptr;
std::size_t adj = 0;
} temp;
temp.ptr = address;
return *reinterpret_cast<decltype(&fp)>(&temp);
}
inline Server &getServer()
{
static Server *server;
if (server == nullptr) {
#ifdef _WIN32
auto handle = GetModuleHandle("endstone_runtime.dll");
#else
auto handle = dlopen("libendstone_runtime.so", RTLD_LAZY);
#endif
if (!handle) {
throw std::runtime_error("Failed to load endstone runtime.");
}
using GetterFn = Server &(*)();
#ifdef _WIN32
auto fn = reinterpret_cast<GetterFn>(GetProcAddress(handle, "endstone_get_server"));
#else
auto fn = reinterpret_cast<GetterFn>(dlsym(handle, "endstone_get_server"));
#endif
if (!fn) {
throw std::runtime_error("Failed to find symbol endstone_get_server");
}
server = &fn();
if (!server) {
throw std::runtime_error("Failed to get server instance.");
}
}
return *server;
}
} // namespace detail
} // namespace endstone