Merge branch 'trunk' of https://github.com/lrre-foss/rnr into trunk

This commit is contained in:
sorket 2023-07-20 01:24:29 -04:00
commit 2df518efe1
41 changed files with 396 additions and 56 deletions

View File

@ -17,13 +17,13 @@ jobs:
shell: msys2 {0} shell: msys2 {0}
steps: steps:
- uses: actions/checkout@v3 - name: Checkout repository
name: Clone repository uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- uses: msys2/setup-msys2@v2 - name: Set up MSYS2 and install required packages
name: Set up MSYS2 and install required packages uses: msys2/setup-msys2@v2
with: with:
msystem: ${{ matrix.sys }} msystem: ${{ matrix.sys }}
install: >- install: >-
@ -34,6 +34,7 @@ jobs:
mingw-w64-${{ matrix.env }}-pugixml mingw-w64-${{ matrix.env }}-pugixml
mingw-w64-${{ matrix.env }}-ogre3d mingw-w64-${{ matrix.env }}-ogre3d
mingw-w64-${{ matrix.env }}-qt6 mingw-w64-${{ matrix.env }}-qt6
mingw-w64-${{ matrix.env }}-bullet
- name: Generate Ninja build files - name: Generate Ninja build files
run: cmake -G Ninja -B build -DCI=ON -DCMAKE_BUILD_TYPE=${{ matrix.configuration == 'Release' && 'MinSizeRel' || matrix.configuration }} . run: cmake -G Ninja -B build -DCI=ON -DCMAKE_BUILD_TYPE=${{ matrix.configuration == 'Release' && 'MinSizeRel' || matrix.configuration }} .
@ -58,7 +59,7 @@ jobs:
run: mkdir build/dist/shaders && cp -R /${{ matrix.sys }}/share/OGRE/Media/Main/* build/dist/shaders && cp -R /${{ matrix.sys }}/share/OGRE/Media/RTShaderLib/* build/dist/shaders run: mkdir build/dist/shaders && cp -R /${{ matrix.sys }}/share/OGRE/Media/Main/* build/dist/shaders && cp -R /${{ matrix.sys }}/share/OGRE/Media/RTShaderLib/* build/dist/shaders
- name: Add additional runtime dependencies - name: Add additional runtime dependencies
run: ldd build/dist/*.exe | grep "=> /" | awk '{print $3}' | grep "clang64" | xargs -I '{}' cp -v '{}' build/dist run: ldd build/dist/*.exe | grep "=> /" | awk '{print $3}' | grep "${{ matrix.sys }}" | xargs -I '{}' cp -v '{}' build/dist
- name: Set output variables - name: Set output variables
id: vars id: vars

View File

@ -16,11 +16,13 @@ add_compile_options(-Wno-attributes -Wno-return-type) # Ignore warnings generate
find_package(Boost REQUIRED) find_package(Boost REQUIRED)
find_package(OGRE REQUIRED COMPONENTS Bites CONFIG) find_package(OGRE REQUIRED COMPONENTS Bites CONFIG)
find_package(pugixml REQUIRED) find_package(pugixml REQUIRED)
find_package(Bullet CONFIG REQUIRED)
set(RNR_BULLET_LIBRARIES LinearMath Bullet3Common BulletDynamics BulletSoftBody BulletCollision BulletInverseDynamics)
add_subdirectory(Projects) add_subdirectory(Projects)
if(CI AND UNIX) if(CI AND UNIX)
file(COPY ${OGRE_MEDIA_DIR}/Main/ DESTINATION ${CMAKE_BINARY_DIR}/shaders) file(COPY ${OGRE_MEDIA_DIR}/ShadowVolume/ DESTINATION ${CMAKE_BINARY_DIR}/shaders)
file(COPY ${OGRE_MEDIA_DIR}/RTShaderLib/ DESTINATION ${CMAKE_BINARY_DIR}/shaders) file(COPY ${OGRE_MEDIA_DIR}/RTShaderLib/ DESTINATION ${CMAKE_BINARY_DIR}/shaders)
file(COPY ${OGRE_PLUGIN_DIR}/ DESTINATION ${CMAKE_BINARY_DIR}/plugins) file(COPY ${OGRE_PLUGIN_DIR}/ DESTINATION ${CMAKE_BINARY_DIR}/plugins)
endif() endif()

View File

@ -16,7 +16,6 @@ material materials/partinstanced
rtshader_system rtshader_system
{ {
transform_stage instanced
lighting_stage per_pixel lighting_stage per_pixel
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -34,6 +34,7 @@ namespace RNR
Ogre::SceneManager* ogreSceneManager; Ogre::SceneManager* ogreSceneManager;
Ogre::Camera* ogreCamera; Ogre::Camera* ogreCamera;
Ogre::Viewport* ogreViewport; Ogre::Viewport* ogreViewport;
Ogre::Light* ogreSceneLight;
Ogre::RTShader::ShaderGenerator* ogreShaderGen; Ogre::RTShader::ShaderGenerator* ogreShaderGen;
QCursor cursor; QCursor cursor;

View File

@ -1,11 +1,13 @@
#include <OgreWidget.hpp> #include <OgreWidget.hpp>
#include <QApplication> #include <QApplication>
#include <filesystem>
#include <OGRE/Bites/OgreSGTechniqueResolverListener.h> #include <OGRE/Bites/OgreSGTechniqueResolverListener.h>
#include <OGRE/OgreDefaultDebugDrawer.h> #include <OGRE/OgreDefaultDebugDrawer.h>
#include <OGRE/Overlay/OgreOverlaySystem.h> #include <OGRE/Overlay/OgreOverlaySystem.h>
#include <OGRE/Overlay/OgreOverlayManager.h> #include <OGRE/Overlay/OgreOverlayManager.h>
#include <OGRE/Overlay/OgreFontManager.h> #include <OGRE/Overlay/OgreFontManager.h>
#include <App/V8/DataModel/Lighting.hpp>
#ifdef __unix__ #ifdef __unix__
#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformnativeinterface.h>
@ -70,6 +72,11 @@ namespace RNR
if(Ogre::RTShader::ShaderGenerator::initialize()) if(Ogre::RTShader::ShaderGenerator::initialize())
{ {
ogreShaderGen = Ogre::RTShader::ShaderGenerator::getSingletonPtr(); ogreShaderGen = Ogre::RTShader::ShaderGenerator::getSingletonPtr();
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
std::filesystem::create_directory("ShaderCache");
}
ogreShaderGen->setShaderCachePath("ShaderCache/"); ogreShaderGen->setShaderCachePath("ShaderCache/");
ogreShaderGen->addSceneManager(ogreSceneManager); ogreShaderGen->addSceneManager(ogreSceneManager);
@ -90,19 +97,19 @@ namespace RNR
pFont->setTrueTypeSize(16); pFont->setTrueTypeSize(16);
pFont->load(); pFont->load();
ogreSceneManager->setShadowTechnique(Ogre::ShadowTechnique::SHADOWTYPE_STENCIL_ADDITIVE); ogreSceneManager->setShadowTechnique(Ogre::ShadowTechnique::SHADOWTYPE_STENCIL_MODULATIVE);
ogreSceneManager->setShadowFarDistance(500.f); ogreSceneManager->setShadowFarDistance(500.f);
Ogre::Light* light = ogreSceneManager->createLight("SunLight"); ogreSceneLight = ogreSceneManager->createLight("SunLight");
Ogre::SceneNode* lightNode = ogreSceneManager->getRootSceneNode()->createChildSceneNode(); Ogre::SceneNode* lightNode = ogreSceneManager->getRootSceneNode()->createChildSceneNode();
lightNode->setPosition(0, 10, 15); lightNode->setPosition(0, 10, 15);
lightNode->setDirection(-0.25, -0.5, -0.5); lightNode->setDirection(-0.25, -0.5, -0.5);
lightNode->attachObject(light); lightNode->attachObject(ogreSceneLight);
light->setCastShadows(true); ogreSceneLight->setCastShadows(true);
light->setDiffuseColour(0.9, 0.9, 1.0); ogreSceneLight->setDiffuseColour(0.9, 0.9, 1.0);
light->setSpecularColour(1.0, 1.0, 1.0); ogreSceneLight->setSpecularColour(1.0, 1.0, 1.0);
light->setType(Ogre::Light::LT_DIRECTIONAL); ogreSceneLight->setType(Ogre::Light::LT_DIRECTIONAL);
Ogre::MaterialManager::getSingletonPtr()->reloadAll(); Ogre::MaterialManager::getSingletonPtr()->reloadAll();
Ogre::MaterialManager::getSingletonPtr()->load("sky/null_plainsky512", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); Ogre::MaterialManager::getSingletonPtr()->load("sky/null_plainsky512", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
@ -127,6 +134,21 @@ namespace RNR
ogreCamera->getParentSceneNode()->setOrientation(Ogre::Quaternion(cam->getCFrame().getRotation())); ogreCamera->getParentSceneNode()->setOrientation(Ogre::Quaternion(cam->getCFrame().getRotation()));
} }
RNR::Lighting* lighting = (RNR::Lighting*)world->getDatamodel()->getService("Lighting");
if(lighting)
{
Ogre::Vector3 clearColor = lighting->getClearColor();
ogreViewport->setBackgroundColour(Ogre::ColourValue(clearColor.x, clearColor.y, clearColor.z));
Ogre::Vector3 shadowColor = lighting->getShadowColor();
ogreSceneManager->setShadowColour(Ogre::ColourValue(shadowColor.x, shadowColor.y, shadowColor.z));
Ogre::Vector3 topAmbient = lighting->getTopAmbient();
ogreSceneLight->setDiffuseColour(Ogre::ColourValue(topAmbient.x, topAmbient.y, topAmbient.z));
Ogre::Vector3 bottomAmbient = lighting->getBottomAmbient();
ogreSceneManager->setAmbientLight(Ogre::ColourValue(bottomAmbient.x, bottomAmbient.y, bottomAmbient.z));
Ogre::Vector3 spotLight = lighting->getSpotLight();
ogreSceneLight->setSpecularColour(Ogre::ColourValue(spotLight.x, spotLight.y, spotLight.z));
}
if(isVisible()) if(isVisible())
ogreRoot->renderOneFrame(this->delta); ogreRoot->renderOneFrame(this->delta);
} }
@ -198,7 +220,11 @@ namespace RNR
void OgreWidget::closeEvent(QCloseEvent* event) void OgreWidget::closeEvent(QCloseEvent* event)
{ {
delete world;
ogreWindow->destroy(); ogreWindow->destroy();
ogreRoot->destroySceneManager(ogreSceneManager);
ogreRoot->shutdown();
} }
QPaintEngine* OgreWidget::paintEngine() const QPaintEngine* OgreWidget::paintEngine() const

View File

@ -7,10 +7,6 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
std::filesystem::create_directory("ShaderCache");
}
QApplication app(argc, argv); QApplication app(argc, argv);
MainWindow window = MainWindow(); MainWindow window = MainWindow();

View File

@ -51,7 +51,7 @@ void MainWindow::widgetItemPrepare(QTreeWidgetItem* item, RNR::Instance* instanc
{ {
QString icon_path; QString icon_path;
icon_path = "content/textures/studio/icons/"; icon_path = "content/textures/studio/icons/";
icon_path += instance->getClassName(); icon_path += instance->getExplorerIcon();
icon_path += ".png"; icon_path += ".png";
QIcon icon; QIcon icon;
if(QFile::exists(icon_path)) if(QFile::exists(icon_path))
@ -138,7 +138,10 @@ void MainWindow::playSolo()
RNR::Players* players = (RNR::Players*)this->ogreWidget->world->getDatamodel()->getService("Players"); RNR::Players* players = (RNR::Players*)this->ogreWidget->world->getDatamodel()->getService("Players");
RNR::Player* player = players->createLocalPlayer(0); RNR::Player* player = players->createLocalPlayer(0);
if(!player)
return;
player->setName(QInputDialog::getText(this, "Player Name", "Enter your player name").toLocal8Bit().data()); player->setName(QInputDialog::getText(this, "Player Name", "Enter your player name").toLocal8Bit().data());
player->loadCharacter();
updateTree(ogreWidget->world->getDatamodel()); updateTree(ogreWidget->world->getDatamodel());
} }

View File

@ -81,7 +81,7 @@ void PropertyViewer::view(RNR::Instance* instance)
QImage image; QImage image;
QString icon_path; QString icon_path;
icon_path = "content/textures/studio/icons/"; icon_path = "content/textures/studio/icons/";
icon_path += instance_ref->getClassName(); icon_path += instance_ref->getExplorerIcon();
icon_path += ".png"; icon_path += ".png";
if(QFile::exists(icon_path)) if(QFile::exists(icon_path))
image = QImage(icon_path); image = QImage(icon_path);

View File

@ -10,10 +10,6 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
std::filesystem::create_directory("ShaderCache");
}
QSurfaceFormat format; QSurfaceFormat format;
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);

View File

@ -16,6 +16,7 @@ add_library(Engine STATIC
Header/App/V8/DataModel/ForceField.hpp Header/App/V8/DataModel/ForceField.hpp
Header/App/V8/DataModel/PartInstance.hpp Header/App/V8/DataModel/PartInstance.hpp
Header/App/V8/DataModel/Light.hpp Header/App/V8/DataModel/Light.hpp
Header/App/V8/DataModel/Lighting.hpp
Header/App/V8/DataModel/FaceInstance.hpp Header/App/V8/DataModel/FaceInstance.hpp
Header/App/V8/DataModel/RunService.hpp Header/App/V8/DataModel/RunService.hpp
Header/App/V8/DataModel/Workspace.hpp Header/App/V8/DataModel/Workspace.hpp
@ -48,6 +49,7 @@ add_library(Engine STATIC
Source/App/V8/DataModel/ForceField.cpp Source/App/V8/DataModel/ForceField.cpp
Source/App/V8/DataModel/PartInstance.cpp Source/App/V8/DataModel/PartInstance.cpp
Source/App/V8/DataModel/Light.cpp Source/App/V8/DataModel/Light.cpp
Source/App/V8/DataModel/Lighting.cpp
Source/App/V8/DataModel/FaceInstance.cpp Source/App/V8/DataModel/FaceInstance.cpp
Source/App/V8/DataModel/RunService.cpp Source/App/V8/DataModel/RunService.cpp
Source/App/V8/DataModel/Workspace.cpp Source/App/V8/DataModel/Workspace.cpp
@ -65,5 +67,7 @@ add_library(Engine STATIC
Source/Rendering/Adorn.cpp Source/Rendering/Adorn.cpp
) )
target_include_directories(Engine PUBLIC ${BOOST_INCLUDE_DIRS} Header/) target_include_directories(Engine PUBLIC ${Boost_INCLUDE_DIRS} ${BULLET_ROOT_DIR}/${BULLET_INCLUDE_DIR} Header/)
target_link_libraries(Engine PUBLIC ${BOOST_LIBRARIES} pugixml OgreBites Luau.Analysis Luau.Ast Luau.Compiler Luau.VM) target_compile_definitions(Engine PUBLIC ${BULLET_DEFINITIONS})
target_link_directories(Engine PUBLIC ${Bullet_DIR}/${BULLET_ROOT_DIR}/${BULLET_LIBRARY_DIRS})
target_link_libraries(Engine PUBLIC ${Boost_LIBRARIES} ${RNR_BULLET_LIBRARIES} pugixml OgreBites Luau.Analysis Luau.Ast Luau.Compiler Luau.VM)

View File

@ -20,6 +20,7 @@ namespace RNR
PartInstance* getTorso(); PartInstance* getTorso();
PartInstance* getHead(); PartInstance* getHead();
void inputFrame(float dx, float dy);
void createHealthBar(); void createHealthBar();
float getHealth() { return m_health; }; float getHealth() { return m_health; };

View File

@ -15,6 +15,8 @@ namespace RNR
{ {
World* m_world; World* m_world;
std::vector<int> scancodes_down; std::vector<int> scancodes_down;
float m_mouseDX;
float m_mouseDY;
protected: protected:
MouseState state; MouseState state;
public: public:

View File

@ -13,6 +13,7 @@ namespace RNR
private: private:
CoordinateFrame m_cframe; CoordinateFrame m_cframe;
CoordinateFrame m_focus; CoordinateFrame m_focus;
Ogre::Radian m_yaw;
virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); virtual void deserializeProperty(char* prop_name, pugi::xml_node prop);
virtual void addProperties(std::vector<ReflectionProperty>& properties); virtual void addProperties(std::vector<ReflectionProperty>& properties);
public: public:
@ -24,6 +25,7 @@ namespace RNR
virtual std::string getClassName() { return "Camera"; } virtual std::string getClassName() { return "Camera"; }
CoordinateFrame& getCFrame() { return m_cframe; }; CoordinateFrame& getCFrame() { return m_cframe; };
CoordinateFrame& getFocus() { return m_focus; } CoordinateFrame& getFocus() { return m_focus; }
Ogre::Radian getYaw() { return m_yaw; }
void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; }; void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; };
void setFocus(CoordinateFrame focus) { m_focus = focus; } void setFocus(CoordinateFrame focus) { m_focus = focus; }
bool zoom(float distance); bool zoom(float distance);

View File

@ -0,0 +1,36 @@
#pragma once
#include <App/V8/Tree/Instance.hpp>
namespace RNR
{
class Lighting : public Instance
{
float m_brightness;
float m_geographicLatitude;
Ogre::Vector3 m_bottomAmbient;
Ogre::Vector3 m_topAmbient;
Ogre::Vector3 m_spotLight;
Ogre::Vector3 m_shadowColor;
Ogre::Vector3 m_clearColor;
virtual void addProperties(std::vector<ReflectionProperty>& properties);
virtual void deserializeProperty(char* prop_name, pugi::xml_node prop);
public:
Lighting();
void setBottomAmbient(Ogre::Vector3 color) { m_bottomAmbient = color; }
Ogre::Vector3 getBottomAmbient() { return m_bottomAmbient; }
void setTopAmbient(Ogre::Vector3 color) { m_topAmbient = color; }
Ogre::Vector3 getTopAmbient() { return m_topAmbient; }
void setSpotLight(Ogre::Vector3 color) { m_spotLight = color; }
Ogre::Vector3 getSpotLight() { return m_spotLight; }
void setShadowColor(Ogre::Vector3 color) { m_shadowColor = color; }
Ogre::Vector3 getShadowColor() { return m_shadowColor; }
void setClearColor(Ogre::Vector3 color) { m_clearColor = color; }
Ogre::Vector3 getClearColor() { return m_clearColor; }
virtual std::string getClassName() { return "Lighting"; }
virtual std::string getExplorerIcon() { return "PointLight"; }
};
}

View File

@ -13,8 +13,10 @@ namespace RNR
enum WorkspaceBatchingMode enum WorkspaceBatchingMode
{ {
BATCH_DONT,
BATCH_INSTANCED, BATCH_INSTANCED,
BATCH_STATIC_GEOMETRY, BATCH_STATIC_GEOMETRY,
BATCH_DYNAMIC_RENDERABLE,
}; };
class Workspace : public ModelInstance class Workspace : public ModelInstance

View File

@ -2,6 +2,7 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <cstddef>
#include <OGRE/Ogre.h> #include <OGRE/Ogre.h>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
@ -36,7 +37,7 @@ namespace RNR
public: public:
Instance(); Instance();
~Instance(); virtual ~Instance();
virtual std::vector<ReflectionProperty> getProperties(); virtual std::vector<ReflectionProperty> getProperties();
void deserializeXmlProperty(pugi::xml_node prop); // TODO: eventually replace this with a method that uses getProperties void deserializeXmlProperty(pugi::xml_node prop); // TODO: eventually replace this with a method that uses getProperties
@ -61,6 +62,7 @@ namespace RNR
RNR::Instance* getParent() { return this->m_parent; }; RNR::Instance* getParent() { return this->m_parent; };
std::string getName() { return this->m_name; }; std::string getName() { return this->m_name; };
virtual std::string getClassName() { return "Instance"; } virtual std::string getClassName() { return "Instance"; }
virtual std::string getExplorerIcon() { return getClassName(); }
void setParent(RNR::Instance* newParent); void setParent(RNR::Instance* newParent);
void setName(std::string name); void setName(std::string name);

View File

@ -15,6 +15,7 @@ namespace RNR
CoordinateFrame& getCFrame() { return m_cframe; }; CoordinateFrame& getCFrame() { return m_cframe; };
void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; }; void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; };
Ogre::Vector3 relativePositionTo(PVInstance* point);
virtual std::string getClassName() { return "PVInstance"; } virtual std::string getClassName() { return "PVInstance"; }
Ogre::Vector3 getPosition() { return m_cframe.getPosition(); } Ogre::Vector3 getPosition() { return m_cframe.getPosition(); }

View File

@ -11,6 +11,9 @@
#include <OGRE/Ogre.h> #include <OGRE/Ogre.h>
#include <pugixml.hpp> #include <pugixml.hpp>
#include <stack> #include <stack>
#include "LinearMath/btVector3.h"
#include "btBulletDynamicsCommon.h"
namespace RNR namespace RNR
{ {
@ -28,6 +31,7 @@ namespace RNR
private: private:
std::map<std::string, Instance*> m_refs; std::map<std::string, Instance*> m_refs;
std::stack<WorldUndeserialized> m_undeserialized; std::stack<WorldUndeserialized> m_undeserialized;
btDiscreteDynamicsWorld* m_dynamicsWorld;
DataModel* m_datamodel; DataModel* m_datamodel;
Workspace* m_workspace; Workspace* m_workspace;
RunService* m_runService; RunService* m_runService;
@ -52,6 +56,7 @@ namespace RNR
double step(float timestep); double step(float timestep);
void update(); void update();
btDiscreteDynamicsWorld* getDynamicsWorld() { return m_dynamicsWorld; }
float getLastDelta() { return m_lastDelta; } float getLastDelta() { return m_lastDelta; }
DataModel* getDatamodel() { return m_datamodel; } DataModel* getDatamodel() { return m_datamodel; }
void setInputManager(IInputManager* inputManager) { m_inputManager = inputManager; } void setInputManager(IInputManager* inputManager) { m_inputManager = inputManager; }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <map> #include <map>
#include <cstddef>
namespace RNR namespace RNR
{ {

View File

@ -10,6 +10,7 @@ namespace RNR
{ {
public: public:
static Ogre::Vector3 getVector3(pugi::xml_node node); static Ogre::Vector3 getVector3(pugi::xml_node node);
static Ogre::Vector3 getColor(pugi::xml_node node);
static CoordinateFrame getCFrame(pugi::xml_node node); static CoordinateFrame getCFrame(pugi::xml_node node);
}; };
} }

View File

@ -11,6 +11,9 @@ namespace RNR
public: public:
Player(); Player();
void initLocalPlayer();
void loadCharacter();
ModelInstance* getCharacter() { return m_character; } ModelInstance* getCharacter() { return m_character; }
void setCharacter(ModelInstance* model) { m_character = model; } void setCharacter(ModelInstance* model) { m_character = model; }
virtual std::string getClassName() { return "Player"; } virtual std::string getClassName() { return "Player"; }

View File

@ -115,6 +115,7 @@ namespace RNR
void TopMenuBar::frame() void TopMenuBar::frame()
{ {
Workspace* workspace = m_world->getWorkspace(); Workspace* workspace = m_world->getWorkspace();
btDiscreteDynamicsWorld* dynamicsWorld = m_world->getDynamicsWorld();
char debugtext[512]; char debugtext[512];
char render_debugtext[255]; char render_debugtext[255];
@ -127,7 +128,11 @@ namespace RNR
snprintf(render_debugtext, 255, "using BATCH_STATIC_GEOMETRY\nGeom Regions: %i", workspace->m_geom->getRegions().size()); snprintf(render_debugtext, 255, "using BATCH_STATIC_GEOMETRY\nGeom Regions: %i", workspace->m_geom->getRegions().size());
break; break;
} }
snprintf(debugtext, 512, "Render\nLast DT = %f\n%s\n",m_world->getLastDelta(),render_debugtext,m_world->getOgreSceneManager()); snprintf(debugtext, 512, "Render\nLast DT = %f\n%s\n\nPhysics\n%i objects, %i constraints",
m_world->getLastDelta(),
render_debugtext,
m_world->getOgreSceneManager(),
dynamicsWorld->getNumCollisionObjects(), dynamicsWorld->getNumConstraints());
m_debugText->setCaption(debugtext); m_debugText->setCaption(debugtext);
Players* players = (Players*)m_world->getDatamodel()->getService("Players"); Players* players = (Players*)m_world->getDatamodel()->getService("Players");

View File

@ -1,11 +1,15 @@
#include <App/Humanoid/Humanoid.hpp> #include <App/Humanoid/Humanoid.hpp>
#include <App/V8/World/World.hpp> #include <App/V8/World/World.hpp>
#include <App/InputManager.hpp>
namespace RNR namespace RNR
{ {
Humanoid::Humanoid() Humanoid::Humanoid()
{ {
// setName("Humanoid");
m_maxHealth = 100.f;
m_health = 100.f;
} }
Humanoid::~Humanoid() Humanoid::~Humanoid()
@ -42,13 +46,38 @@ namespace RNR
} }
if(getNode()) if(getNode())
world->getOgreSceneManager()->destroySceneNode(getNode()); world->getOgreSceneManager()->destroySceneNode(getNode());
setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode()); setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode());
Ogre::BillboardSet* healthBarSet = world->getOgreSceneManager()->createBillboardSet("HumanoidHealth" + getParent()->getName()); Ogre::BillboardSet* healthBarSet = world->getOgreSceneManager()->createBillboardSet("HumanoidHealth" + getParent()->getName());
Ogre::Billboard* healthBarBillboard = healthBarSet->createBillboard(Ogre::Vector3(100, 0, 200)); healthBarSet->setBillboardType(Ogre::BillboardType::BBT_PERPENDICULAR_COMMON);
getNode()->attachObject(healthBarSet); healthBarSet->setDebugDisplayEnabled(true);
getNode()->setPosition(getHead()->getPosition()); //Ogre::Billboard* healthBarBillboard = healthBarSet->createBillboard(Ogre::Vector3(0, 2, 0), Ogre::ColourValue(1, 0, 0, 1));
Ogre::Billboard* healthBarBillboardFilled = healthBarSet->createBillboard(Ogre::Vector3(0, 2, 0), Ogre::ColourValue(0, 1, 0, 1));
float healthBarScale = 0.5f;
//healthBarBillboard->setDimensions(5 * healthBarScale, 1 * healthBarScale);
healthBarBillboardFilled->setDimensions((m_health / m_maxHealth) * 5.f * healthBarScale, 1 * healthBarScale);
healthBarSet->setCastShadows(true);
printf("Humanoid::createHealthBar: WIP"); Ogre::BillboardSet* nameBarSet = world->getOgreSceneManager()->createBillboardSet("HumanoidName" + getParent()->getName());
nameBarSet->setDebugDisplayEnabled(true);
Ogre::FontPtr comic = Ogre::FontManager::getSingletonPtr()->getByName("ComicSans");
if(!comic)
printf("Humanoid::createHealthBar: comic == NULL\n");
comic->putText(nameBarSet, getParent()->getName(), 1);
int num_billboards = nameBarSet->getNumBillboards();
for(int i = 0; i < num_billboards; i++)
{
Ogre::Billboard* chara = nameBarSet->getBillboard(i);
Ogre::Vector3 chara_pos = chara->getPosition();
chara_pos.y += 2 + healthBarScale;
chara->setPosition(chara_pos);
}
getNode()->attachObject(healthBarSet);
getNode()->attachObject(nameBarSet);
getNode()->setPosition(getHead()->getPosition());
getNode()->setOrientation(getHead()->getRotation());
printf("Humanoid::createHealthBar: WIP\n");
} }
void Humanoid::deserializeProperty(char* prop_name, pugi::xml_node prop) void Humanoid::deserializeProperty(char* prop_name, pugi::xml_node prop)
@ -63,6 +92,58 @@ namespace RNR
} }
} }
void Humanoid::inputFrame(float dx, float dy)
{
IInputManager* inputManager = world->getInputManager();
PartInstance* torso = getTorso();
Camera* camera = world->getWorkspace()->getCurrentCamera();
if(!torso)
{
printf("Humanoid::inputFrame: no torso\n");
return;
}
if(inputManager)
{
Ogre::Matrix3 camera_rotation;
camera_rotation.FromEulerAnglesYXZ(camera->getYaw(), Ogre::Radian(0), Ogre::Radian(0)); // we only want yaw because otherwise the movement target will go through the ground/in the air
Ogre::Quaternion direction = torso->getRotation();
Ogre::Quaternion new_direction = Ogre::Quaternion::nlerp(0.5f, direction, camera_rotation);
float forward = 0;
if(inputManager->isKeyDown('W'))
forward = 16;
Ogre::Vector3 move = Ogre::Vector3(0, 0, -forward);
move = direction * move;
move *= world->getLastDelta();
bool move_valid = true;
// TODO: collision checking
if(!move_valid)
return;
for(auto& child : *getParent()->getChildren())
{
PartInstance* bp = dynamic_cast<PartInstance*>(child);
if(bp)
{
Ogre::Vector3 bp_p = bp->getPosition();
bp_p += move;
bp->getCFrame().setPosition(bp_p);
Ogre::Matrix3 new_rotation_matrix;
new_direction.ToRotationMatrix(new_rotation_matrix);
bp->getCFrame().setRotation(new_rotation_matrix);
bp->updateMatrix();
world->getWorkspace()->setDirty();
}
}
camera->getCFrame().setPosition(camera->getCFrame().getPosition() + move);
}
}
void Humanoid::addProperties(std::vector<ReflectionProperty>& properties) void Humanoid::addProperties(std::vector<ReflectionProperty>& properties)
{ {
ReflectionProperty _properties[] = { ReflectionProperty _properties[] = {

View File

@ -1,5 +1,6 @@
#include <App/InputManager.hpp> #include <App/InputManager.hpp>
#include <App/V8/DataModel/Camera.hpp> #include <App/V8/DataModel/Camera.hpp>
#include <App/Humanoid/Humanoid.hpp>
#include <stdio.h> #include <stdio.h>
namespace RNR namespace RNR
@ -9,8 +10,7 @@ namespace RNR
state.mouse_primary = false; state.mouse_primary = false;
state.mouse_secondary = false; state.mouse_secondary = false;
state.mouse_middle = false; state.mouse_middle = false;
state.mouse_scroll = 0; state.mouse_scroll = 0; }
}
void IInputManager::keyDown(int scancode) void IInputManager::keyDown(int scancode)
{ {
@ -43,14 +43,14 @@ namespace RNR
{ {
if(m_world) if(m_world)
{ {
float xd = x * m_world->getLastDelta(); m_mouseDX = x * m_world->getLastDelta();
float yd = y * m_world->getLastDelta(); m_mouseDY = y * m_world->getLastDelta();
Workspace* workspace = m_world->getWorkspace(); Workspace* workspace = m_world->getWorkspace();
Camera* camera = workspace->getCurrentCamera(); Camera* camera = workspace->getCurrentCamera();
if(camera && state.mouse_secondary) if(camera && state.mouse_secondary)
{ {
camera->cameraFrame(xd, yd); camera->cameraFrame(m_mouseDX, m_mouseDY);
resetMouse(); resetMouse();
} }
@ -59,10 +59,29 @@ namespace RNR
void IInputManager::frame() void IInputManager::frame()
{ {
Workspace* workspace = m_world->getWorkspace(); Players* players = (Players*)m_world->getDatamodel()->getService("Players");
Camera* camera = workspace->getCurrentCamera(); Player* localPlayer = players->getLocalPlayer();
if(camera) if(localPlayer)
camera->cameraFrame(0, 0, false); // update camera position {
ModelInstance* character = localPlayer->getCharacter();
if(character)
{
Humanoid* humanoid = (Humanoid*)character->findFirstChildOfType("Humanoid");
if(humanoid)
{
humanoid->inputFrame(m_mouseDX, m_mouseDY);
}
}
}
else
{
Workspace* workspace = m_world->getWorkspace();
Camera* camera = workspace->getCurrentCamera();
if(camera)
camera->cameraFrame(0, 0, false); // update camera position
}
m_mouseDX = 0;
m_mouseDY = 0;
} }
void IInputManager::mousePrimaryState(bool down) void IInputManager::mousePrimaryState(bool down)

View File

@ -3,7 +3,6 @@
#include <App/CoordinateFrame.hpp> #include <App/CoordinateFrame.hpp>
#include <App/BrickColor.hpp> #include <App/BrickColor.hpp>
#include <Helpers/Strings.hpp> #include <Helpers/Strings.hpp>
#include <format>
namespace RNR namespace RNR
{ {

View File

@ -1,6 +1,7 @@
#include <App/V8/DataModel/Camera.hpp> #include <App/V8/DataModel/Camera.hpp>
#include <App/V8/World/World.hpp> #include <App/V8/World/World.hpp>
#include <App/InputManager.hpp> #include <App/InputManager.hpp>
#include <Network/Players.hpp>
#include <Helpers/XML.hpp> #include <Helpers/XML.hpp>
namespace RNR namespace RNR
@ -40,6 +41,7 @@ namespace RNR
pitch = old_pitch + pitch; pitch = old_pitch + pitch;
yaw = old_yaw - yaw; yaw = old_yaw - yaw;
m_yaw = yaw;
Ogre::Matrix3 rotation; Ogre::Matrix3 rotation;
rotation.FromEulerAnglesYXZ(yaw, pitch, Ogre::Radian(0)); rotation.FromEulerAnglesYXZ(yaw, pitch, Ogre::Radian(0));

View File

@ -0,0 +1,67 @@
#include <App/V8/DataModel/Lighting.hpp>
#include <Helpers/XML.hpp>
namespace RNR
{
Lighting::Lighting()
{
setName("Lighting");
setClearColor(Ogre::Vector3(255.f/255.f,255.f/255.f,255.f/255.f));
setShadowColor(Ogre::Vector3(127.f/255.f,127.f/255.f,127.f/255.f));
setBottomAmbient(Ogre::Vector3(122.f/255.f,134.f/255.f,120.f/255.f));
setTopAmbient(Ogre::Vector3(209.f/255.f,208.f/255.f,217.f/255.f));
setSpotLight(Ogre::Vector3(191.f/255.f,191.f/255.f,191.f/255.f));
}
void Lighting::deserializeProperty(char* prop_name, pugi::xml_node node)
{
if(prop_name == std::string("ClearColor"))
{
setClearColor(XML::getColor(node));
}
else if(prop_name == std::string("ShadowColor"))
{
setShadowColor(XML::getColor(node));
}
else if(prop_name == std::string("SpotLightV9"))
{
setSpotLight(XML::getColor(node));
}
else if(prop_name == std::string("BottomAmbientV9"))
{
setBottomAmbient(XML::getColor(node));
}
else if(prop_name == std::string("TopAmbientV9"))
{
setTopAmbient(XML::getColor(node));
}
}
void Lighting::addProperties(std::vector<ReflectionProperty>& properties)
{
ReflectionProperty _properties[] = {
{ this, std::string("BottomAmbientV9"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_bottomAmbient; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setBottomAmbient(*(Ogre::Vector3*)value); ) },
{ this, std::string("TopAmbientV9"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_topAmbient; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setTopAmbient(*(Ogre::Vector3*)value); ) },
{ this, std::string("ClearColor"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_clearColor; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setClearColor(*(Ogre::Vector3*)value); ) },
{ this, std::string("ShadowColor"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_shadowColor; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setShadowColor(*(Ogre::Vector3*)value); ) },
{ this, std::string("SpotLightV9"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_spotLight; ),
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setSpotLight(*(Ogre::Vector3*)value); ) },
};
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
}
}

View File

@ -8,7 +8,7 @@ namespace RNR
Workspace::Workspace() : ModelInstance() Workspace::Workspace() : ModelInstance()
{ {
setName("Workspace"); setName("Workspace");
m_batchMode = BATCH_STATIC_GEOMETRY; m_batchMode = BATCH_DONT;
m_worldspawn = world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode(); m_worldspawn = world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode();
@ -19,9 +19,11 @@ namespace RNR
break; break;
case BATCH_STATIC_GEOMETRY: case BATCH_STATIC_GEOMETRY:
m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom"); m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom");
m_geom->setRegionDimensions(Ogre::Vector3(512,512,512)); m_geom->setRegionDimensions(Ogre::Vector3(2048,2048,2048));
m_geom->setCastShadows(true); m_geom->setCastShadows(true);
break; break;
case BATCH_DONT:
break;
} }
} }
@ -36,11 +38,12 @@ namespace RNR
case BATCH_INSTANCED: case BATCH_INSTANCED:
{ {
Ogre::Entity* childEntity = (Ogre::Entity*)childAdded->getObject(); Ogre::Entity* childEntity = (Ogre::Entity*)childAdded->getObject();
Ogre::InstancedEntity* replica = m_instanceManager->createInstancedEntity(childEntity->getSubEntity(0)->getMaterialName()); Ogre::InstancedEntity* replica = m_instanceManager->createInstancedEntity("materials/partinstanced");
replica->setPosition(part->getPosition()); replica->setPosition(part->getPosition());
replica->setOrientation(part->getCFrame().getRotation()); replica->setOrientation(part->getCFrame().getRotation());
replica->setScale(part->getSize()); replica->setScale(part->getSize());
childAdded->setObject(replica); childAdded->setObject(replica);
child_node->setVisible(false);
} }
break; break;
case BATCH_STATIC_GEOMETRY: case BATCH_STATIC_GEOMETRY:
@ -48,10 +51,12 @@ namespace RNR
part->getPosition(), part->getPosition(),
part->getCFrame().getRotation(), part->getCFrame().getRotation(),
part->getSize()); part->getSize());
child_node->setVisible(false);
m_geomDirty = true;
break;
case BATCH_DONT:
break; break;
} }
child_node->setVisible(false);
m_geomDirty = true;
} }
} }

View File

@ -15,6 +15,17 @@ namespace RNR
Instance::~Instance() Instance::~Instance()
{ {
setParent(NULL); setParent(NULL);
if(getNode())
{
getNode()->removeAndDestroyAllChildren();
delete getNode();
}
if(getObject())
{
if(getObject()->getParentNode() != 0)
getObject()->detachFromParent();
delete getObject();
}
} }
std::vector<ReflectionProperty> Instance::getProperties() std::vector<ReflectionProperty> Instance::getProperties()
@ -47,6 +58,8 @@ namespace RNR
pugi::xml_attribute prop_name = prop.attribute("name"); pugi::xml_attribute prop_name = prop.attribute("name");
if(prop_name.as_string() == std::string("Name")) if(prop_name.as_string() == std::string("Name"))
setName(prop.text().as_string()); setName(prop.text().as_string());
else if(prop_name.as_string() == std::string("archivable"))
m_archivable = prop.text().as_bool();
else else
deserializeProperty((char*)prop_name.as_string(), prop); deserializeProperty((char*)prop_name.as_string(), prop);
} }

View File

@ -28,4 +28,9 @@ namespace RNR
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty))); properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
} }
Ogre::Vector3 PVInstance::relativePositionTo(PVInstance* point)
{
return point->getPosition() - getPosition();
}
} }

View File

@ -1,6 +1,7 @@
#include <App/V8/World/World.hpp> #include <App/V8/World/World.hpp>
#include <App/V8/Tree/InstanceFactory.hpp> #include <App/V8/Tree/InstanceFactory.hpp>
#include <App/V8/DataModel/PartInstance.hpp> #include <App/V8/DataModel/PartInstance.hpp>
#include <App/V8/DataModel/Lighting.hpp>
#include <App/GUI/SelectionBox.hpp> #include <App/GUI/SelectionBox.hpp>
#include <App/Humanoid/Humanoid.hpp> #include <App/Humanoid/Humanoid.hpp>
#include <App/InputManager.hpp> #include <App/InputManager.hpp>
@ -14,6 +15,13 @@ namespace RNR
{ {
Instance::setWorld(this); Instance::setWorld(this);
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
m_inputManager = 0; m_inputManager = 0;
m_instanceFactory = new InstanceFactory(); m_instanceFactory = new InstanceFactory();
@ -27,6 +35,7 @@ namespace RNR
m_instanceFactory->registerInstance("RunService", InstanceFactory::instanceBuilder<RunService>); m_instanceFactory->registerInstance("RunService", InstanceFactory::instanceBuilder<RunService>);
m_instanceFactory->registerInstance("Players", InstanceFactory::instanceBuilder<Players>); m_instanceFactory->registerInstance("Players", InstanceFactory::instanceBuilder<Players>);
m_instanceFactory->registerInstance("Player", InstanceFactory::instanceBuilder<Player>); m_instanceFactory->registerInstance("Player", InstanceFactory::instanceBuilder<Player>);
m_instanceFactory->registerInstance("Lighting", InstanceFactory::instanceBuilder<Lighting>);
m_ogreRoot = ogre; m_ogreRoot = ogre;
m_ogreSceneManager = ogreSceneManager; m_ogreSceneManager = ogreSceneManager;
@ -109,13 +118,14 @@ namespace RNR
WorldUndeserialized s = m_undeserialized.top(); WorldUndeserialized s = m_undeserialized.top();
m_undeserialized.pop(); m_undeserialized.pop();
s.instance->setParent(s.parent);
pugi::xml_node props = s.node.child("Properties"); pugi::xml_node props = s.node.child("Properties");
for(pugi::xml_node prop : props.children()) for(pugi::xml_node prop : props.children())
{ {
s.instance->deserializeXmlProperty(prop); s.instance->deserializeXmlProperty(prop);
} }
s.instance->setParent(s.parent);
if(s.instance->getClassName() == "Model") if(s.instance->getClassName() == "Model")
{ {
ModelInstance* m = (ModelInstance*)s.instance; ModelInstance* m = (ModelInstance*)s.instance;
@ -140,7 +150,10 @@ namespace RNR
double World::step(float timestep) double World::step(float timestep)
{ {
if(m_runService && m_runService->getRunning()) if(m_runService && m_runService->getRunning())
{
m_runService->step(timestep); m_runService->step(timestep);
m_dynamicsWorld->stepSimulation(timestep);
}
m_lastDelta = timestep; m_lastDelta = timestep;
return 0.0; return 0.0;
} }

View File

@ -11,6 +11,16 @@ namespace RNR
); );
} }
Ogre::Vector3 XML::getColor(pugi::xml_node node)
{
Ogre::Vector3 rgb;
unsigned int hex = node.text().as_uint();
rgb.x = ((hex >> 16) & 0xff) / 255.0;
rgb.y = ((hex >> 8) & 0xff) / 255.0;
rgb.z = ((hex) & 0xff) / 255.0;
return rgb;
}
CoordinateFrame XML::getCFrame(pugi::xml_node node) CoordinateFrame XML::getCFrame(pugi::xml_node node)
{ {
CoordinateFrame cframe; CoordinateFrame cframe;

View File

@ -1,4 +1,5 @@
#include <Network/Player.hpp> #include <Network/Player.hpp>
#include <App/Humanoid/Humanoid.hpp>
#include <App/V8/World/World.hpp> #include <App/V8/World/World.hpp>
namespace RNR namespace RNR
@ -22,4 +23,38 @@ namespace RNR
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty))); properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
} }
void Player::initLocalPlayer()
{
}
void Player::loadCharacter()
{
m_character = new ModelInstance();
m_character->setName(getName());
PartInstance* head = new PartInstance();
head->setName("Head");
head->setSize(Ogre::Vector3(2, 1, 1));
head->setBrickColor(24);
head->getCFrame().setPosition(Ogre::Vector3(0, 1.5, 0));
head->updateMatrix();
head->setParent(m_character);
PartInstance* torso = new PartInstance();
torso->setName("Torso");
torso->setSize(Ogre::Vector3(2, 2, 1));
torso->setBrickColor(23);
torso->getCFrame().setPosition(Ogre::Vector3(0, 0, 0));
torso->updateMatrix();
torso->setParent(m_character);
Humanoid* character_humanoid = new Humanoid();
character_humanoid->setParent(m_character);
m_character->setParent(world->getWorkspace());
Camera* player_camera = world->getWorkspace()->getCurrentCamera();
player_camera->setCFrame(CoordinateFrame());
}
} }

View File

@ -12,11 +12,12 @@ namespace RNR
{ {
if(m_localPlayer) if(m_localPlayer)
{ {
printf("Players::createLocalPlayer: attempt to create another local player\n", userId); printf("Players::createLocalPlayer: attempt to create another local player %i\n", userId);
return m_localPlayer; return 0;
} }
printf("Players::createLocalPlayer: created player %i\n", userId); printf("Players::createLocalPlayer: created player %i\n", userId);
m_localPlayer = new Player(); m_localPlayer = new Player();
m_localPlayer->initLocalPlayer();
return m_localPlayer; return m_localPlayer;
} }

View File

@ -1,9 +1,9 @@
# RNR # RNR
[![GitHub CI Status](https://img.shields.io/github/actions/workflow/status/lrre-foss/rnr/build.yml?branch=trunk&label=builds)](https://github.com/lrre-foss/rnr/actions) [![GitHub CI Status](https://img.shields.io/github/actions/workflow/status/lrre-foss/rnr/build.yml?branch=trunk&label=builds)](https://github.com/lrre-foss/rnr/actions)
[![Discord](https://img.shields.io/discord/1130992923329175552?style=social&logo=discord)](https://discord.gg/2tj4TREby3)
[![Star](https://img.shields.io/github/stars/lrre-foss/RNR?style=social)](https://github.com/lrre-foss/RNR/stargazers) [![Star](https://img.shields.io/github/stars/lrre-foss/RNR?style=social)](https://github.com/lrre-foss/RNR/stargazers)
[Discord](https://discord.gg/89WagAUr)
RNR (**R**NR's **N**ot **R**oblox) is a project that aims to recreate the look and feel of classic Roblox with new features while remaining partially compatible with clients from that era. It is built upon an engine that closely resembles Roblox's own at the time, referencing disassemblies of legacy client binaries. RNR (**R**NR's **N**ot **R**oblox) is a project that aims to recreate the look and feel of classic Roblox with new features while remaining fully compatible with clients from that era. It is built upon an engine that closely resembles Roblox's own at the time, referencing disassemblies of legacy client binaries.
Interested in contributing? [Feel free to make a pull request!](https://github.com/lrre-foss/RNR/pulls) Interested in contributing? [Feel free to make a pull request!](https://github.com/lrre-foss/RNR/pulls)
@ -13,6 +13,7 @@ There are several goals that RNR seeks to accomplish, them being;
- Easy-to-use (simple CLI options to launch and host games, as well as a level editor with a modern UI) - Easy-to-use (simple CLI options to launch and host games, as well as a level editor with a modern UI)
- Fully compatible with Roblox versions up to 0.3.744.0 (dated April 2008) in areas such as hosting, joining, levels, etc. - Fully compatible with Roblox versions up to 0.3.744.0 (dated April 2008) in areas such as hosting, joining, levels, etc.
- Incorporates all the various facets of the Roblox engine, plus a little bit extra (e.g. a network replication whitelist, fancy shader support, etc.) - Incorporates all the various facets of the Roblox engine, plus a little bit extra (e.g. a network replication whitelist, fancy shader support, etc.)
- Made using clean-room reverse engineering
- Uses Roblox's [Luau](https://luau-lang.org/) as its scripting language while remaining fully compatible with classic Roblox scripts written using Lua 5.1 - Uses Roblox's [Luau](https://luau-lang.org/) as its scripting language while remaining fully compatible with classic Roblox scripts written using Lua 5.1
- As free and open-source as possible (with client code licensed under the GPL and the engine itself being released into the public domain, void of any copyright) - As free and open-source as possible (with client code licensed under the GPL and the engine itself being released into the public domain, void of any copyright)
- Patching all the security vulnerabilities and fixing bugs/inefficiencies that legacy Roblox clients had - Patching all the security vulnerabilities and fixing bugs/inefficiencies that legacy Roblox clients had