Compare commits

...

10 Commits

Author SHA1 Message Date
DustyBagel
a15e0d09cd
Possible fix for check errors. 2024-06-27 19:14:36 -05:00
DustyBagel
6f9bbea49a Add main.cpp to CMakeLists.txt 2024-06-27 18:46:35 -05:00
DustyBagel
eff77e1f7f Merge branch 'master' of https://github.com/DustyBagel/minetest-lan 2024-06-27 17:53:40 -05:00
DustyBagel
cacaaec14e Remove unneeded freeminer code. 2024-06-27 17:48:42 -05:00
DustyBagel
9ff9b30e0f Remove unneeded freeminer code. 2024-06-27 17:45:13 -05:00
DustyBagel
c7c3adabca
Merge branch 'minetest:master' into master 2024-06-27 17:43:21 -05:00
grorp
9a1501ae89
CIrrDeviceSDL: Fix numpad key events not having correct KeyInput.Char (#14780)
Allows you to change viewing range using numpad +/- again. This fix also works with the current unreleased version of SDL 3.

The keycodes for numpad keys (both SDL keycodes and Irrlicht keycodes) are not the same as the keycodes for the equivalent non-numpad keys and don't correspond to chars, so I mapped them to chars manually.

Since I think the resolution of https://github.com/minetest/minetest/issues/13770 was "just disable numlock", I made sure to only do this for the numpad number keys if numlock is enabled.
2024-06-27 14:44:44 +02:00
Erich Schubert
514e106414
Fix missing newline before Markdown list (#14783)
Renders incorrectly e.g. on https://api.minetest.net/spatial-vectors/
2024-06-26 22:21:18 +02:00
grorp
4c001bd248
Make button sprites (scrollbar arrows) DPI-aware (#14772) 2024-06-26 15:25:27 +02:00
DustyBagel
eae9fa4e95 Merge https://github.com/minetest/minetest 2024-06-25 13:45:56 -05:00
22 changed files with 135 additions and 503 deletions

@ -3902,6 +3902,7 @@ Operators
---------
Operators can be used if all of the involved vectors have metatables:
* `v1 == v2`:
* Returns whether `v1` and `v2` are identical.
* `-v`:

@ -200,7 +200,7 @@ class IGUIButton : public IGUIElement
\param loop: True if the animation should loop, false if not
\param scale: True if the sprite should scale to button size, false if not */
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
video::SColor color = video::SColor(255, 255, 255, 255), bool loop = false, bool scale = false) = 0;
video::SColor color = video::SColor(255, 255, 255, 255), bool loop = false) = 0;
//! Get the sprite-index for the given state or -1 when no sprite is set
virtual s32 getSpriteIndex(EGUI_BUTTON_STATE state) const = 0;
@ -211,9 +211,6 @@ class IGUIButton : public IGUIElement
//! Returns if the sprite in the given state does loop
virtual bool getSpriteLoop(EGUI_BUTTON_STATE state) const = 0;
//! Returns if the sprite in the given state is scaled
virtual bool getSpriteScale(EGUI_BUTTON_STATE state) const = 0;
//! Sets if the button should behave like a push button.
/** Which means it can be in two states: Normal or Pressed. With a click on the button,
the user can change the state of the button. */

@ -374,6 +374,12 @@ const c8 *const GUISkinFontNames[EGDF_COUNT + 1] = {
class IGUISkin : virtual public IReferenceCounted
{
public:
//! returns display density scaling factor
virtual float getScale() const = 0;
//! sets display density scaling factor
virtual void setScale(float scale) = 0;
//! returns default color
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0;

@ -75,12 +75,11 @@ void CGUIButton::setSpriteBank(IGUISpriteBank *sprites)
SpriteBank = sprites;
}
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
{
ButtonSprites[(u32)state].Index = index;
ButtonSprites[(u32)state].Color = color;
ButtonSprites[(u32)state].Loop = loop;
ButtonSprites[(u32)state].Scale = scale;
}
//! Get the sprite-index for the given state or -1 when no sprite is set
@ -101,12 +100,6 @@ bool CGUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const
return ButtonSprites[(u32)state].Loop;
}
//! Returns if the sprite in the given state is scaled
bool CGUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const
{
return ButtonSprites[(u32)state].Scale;
}
//! called if an event happened.
bool CGUIButton::OnEvent(const SEvent &event)
{
@ -294,19 +287,26 @@ void CGUIButton::draw()
void CGUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di &center)
{
u32 stateIdx = (u32)state;
s32 spriteIdx = ButtonSprites[stateIdx].Index;
if (spriteIdx == -1)
return;
if (ButtonSprites[stateIdx].Index != -1) {
if (ButtonSprites[stateIdx].Scale) {
const video::SColor colors[] = {ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color};
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect,
&AbsoluteClippingRect, colors,
os::Timer::getTime() - startTime, ButtonSprites[stateIdx].Loop);
} else {
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, os::Timer::getTime(),
ButtonSprites[stateIdx].Loop, true);
}
}
u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber;
core::rect<s32> srcRect = SpriteBank->getPositions()[rectIdx];
IGUISkin *skin = Environment->getSkin();
s32 scale = std::max(std::floor(skin->getScale()), 1.0f);
core::rect<s32> rect(center, srcRect.getSize() * scale);
rect -= rect.getSize() / 2;
const video::SColor colors[] = {
ButtonSprites[stateIdx].Color,
ButtonSprites[stateIdx].Color,
ButtonSprites[stateIdx].Color,
ButtonSprites[stateIdx].Color,
};
SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors,
os::Timer::getTime() - startTime, ButtonSprites[stateIdx].Loop);
}
EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const

@ -92,7 +92,7 @@ class CGUIButton : public IGUIButton
*/
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
video::SColor color = video::SColor(255, 255, 255, 255),
bool loop = false, bool scale = false) override;
bool loop = false) override;
//! Get the sprite-index for the given state or -1 when no sprite is set
s32 getSpriteIndex(EGUI_BUTTON_STATE state) const override;
@ -103,9 +103,6 @@ class CGUIButton : public IGUIButton
//! Returns if the sprite in the given state does loop
bool getSpriteLoop(EGUI_BUTTON_STATE state) const override;
//! Returns if the sprite in the given state is scaled
bool getSpriteScale(EGUI_BUTTON_STATE state) const override;
//! Sets if the button should behave like a push button. Which means it
//! can be in two states: Normal or Pressed. With a click on the button,
//! the user can change the state of the button.
@ -158,19 +155,18 @@ class CGUIButton : public IGUIButton
struct ButtonSprite
{
ButtonSprite() :
Index(-1), Loop(false), Scale(false)
Index(-1), Loop(false)
{
}
bool operator==(const ButtonSprite &other) const
{
return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
return Index == other.Index && Color == other.Color && Loop == other.Loop;
}
s32 Index;
video::SColor Color;
bool Loop;
bool Scale;
};
ButtonSprite ButtonSprites[EGBS_COUNT];

@ -24,6 +24,12 @@ class CGUISkin : public IGUISkin
//! destructor
virtual ~CGUISkin();
//! returns display density scaling factor
virtual float getScale() const override { return Scale; }
//! sets display density scaling factor
virtual void setScale(float scale) override { Scale = scale; }
//! returns default color
video::SColor getColor(EGUI_DEFAULT_COLOR color) const override;
@ -210,6 +216,7 @@ class CGUISkin : public IGUISkin
EGUI_SKIN_TYPE getType() const override;
private:
float Scale = 1.0f;
video::SColor Colors[EGDC_COUNT];
s32 Sizes[EGDS_COUNT];
u32 Icons[EGDI_COUNT];

@ -129,9 +129,9 @@ EM_BOOL CIrrDeviceSDL::MouseLeaveCallback(int eventType, const EmscriptenMouseEv
}
#endif
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key)
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE irrlichtKey)
{
switch (key) {
switch (irrlichtKey) {
// keys which are known to have safe special character interpretation
// could need changes over time (removals and additions!)
case KEY_RETURN:
@ -189,24 +189,68 @@ bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key)
}
}
int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
int CIrrDeviceSDL::findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock)
{
switch (irrlichtKey) {
// special cases that always return a char regardless of how the SDL keycode
// looks
switch (key) {
case KEY_RETURN:
case KEY_ESCAPE:
return (int)key;
return (int)irrlichtKey;
// This is necessary for keys on the numpad because they don't use the same
// keycodes as their non-numpad versions (whose keycodes correspond to chars),
// but have their own SDL keycodes and their own Irrlicht keycodes (which
// don't correspond to chars).
case KEY_MULTIPLY:
return '*';
case KEY_ADD:
return '+';
case KEY_SUBTRACT:
return '-';
case KEY_DIVIDE:
return '/';
default:
break;
}
if (numlock) {
// Number keys on the numpad are also affected, but we only want them
// to produce number chars when numlock is enabled.
switch (irrlichtKey) {
case KEY_NUMPAD0:
return '0';
case KEY_NUMPAD1:
return '1';
case KEY_NUMPAD2:
return '2';
case KEY_NUMPAD3:
return '3';
case KEY_NUMPAD4:
return '4';
case KEY_NUMPAD5:
return '5';
case KEY_NUMPAD6:
return '6';
case KEY_NUMPAD7:
return '7';
case KEY_NUMPAD8:
return '8';
case KEY_NUMPAD9:
return '9';
default:
break;
}
}
// SDL in-place ORs values with no character representation with 1<<30
// https://wiki.libsdl.org/SDL2/SDLKeycodeLookup
if (assumedChar & (1 << 30))
// This also affects the numpad keys btw.
if (sdlKey & (1 << 30))
return 0;
switch (key) {
switch (irrlichtKey) {
case KEY_PRIOR:
case KEY_NEXT:
case KEY_HOME:
@ -218,7 +262,7 @@ int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
case KEY_NUMLOCK:
return 0;
default:
return assumedChar;
return sdlKey;
}
}
@ -656,7 +700,7 @@ bool CIrrDeviceSDL::run()
{
os::Timer::tick();
SEvent irrevent;
SEvent irrevent{};
SDL_Event SDL_event;
while (!Close && wrap_PollEvent(&SDL_event)) {
@ -825,7 +869,8 @@ bool CIrrDeviceSDL::run()
irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL) != 0;
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key);
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key,
(SDL_event.key.keysym.mod & KMOD_NUM) != 0);
postEventFromUser(irrevent);
} break;

@ -273,10 +273,10 @@ class CIrrDeviceSDL : public CIrrDeviceStub
#endif
// Check if a key is a known special character with no side effects on text boxes.
static bool keyIsKnownSpecial(EKEY_CODE key);
static bool keyIsKnownSpecial(EKEY_CODE irrlichtKey);
// Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key);
static int findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock);
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
void resetReceiveTextInputEvents();

@ -417,7 +417,6 @@ set(common_SRCS
light.cpp
lighting.cpp
log.cpp
#log_types.cpp
main.cpp
map.cpp
map_settings_manager.cpp

@ -353,6 +353,7 @@ void ClientLauncher::config_guienv()
float density = rangelim(g_settings->getFloat("gui_scaling"), 0.5f, 20) *
RenderingEngine::getDisplayDensity();
skin->setScale(density);
skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * density));
skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(21.0f * density));
skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density));

@ -1,96 +0,0 @@
#pragma once
#include "porting.h"
#if defined(linux) || defined(__linux)
#include <sys/prctl.h>
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
#include <pthread.h>
#include <pthread_np.h>
#elif defined(__NetBSD__)
#include <pthread.h>
#elif defined(__APPLE__)
#include <pthread.h>
#endif
#if defined(linux) || defined(__linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define PORTING_USE_PTHREAD 1
#include <pthread.h>
#endif
namespace porting
{
extern std::atomic_bool g_sighup, g_siginfo;
#if defined(linux) || defined(__linux)
inline void setThreadName(const char *name) {
/* It would be cleaner to do this with pthread_setname_np,
* which was added to glibc in version 2.12, but some major
* distributions are still runing 2.11 and previous versions.
*/
prctl(PR_SET_NAME, name);
}
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
inline void setThreadName(const char *name) {
pthread_set_name_np(pthread_self(), name);
}
#elif defined(__NetBSD__)
inline void setThreadName(const char *name) {
pthread_setname_np(pthread_self(), name);
}
#elif defined(_MSC_VER)
typedef struct tagTHREADNAME_INFO {
DWORD dwType; // must be 0x1000
LPCSTR szName; // pointer to name (in user addr space)
DWORD dwThreadID; // thread ID (-1=caller thread)
DWORD dwFlags; // reserved for future use, must be zero
} THREADNAME_INFO;
inline void setThreadName(const char *name) {
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = -1;
info.dwFlags = 0;
__try {
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *) &info);
} __except (EXCEPTION_CONTINUE_EXECUTION) {}
}
#elif defined(__APPLE__)
inline void setThreadName(const char *name) {
pthread_setname_np(name);
}
#elif defined(_WIN32) || defined(__GNU__)
inline void setThreadName(const char* name) {}
#else
#ifndef __EMSCRIPTEN__
#warning "Unrecognized platform, thread names will not be available."
#endif
inline void setThreadName(const char* name) {}
#endif
inline void setThreadPriority(int priority) {
#if PORTING_USE_PTHREAD
// http://en.cppreference.com/w/cpp/thread/thread/native_handle
sched_param sch;
//int policy;
//pthread_getschedparam(pthread_self(), &policy, &sch);
sch.sched_priority = priority;
if(pthread_setschedparam(pthread_self(), SCHED_FIFO /*SCHED_RR*/, &sch)) {
//std::cout << "Failed to setschedparam: " << std::strerror(errno) << '\n';
}
#endif
}
#ifndef SERVER
//void irr_device_wait_egl (irr::IrrlichtDevice * device = nullptr);
#endif
}

@ -89,12 +89,11 @@ void GUIButton::setSpriteBank(IGUISpriteBank* sprites)
SpriteBank = sprites;
}
void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)
void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
{
ButtonSprites[(u32)state].Index = index;
ButtonSprites[(u32)state].Color = color;
ButtonSprites[(u32)state].Loop = loop;
ButtonSprites[(u32)state].Scale = scale;
}
//! Get the sprite-index for the given state or -1 when no sprite is set
@ -115,12 +114,6 @@ bool GUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const
return ButtonSprites[(u32)state].Loop;
}
//! Returns if the sprite in the given state is scaled
bool GUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const
{
return ButtonSprites[(u32)state].Scale;
}
//! called if an event happened.
bool GUIButton::OnEvent(const SEvent& event)
{
@ -354,23 +347,26 @@ void GUIButton::draw()
void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center)
{
u32 stateIdx = (u32)state;
s32 spriteIdx = ButtonSprites[stateIdx].Index;
if (spriteIdx == -1)
return;
if (ButtonSprites[stateIdx].Index != -1)
{
if ( ButtonSprites[stateIdx].Scale )
{
const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color};
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect.UpperLeftCorner,
&AbsoluteClippingRect, colors[0], // FIXME: remove [0]
porting::getTimeMs()-startTime, ButtonSprites[stateIdx].Loop);
}
else
{
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, porting::getTimeMs(),
ButtonSprites[stateIdx].Loop, true);
}
}
u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber;
core::rect<s32> srcRect = SpriteBank->getPositions()[rectIdx];
IGUISkin *skin = Environment->getSkin();
s32 scale = std::max(std::floor(skin->getScale()), 1.0f);
core::rect<s32> rect(center, srcRect.getSize() * scale);
rect -= rect.getSize() / 2;
const video::SColor colors[] = {
ButtonSprites[stateIdx].Color,
ButtonSprites[stateIdx].Color,
ButtonSprites[stateIdx].Color,
ButtonSprites[stateIdx].Color,
};
SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors,
porting::getTimeMs() - startTime, ButtonSprites[stateIdx].Loop);
}
EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const

@ -92,7 +92,7 @@ class GUIButton : public gui::IGUIButton
*/
virtual void setSprite(gui::EGUI_BUTTON_STATE state, s32 index,
video::SColor color=video::SColor(255,255,255,255),
bool loop=false, bool scale=false) override;
bool loop=false) override;
//! Get the sprite-index for the given state or -1 when no sprite is set
virtual s32 getSpriteIndex(gui::EGUI_BUTTON_STATE state) const override;
@ -103,9 +103,6 @@ class GUIButton : public gui::IGUIButton
//! Returns if the sprite in the given state does loop
virtual bool getSpriteLoop(gui::EGUI_BUTTON_STATE state) const override;
//! Returns if the sprite in the given state is scaled
virtual bool getSpriteScale(gui::EGUI_BUTTON_STATE state) const override;
//! Sets if the button should behave like a push button. Which means it
//! can be in two states: Normal or Pressed. With a click on the button,
//! the user can change the state of the button.
@ -230,13 +227,12 @@ class GUIButton : public gui::IGUIButton
{
bool operator==(const ButtonSprite &other) const
{
return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
return Index == other.Index && Color == other.Color && Loop == other.Loop;
}
s32 Index = -1;
video::SColor Color;
bool Loop = false;
bool Scale = false;
};
ButtonSprite ButtonSprites[gui::EGBS_COUNT];

@ -27,6 +27,12 @@ namespace gui
//! destructor
virtual ~GUISkin();
//! returns display density scaling factor
virtual float getScale() const { return Scale; }
//! sets display density scaling factor
virtual void setScale(float scale) { Scale = scale; }
//! returns default color
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
@ -292,6 +298,7 @@ namespace gui
private:
float Scale = 1.0f;
video::SColor Colors[EGDC_COUNT];
s32 Sizes[EGDS_COUNT];
u32 Icons[EGDI_COUNT];

@ -1,101 +0,0 @@
/*
This file is part of Freeminer.
Freeminer 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 3 of the License, or
(at your option) any later version.
Freeminer 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 Freeminer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "log_types.h"
#include "convert_json.h"
#include "irr_v3d.h"
#include "network/address.h"
std::ostream &operator<<(std::ostream &s, const v2s16 &p)
{
s << "(" << p.X << "," << p.Y << ")";
return s;
}
std::ostream &operator<<(std::ostream &s, const v2s32 &p)
{
s << "(" << p.X << "," << p.Y << ")";
return s;
}
std::ostream &operator<<(std::ostream &s, const v2f &p)
{
s << "(" << p.X << "," << p.Y << ")";
return s;
}
std::ostream &operator<<(std::ostream &s, const v3pos_t &p)
{
s << "(" << p.X << "," << p.Y << "," << p.Z << ")";
return s;
}
std::ostream &operator<<(std::ostream &s, const v3f &p)
{
s << "(" << p.X << "," << p.Y << "," << p.Z << ")";
return s;
}
#if USE_OPOS64
std::ostream &operator<<(std::ostream &s, const v3opos_t &p)
{
s << "(" << p.X << "," << p.Y << "," << p.Z << ")";
return s;
}
#endif
std::ostream &operator<<(std::ostream &s, const std::map<v3pos_t, unsigned int> &p)
{
for (auto &i : p)
s << i.first << "=" << i.second << " ";
return s;
}
std::ostream &operator<<(std::ostream &s, const irr::video::SColor &c)
{
s << "c32(" << c.color << ": a=" << c.getAlpha() << ",r=" << c.getRed()
<< ",g=" << c.getGreen() << ",b=" << c.getBlue() << ")";
return s;
}
std::ostream &operator<<(std::ostream &s, const irr::video::SColorf &c)
{
s << "cf32("
<< "a=" << c.getAlpha() << ",r=" << c.getRed() << ",g=" << c.getGreen()
<< ",b=" << c.getBlue() << ")";
return s;
}
#include "util/string.h"
std::ostream &operator<<(std::ostream &s, const std::wstring &w)
{
s << wide_to_utf8(w);
return s;
}
std::ostream &operator<<(std::ostream &s, const Json::Value &json)
{
s << fastWriteJson(json);
return s;
}
std::ostream &operator<<(std::ostream &s, const Address &addr)
{
addr.print(s);
// s << addr.getPort();
return s;
}

@ -1,55 +0,0 @@
/*
This file is part of Freeminer.
Freeminer 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 3 of the License, or
(at your option) any later version.
Freeminer 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 Freeminer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOG_TYPES_HEADER
#define LOG_TYPES_HEADER
//#include "log.h" //for replacing log.h to log_types.h in includes
#include "irr_v2d.h"
#include "irr_v3d.h"
#include <ostream>
std::ostream &operator<<(std::ostream &s, const v2s16 &p);
std::ostream &operator<<(std::ostream &s, const v2s32 &p);
std::ostream &operator<<(std::ostream &s, const v2f &p);
std::ostream &operator<<(std::ostream &s, const v3pos_t &p);
std::ostream &operator<<(std::ostream &s, const v3f &p);
#if USE_OPOS64
std::ostream &operator<<(std::ostream &s, const v3opos_t &p);
#endif
#include <SColor.h>
std::ostream &operator<<(std::ostream &s, const irr::video::SColor &c);
std::ostream &operator<<(std::ostream &s, const irr::video::SColorf &c);
#include <map>
std::ostream &operator<<(std::ostream &s, const std::map<v3pos_t, unsigned int> &p);
std::ostream &operator<<(std::ostream &s, const std::wstring &w);
namespace Json
{
class Value;
};
//std::ostream &operator<<(std::ostream &s, const Json::Value &json);
class Address;
std::ostream &operator<<(std::ostream &s, const Address &addr);
#endif

@ -31,7 +31,7 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
#include "debug.h"
#include "json/json.h"
#include "porting.h"
#include "threading/thread_vector.h"
#include "threading/thread.h"
#include "threading/concurrent_map.h"
#include "network/address.h"
@ -71,13 +71,13 @@ typedef int socket_t;
const static unsigned short int adv_port = 29998;
static std::string ask_str;
lan_adv::lan_adv() : thread_vector("lan_adv")
lan_adv::lan_adv() : Thread("lan_adv")
{
}
void lan_adv::ask()
{
reanimate();
if (!isRunning()) start();
if (ask_str.empty()) {
Json::Value j;
@ -169,14 +169,15 @@ void lan_adv::send_string(const std::string &str)
void lan_adv::serve(unsigned short port)
{
server_port = port;
restart();
if (isRunning()) stop();
start();
}
void *lan_adv::run()
{
BEGIN_DEBUG_EXCEPTION_HANDLER;
reg("LanAdv" + (server_port ? std::string("Server") : std::string("Client")));
setName("LanAdv" + (server_port ? std::string("Server") : std::string("Client")));
UDPSocket socket_recv(true);
int set_option_off = 0, set_option_on = 1;

@ -19,14 +19,14 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <json/value.h>
#include "json/json.h"
#include <string>
#include <atomic>
#include "threading/thread_vector.h"
#include "threading/thread.h"
#include "threading/concurrent_map.h"
class lan_adv : public thread_vector
class lan_adv : public Thread
{
public:
void *run();
@ -43,4 +43,4 @@ class lan_adv : public thread_vector
private:
unsigned short server_port = 0;
};
};

@ -50,18 +50,6 @@ void lan_get() {
lan_adv_client.ask();
}
/*
if (ask_str.empty()) {
Json::Value j;
j["cmd"] = "ask";
j["proto_min"] = Server::getProtocolVersionMin();
j["proto_max"] = Server::getProtocolVersionMax();
ask_str = fastWriteJson(j);
};
lan_adv_client.send_string(ask_str);
*/
bool lan_fresh() {
auto result = lan_adv_client.fresh.load();
lan_adv_client.fresh = false;

@ -3,6 +3,5 @@ set(JTHREAD_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/thread.cpp
${CMAKE_CURRENT_SOURCE_DIR}/semaphore.cpp
${CMAKE_CURRENT_SOURCE_DIR}/lock.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread_vector.cpp
PARENT_SCOPE)

@ -1,118 +0,0 @@
#include "thread_vector.h"
#include "fm_porting.h"
#include "log.h"
#include "porting.h"
thread_vector::thread_vector(const std::string &name, int priority) :
m_name(name), m_priority(priority)
{
request_stop = false;
};
thread_vector::~thread_vector()
{
join();
};
void thread_vector::func()
{
reg();
run();
};
void thread_vector::reg(const std::string &name, int priority)
{
if (!name.empty())
m_name = name;
porting::setThreadName(m_name.c_str());
g_logger.registerThread(m_name);
if (priority)
m_priority = priority;
if (m_priority)
porting::setThreadPriority(m_priority);
};
void thread_vector::start(const size_t n)
{
#if !NDEBUG
infostream << "start thread " << m_name << " n=" << n << std::endl;
#endif
request_stop = false;
for (size_t i = 0; i < n; ++i) {
workers.emplace_back(&thread_vector::func, this);
}
}
void thread_vector::stop()
{
request_stop = true;
}
void thread_vector::join()
{
stop();
for (auto &worker : workers) {
try {
if (worker.joinable()) {
worker.join();
}
} catch (...) {
}
}
workers.clear();
}
void thread_vector::restart(size_t n)
{
join();
start(n);
}
void thread_vector::reanimate(size_t n)
{
if (workers.empty()) {
start(n);
}
}
void thread_vector::sleep(const int seconds)
{
for (int i = 0; i <= seconds; ++i) {
std::this_thread::sleep_for(std::chrono::seconds(1));
if (request_stop) {
return;
}
}
}
// JThread compat:
bool thread_vector::stopRequested()
{
return request_stop;
}
bool thread_vector::isRunning()
{
return !workers.empty();
}
void thread_vector::wait()
{
join();
};
void thread_vector::kill()
{
join();
};
void *thread_vector::run()
{
return nullptr;
};
bool thread_vector::isCurrentThread()
{
auto thread_me = std::hash<std::thread::id>()(std::this_thread::get_id());
for (auto &worker : workers)
if (thread_me == std::hash<std::thread::id>()(worker.get_id()))
return true;
return false;
}

@ -1,37 +0,0 @@
#pragma once
#include <atomic>
#include <thread>
#include <vector>
#include <string>
class thread_vector {
public:
std::vector<std::thread> workers;
std::atomic_bool request_stop;
thread_vector(const std::string &name = "Unnamed", int priority = 0);
virtual ~thread_vector();
virtual void func();
void reg (const std::string &name = "", int priority = 0);
void start (const size_t n = 1);
void restart (const size_t n = 1);
void reanimate (const size_t n = 1);
void stop ();
void join ();
void sleep(const int second);
// Thread compat:
bool stopRequested();
bool isRunning();
void wait();
void kill();
virtual void * run() = 0;
bool isCurrentThread();
protected:
std::string m_name;
int m_priority = 0;
};