summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/AssetManager.cpp59
-rw-r--r--src/AssetManager.hpp4
-rw-r--r--src/Block.cpp531
-rw-r--r--src/Block.hpp13
-rw-r--r--src/Event.cpp5
-rw-r--r--src/Framebuffer.cpp12
-rw-r--r--src/Game.cpp241
-rw-r--r--src/Game.hpp30
-rw-r--r--src/GameState.cpp4
-rw-r--r--src/GameState.hpp2
-rw-r--r--src/GlobalState.cpp238
-rw-r--r--src/GlobalState.hpp25
-rw-r--r--src/Plugin.cpp261
-rw-r--r--src/Plugin.hpp19
-rw-r--r--src/Render.cpp107
-rw-r--r--src/Render.hpp1
-rw-r--r--src/Renderer.cpp3
-rw-r--r--src/RendererEntity.cpp3
-rw-r--r--src/RendererSection.cpp4
-rw-r--r--src/RendererSectionData.cpp5
-rw-r--r--src/RendererSky.cpp9
-rw-r--r--src/RendererWorld.cpp70
-rw-r--r--src/RendererWorld.hpp9
-rw-r--r--src/Utility.cpp2
-rw-r--r--src/World.cpp12
-rw-r--r--src/main.cpp4
26 files changed, 786 insertions, 887 deletions
diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp
index 71800d7..19cd452 100644
--- a/src/AssetManager.cpp
+++ b/src/AssetManager.cpp
@@ -11,8 +11,10 @@
#define STB_IMAGE_IMPLEMENTATION
#define STBI_ONLY_PNG
#include <stb_image.h>
+#include <optick.h>
#include "Utility.hpp"
+#include "Plugin.hpp"
namespace fs = std::experimental::filesystem::v1;
@@ -28,6 +30,7 @@ std::map<BlockId, BlockFaces> blockIdToBlockFaces;
void LoadIds();
void LoadAssets();
void LoadTextures();
+void LoadScripts();
void WalkDirEntry(const fs::directory_entry &dirEntry, AssetTreeNode *node);
void ParseAsset(AssetTreeNode &node);
@@ -35,6 +38,7 @@ void ParseAssetTexture(AssetTreeNode &node);
void ParseAssetBlockModel(AssetTreeNode &node);
void ParseAssetBlockState(AssetTreeNode &node);
void ParseAssetShader(AssetTreeNode &node);
+void ParseAssetScript(AssetTreeNode &node);
void ParseBlockModels();
@@ -58,6 +62,9 @@ void AssetManager::InitAssetManager()
LoadIds();
ParseBlockModels();
+
+ PluginSystem::Init();
+ LoadScripts();
}
void LoadIds() {
@@ -96,6 +103,36 @@ void LoadTextures() {
atlas = std::make_unique<TextureAtlas>(textureData);
}
+void LoadScripts() {
+ AssetTreeNode *node = AssetManager::GetAssetByAssetName("/");
+ for (auto &it : node->childs) {
+ for (auto &child : it->childs) {
+ if (child->name == "scripts") {
+ for (auto &script : child->childs)
+ {
+ if (script->name != "init")
+ continue;
+
+ AssetScript *asset = dynamic_cast<AssetScript *>(script->asset.get());
+ if (!asset) {
+ LOG(ERROR) << "Unrecognised script file /" << it->name;
+ continue;
+ }
+ try {
+ PluginSystem::Execute(asset->code, true);
+ }
+ catch (std::exception & e) {
+ LOG(ERROR) << "Failed loading script '" << script->name << "' in '" << it->name << "'";
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ LOG(INFO) << "Scripts loaded";
+}
+
void WalkDirEntry(const fs::directory_entry &dirEntry, AssetTreeNode *node) {
for (auto &file : fs::directory_iterator(dirEntry)) {
node->childs.push_back(std::make_unique<AssetTreeNode>());
@@ -138,6 +175,11 @@ void ParseAsset(AssetTreeNode &node) {
ParseAssetShader(node);
return;
}
+
+ if (node.parent->name == "scripts") {
+ ParseAssetScript(node);
+ return;
+ }
}
void ParseAssetTexture(AssetTreeNode &node) {
@@ -380,6 +422,14 @@ void ParseAssetShader(AssetTreeNode &node) {
}
}
+void ParseAssetScript(AssetTreeNode &node) {
+ node.asset = std::make_unique<AssetScript>();
+ AssetScript *asset = dynamic_cast<AssetScript*>(node.asset.get());
+ asset->code = std::string((char*)node.data.data(), (char*)node.data.data() + node.data.size());
+ node.data.clear();
+ node.data.shrink_to_fit();
+}
+
void ParseBlockModels() {
std::string textureName;
@@ -563,16 +613,16 @@ BlockFaces &AssetManager::GetBlockModelByBlockId(BlockId block) {
return blockIdToBlockFaces.find(block)->second;
}
- auto blockStateName = TransformBlockIdToBlockStateName(block);
- AssetBlockState *asset = GetAsset<AssetBlockState>("/minecraft/blockstates/" + blockStateName.first);
+ BlockInfo blockInfo = GetBlockInfo(block);
+ AssetBlockState *asset = GetAsset<AssetBlockState>("/minecraft/blockstates/" + blockInfo.blockstate);
if (!asset)
return GetBlockModelByBlockId(BlockId{ 7788,0 });
BlockState &blockState = asset->blockState;
- if (blockState.variants.find(blockStateName.second) == blockState.variants.end())
+ if (blockState.variants.find(blockInfo.variant) == blockState.variants.end())
return GetBlockModelByBlockId(BlockId{ 7788,0 });
- BlockStateVariant &variant = blockState.variants[blockStateName.second];
+ BlockStateVariant &variant = blockState.variants[blockInfo.variant];
if (variant.models.empty())
return GetBlockModelByBlockId(BlockId{ 7788,0 });
@@ -622,6 +672,7 @@ std::string AssetManager::GetAssetNameByBlockId(BlockId block) {
}
Asset *AssetManager::GetAssetPtr(const std::string & assetName) {
+ OPTICK_EVENT();
AssetTreeNode *node;
if (assetName[0] != '/')
node = GetAssetByAssetName('/' + assetName);
diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp
index de3881e..bf948b3 100644
--- a/src/AssetManager.hpp
+++ b/src/AssetManager.hpp
@@ -167,6 +167,10 @@ struct AssetShader : Asset {
std::unique_ptr<Shader> shader;
};
+struct AssetScript : Asset {
+ std::string code;
+};
+
namespace AssetManager {
void InitAssetManager();
diff --git a/src/Block.cpp b/src/Block.cpp
index a12db9d..48c099d 100644
--- a/src/Block.cpp
+++ b/src/Block.cpp
@@ -1,525 +1,20 @@
#include "Block.hpp"
-std::pair<std::string, std::string> TransformBlockIdToBlockStateName(BlockId blockId) {
- switch (blockId.id) {
- case 1: {
- if (blockId.state > 6)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("stone", "normal"),
- std::pair<std::string,std::string>("granite", "normal"),
- std::pair<std::string,std::string>("smooth_granite", "normal"),
- std::pair<std::string,std::string>("diorite", "normal"),
- std::pair<std::string,std::string>("smooth_diorite", "normal"),
- std::pair<std::string,std::string>("andesite", "normal"),
- std::pair<std::string,std::string>("smooth_andesite", "normal"),
- };
- return ids[blockId.state];
- }
- case 2: {
- return std::make_pair("grass", "snowy=false");
- }
- case 3: {
- if (blockId.state > 2)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("dirt", "normal"),
- std::pair<std::string,std::string>("coarse_dirt", "normal"),
- std::pair<std::string,std::string>("podzol", "snowy=false"),
- };
- return ids[blockId.state];
- }
- case 4: {
- return std::make_pair("cobblestone", "normal");
- }
- case 5: {
- if (blockId.state > 5)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("oak_planks", "normal"),
- std::pair<std::string,std::string>("spruce_planks", "normal"),
- std::pair<std::string,std::string>("birch_planks", "normal"),
- std::pair<std::string,std::string>("jungle_planks", "normal"),
- std::pair<std::string,std::string>("acacia_planks", "normal"),
- std::pair<std::string,std::string>("dark_oak_planks", "normal"),
- };
- return ids[blockId.state];
- }
- case 7: {
- return std::make_pair("bedrock", "normal");
- }
- case 8:
- case 9: {
- return std::make_pair("water", "normal");
- }
- case 10:
- case 11: {
- return std::make_pair("lava", "normal");
- }
- case 12: {
- if (blockId.state > 1)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("sand", "normal"),
- std::pair<std::string,std::string>("red_sand", "normal"),
- };
- return ids[blockId.state];
- }
- case 13: {
- return std::make_pair("gravel", "normal");
- }
- case 14: {
- return std::make_pair("gold_ore", "normal");
- }
- case 15: {
- return std::make_pair("iron_ore", "normal");
- }
- case 16: {
- return std::make_pair("coal_ore", "normal");
- }
- case 17: {
- unsigned char type = blockId.state & 0x3;
- unsigned char dir = (blockId.state & 0xC) >> 2;
- static const std::string types[] = {
- "oak_log",
- "spruce_log",
- "birch_log",
- "jungle_log",
- };
- static const std::string dirs[] = {
- "axis=y",
- "axis=x",
- "axis=z",
- "axis=none",
- };
- return std::make_pair(types[type], dirs[dir]);
- }
- case 18: {
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("oak_leaves", "normal"),
- std::pair<std::string,std::string>("spruce_leaves", "normal"),
- std::pair<std::string,std::string>("birch_leaves", "normal"),
- std::pair<std::string,std::string>("jungle_leaves", "normal"),
- };
- return ids[blockId.state & 0x3];
- }
- case 20: {
- return std::make_pair("glass", "normal");
- }
- case 21: {
- return std::make_pair("lapis_ore", "normal");
- }
- case 22: {
- return std::make_pair("lapis_block", "normal");
- }
- case 24: {
- if (blockId.state > 2)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("sandstone", "normal"),
- std::pair<std::string,std::string>("chiseled_sandstone", "normal"),
- std::pair<std::string,std::string>("smooth_sandstone", "normal"),
- };
- return ids[blockId.state];
- }
- case 30: {
- return std::make_pair("web", "normal");
- }
- case 31: {
- if (blockId.state > 2)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("dead_bush", "normal"),
- std::pair<std::string,std::string>("tall_grass", "normal"),
- std::pair<std::string,std::string>("fern", "normal"),
- };
- return ids[blockId.state];
- }
- case 32: {
- return std::make_pair("dead_bush", "normal");
- }
- case 35: {
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("white_wool", "normal"),
- std::pair<std::string,std::string>("orange_wool", "normal"),
- std::pair<std::string,std::string>("magenta_wool", "normal"),
- std::pair<std::string,std::string>("light_blue_wool", "normal"),
- std::pair<std::string,std::string>("yellow_wool", "normal"),
- std::pair<std::string,std::string>("lime_wool", "normal"),
- std::pair<std::string,std::string>("pink_wool", "normal"),
- std::pair<std::string,std::string>("gray_wool", "normal"),
- std::pair<std::string,std::string>("silver_wool", "normal"),
- std::pair<std::string,std::string>("cyan_wool", "normal"),
- std::pair<std::string,std::string>("purple_wool", "normal"),
- std::pair<std::string,std::string>("blue_wool", "normal"),
- std::pair<std::string,std::string>("brown_wool", "normal"),
- std::pair<std::string,std::string>("green_wool", "normal"),
- std::pair<std::string,std::string>("red_wool", "normal"),
- std::pair<std::string,std::string>("black_wool", "normal"),
- };
- return ids[blockId.state];
- }
- case 37: {
- return std::make_pair("dandelion", "normal");
- }
- case 38: {
- if (blockId.state > 8)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("poppy", "normal"),
- std::pair<std::string,std::string>("blue_orchid", "normal"),
- std::pair<std::string,std::string>("allium", "normal"),
- std::pair<std::string,std::string>("houstonia", "normal"),
- std::pair<std::string,std::string>("red_tulip", "normal"),
- std::pair<std::string,std::string>("orange_tulip", "normal"),
- std::pair<std::string,std::string>("white_tulip", "normal"),
- std::pair<std::string,std::string>("pink_tulip", "normal"),
- std::pair<std::string,std::string>("oxeye_daisy", "normal"),
- };
- return ids[blockId.state];
- }
- case 39: {
- return std::make_pair("brown_mushroom","normal");
- }
- case 40: {
- return std::make_pair("red_mushroom", "normal");
- }
- case 41: {
- return std::make_pair("gold_block", "normal");
- }
- case 44: {
- return std::make_pair("stone_slab", "half=" + std::string(!(blockId.state >> 3) ? "bottom" : "top"));
- }
- case 45: {
- return std::make_pair("brick_block", "normal");
- }
- case 46: {
- return std::make_pair("tnt", "normal");
- }
- case 47: {
- return std::make_pair("bookshelf", "normal");
- }
- case 48: {
- return std::make_pair("mossy_cobblestone", "normal");
- }
- case 49: {
- return std::make_pair("obsidian", "normal");
- }
- case 50: {
- if (blockId.state > 5)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("", ""),
- std::pair<std::string,std::string>("torch", "facing=east"),
- std::pair<std::string,std::string>("torch", "facing=west"),
- std::pair<std::string,std::string>("torch", "facing=south"),
- std::pair<std::string,std::string>("torch", "facing=north"),
- std::pair<std::string,std::string>("torch", "facing=up"),
- };
- return ids[blockId.state];
- }
- case 53: {
- bool isUp = blockId.state >> 2;
- unsigned char dir = blockId.state & 0x3;
- static const std::string dirs[] = {
- "facing=east,half=",
- "facing=west,half=",
- "facing=south,half=",
- "facing=north,half=",
- };
+#include <map>
- return std::make_pair("oak_stairs", dirs[dir] + (isUp? "top" : "bottom") +",shape=straight");
- }
- case 56: {
- return std::make_pair("diamond_ore", "normal");
- }
- case 57: {
- return std::make_pair("diamond_block", "normal");
- }
- case 59: {
- return std::make_pair("wheat", "age=" + std::to_string(blockId.state));
- }
- case 60: {
- return std::make_pair("farmland", "moisture=" + std::to_string(7 - blockId.state));
- }
- case 61: {
- static const std::string dirs[] = {
- "",
- "",
- "facing=north",
- "facing=south",
- "facing=west",
- "facing=east",
- };
- return std::make_pair("furnace", dirs[blockId.state]);
- }
- case 64: {
- bool isUp = !(blockId.state >> 3);
- bool hingeIsLeft = true;
- bool isOpen = 0;
- unsigned char dir = 0;
- if (isUp)
- hingeIsLeft = blockId.state & 0x1;
- else {
- isOpen = (blockId.state >> 1) & 0x1;
- dir = blockId.state >> 2;
- }
- static const std::string dirs[] = {
- "east",
- "south",
- "west",
- "north",
- };
+#include "Plugin.hpp"
- return std::make_pair("wooden_door", "facing=" + dirs[dir] + ",half=" + (isUp ? "upper" : "lower") + ",hinge=" + (hingeIsLeft ? "left" : "right") + ",open=" + (isOpen ? "true" : "false"));
- }
- case 67: {
- bool isUp = blockId.state >> 2;
- unsigned char dir = blockId.state & 0x3;
- static const std::string dirs[] = {
- "facing=east,half=",
- "facing=west,half=",
- "facing=south,half=",
- "facing=north,half=",
- };
+std::map<BlockId, BlockInfo> staticBlockInfo;
- return std::make_pair("stone_stairs", dirs[dir] + (isUp ? "top" : "bottom") + ",shape=straight");
- }
- case 69: {
- bool isActive = blockId.state >> 3;
- static const std::string types[] = {
- "facing=down_x",
- "facing=east",
- "facing=west",
- "facing=south",
- "facing=north",
- "facing=up_z",
- "facing=up_x",
- "facing=down_z",
- };
-
- return std::make_pair("lever", types[blockId.state & 0x7] + ",powered=" + (isActive ? "true" : "false"));
- }
- case 73: {
- return std::make_pair("redstone_ore", "normal");
- }
- case 74: {
- return std::make_pair("redstone_ore", "normal");
- }
- case 78: {
- if (blockId.state > 7)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("snow_layer", "layers=1"),
- std::pair<std::string,std::string>("snow_layer", "layers=2"),
- std::pair<std::string,std::string>("snow_layer", "layers=3"),
- std::pair<std::string,std::string>("snow_layer", "layers=4"),
- std::pair<std::string,std::string>("snow_layer", "layers=5"),
- std::pair<std::string,std::string>("snow_layer", "layers=6"),
- std::pair<std::string,std::string>("snow_layer", "layers=7"),
- std::pair<std::string,std::string>("snow_layer", "layers=8"),
- };
- return ids[blockId.state];
- }
- case 79: {
- return std::make_pair("ice", "normal");
- }
- case 80: {
- return std::make_pair("snow", "normal");
- }
- case 81: {
- return std::make_pair("cactus", "normal");
- }
- case 82: {
- return std::make_pair("clay", "normal");
- }
- case 83: {
- return std::make_pair("reeds", "normal");
- }
- case 86: {
- if (blockId.state > 3)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("pumpkin", "facing=south"),
- std::pair<std::string,std::string>("pumpkin", "facing=west"),
- std::pair<std::string,std::string>("pumpkin", "facing=north"),
- std::pair<std::string,std::string>("pumpkin", "facing=east"),
- };
- return ids[blockId.state];
- }
- case 87: {
- return std::make_pair("netherrack", "normal");
- }
- case 88: {
- return std::make_pair("soul_sand", "normal");
- }
- case 89: {
- return std::make_pair("glowstone", "normal");
- }
- case 90: {
- return std::make_pair("portal", blockId.state == 1 ? "axis=x" : "axis=z");
- }
- case 93: {
- static const std::string dirs[] = {
- "east",
- "south",
- "west",
- "north",
- };
- unsigned char dir = blockId.state & 0x3;
- unsigned char delay = (blockId.state >> 2) + 1;
- return std::make_pair("unpowered_repeater", "delay=" + std::to_string(delay) + ",facing=" + dirs[dir] + ",locked=false");
- }
- case 94: {
- static const std::string dirs[] = {
- "east",
- "south",
- "west",
- "north",
- };
- unsigned char dir = blockId.state & 0x3;
- unsigned char delay = (blockId.state >> 2) + 1;
- return std::make_pair("powered_repeater", "delay=" + std::to_string(delay) + ",facing=" + dirs[dir] + ",locked=false");
- }
- case 99: {
- static const std::string variants[] = {
- "variant=all_inside",
- "variant=north_west",
- "variant=north",
- "variant=north_east",
- "variant=west",
- "variant=center",
- "variant=east",
- "variant=south_west",
- "variant=south",
- "variant=south_east",
- "variant=stem",
- "variant=all_outside",
- "variant=all_stem",
- };
- return std::make_pair("brown_mushroom_block", variants[blockId.state]);
- }
- case 100: {
- static const std::string variants[] = {
- "variant=all_inside",
- "variant=north_west",
- "variant=north",
- "variant=north_east",
- "variant=west",
- "variant=center",
- "variant=east",
- "variant=south_west",
- "variant=south",
- "variant=south_east",
- "variant=stem",
- "variant=all_outside",
- "variant=all_stem",
- };
- return std::make_pair("red_mushroom_block", variants[blockId.state]);
- }
- case 103: {
- return std::make_pair("melon_block", "normal");
- }
- case 106: {
- static const std::string values[] = {
- "false",
- "true",
- };
- return std::make_pair("vine", "east=" + values[(blockId.state >> 3) & 0x1] + ",north=" + values[(blockId.state >> 2) & 0x1] + ",south=" + values[blockId.state & 0x1] + ",up=" + values[blockId.state == 0] + ",west=" + values[(blockId.state >> 1) & 0x1]);
- }
- case 111: {
- return std::make_pair("waterlily", "normal");
- }
- case 112: {
- return std::make_pair("nether_brick", "normal");
- }
- case 121: {
- return std::make_pair("end_stone", "normal");
- }
- case 129: {
- return std::make_pair("emerald_ore", "normal");
- }
- case 133: {
- return std::make_pair("emerald_block", "normal");
- }
- case 141: {
- return std::make_pair("carrots", "age=" + std::to_string(blockId.state));
- }
- case 142: {
- return std::make_pair("potatoes", "age=" + std::to_string(blockId.state));
- }
- case 149: {
- static const std::string dirs[] = {
- "east",
- "south",
- "west",
- "north",
- };
- unsigned char dir = blockId.state & 0x3;
- bool substractMode = (blockId.state >> 2) & 0x1;
- bool isPowered = blockId.state >> 3;
- return std::make_pair("unpowered_comparator", "facing=" + dirs[dir] + ",mode=" + (substractMode ? "subtract" : "compare") + ",powered=" + (isPowered ? "true" : "false"));
- }
- case 153: {
- return std::make_pair("quartz_ore", "normal");
- }
- case 155: {
- return std::make_pair("quartz_block", "normal");
- }
- case 161: {
- if ((blockId.state & 0x3) > 2)
- break;
- static const std::pair<std::string, std::string> ids[] = {
- std::pair<std::string,std::string>("acacia_leaves", "normal"),
- std::pair<std::string,std::string>("dark_oak_leaves", "normal"),
- };
- return ids[blockId.state & 0x3];
- }
- case 162: {
- unsigned char type = blockId.state & 0x3;
- if (type > 2)
- break;
- unsigned char dir = (blockId.state & 0xC) >> 2;
- static const std::string types[] = {
- "acacia_log",
- "dark_oak_log",
- };
- static const std::string dirs[] = {
- "axis=y",
- "axis=x",
- "axis=z",
- "axis=none",
- };
- return std::make_pair(types[type], dirs[dir]);
- }
- case 175: {
- bool high = ((blockId.state >> 3) & 0x1);
- unsigned char type = blockId.state & 0x7;
-
- static const std::string types[] = {
- "sunflower",
- "syringa",
- "double_grass",
- "double_fern",
- "double_rose",
- "paeonia",
- };
+void RegisterStaticBlockInfo(BlockId blockId, BlockInfo blockInfo) {
+ staticBlockInfo[blockId] = blockInfo;
+}
- static const std::string isHigh[] = {
- "half=lower",
- "half=upper",
- };
- return std::make_pair(types[type], isHigh[high]);
- }
- case 207: {
- return std::make_pair("beetroots", "age=" + std::to_string(blockId.state));
- }
- case 208: {
- return std::make_pair("grass_path", "normal");
- }
- default:
- break;
- }
-
- return std::make_pair("", "");
+BlockInfo GetBlockInfo(BlockId blockId, Vector blockPos) {
+ auto it = staticBlockInfo.find(blockId);
+ if (it != staticBlockInfo.end())
+ return it->second;
+ if (blockPos == Vector())
+ return BlockInfo{ true, "", "" };
+ return PluginSystem::RequestBlockInfo(blockPos);
}
diff --git a/src/Block.hpp b/src/Block.hpp
index fa8b51a..fbeeaeb 100644
--- a/src/Block.hpp
+++ b/src/Block.hpp
@@ -3,6 +3,8 @@
#include <utility>
#include <string>
+#include "Vector.hpp"
+
struct BlockId {
unsigned short id : 13;
unsigned char state : 4;
@@ -39,5 +41,12 @@ namespace std {
};
}
-//returns name of blockstate and name of variant
-std::pair<std::string, std::string> TransformBlockIdToBlockStateName(BlockId blockId); \ No newline at end of file
+struct BlockInfo {
+ bool collides;
+ std::string blockstate;
+ std::string variant;
+};
+
+void RegisterStaticBlockInfo(BlockId blockId, BlockInfo blockInfo);
+
+BlockInfo GetBlockInfo(BlockId blockId, Vector blockPos = Vector(0,0,0)); \ No newline at end of file
diff --git a/src/Event.cpp b/src/Event.cpp
index 5c126bb..ea09af3 100644
--- a/src/Event.cpp
+++ b/src/Event.cpp
@@ -1,5 +1,7 @@
#include "Event.hpp"
+#include <optick.h>
+
std::list<EventListener*> EventSystem::listeners;
std::recursive_mutex EventSystem::listenersMutex;
@@ -14,6 +16,7 @@ EventListener::~EventListener() {
}
void EventListener::HandleEvent() {
+ OPTICK_EVENT();
if (!NotEmpty())
return;
@@ -27,6 +30,7 @@ void EventListener::HandleEvent() {
}
void EventListener::HandleAllEvents() {
+ OPTICK_EVENT();
if (!NotEmpty())
return;
@@ -54,6 +58,7 @@ void EventListener::RegisterHandler(size_t eventId, const EventListener::Handler
}
void EventListener::PollEvents() {
+ OPTICK_EVENT();
std::lock_guard<std::recursive_mutex> rawLock (rawEventsMutex);
if (rawEvents.empty())
return;
diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp
index fb7ebc7..d81b0e0 100644
--- a/src/Framebuffer.cpp
+++ b/src/Framebuffer.cpp
@@ -3,11 +3,13 @@
#include <string>
#include "Utility.hpp"
#include "AssetManager.hpp"
+#include <optick.h>
const GLuint magic = 316784;
GLuint quadVao = magic, quadVbo = magic;
Framebuffer::Framebuffer(unsigned int width, unsigned int height, bool createDepthStencilBuffer) : width(width), height(height) {
+ OPTICK_EVENT();
if (quadVao == magic) {
float quadVertices[] = {
// positions // texCoords
@@ -70,11 +72,13 @@ Framebuffer::~Framebuffer() {
}
void Framebuffer::Activate() {
+ OPTICK_EVENT();
glViewport(0, 0, width, height);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}
void Framebuffer::RenderTo(Framebuffer &target) {
+ OPTICK_EVENT();
glBindFramebuffer(GL_FRAMEBUFFER, target.fbo);
glViewport(0, 0, target.width, target.height);
AssetManager::GetAsset<AssetShader>("/altcraft/shaders/fbo")->shader->Activate();
@@ -96,8 +100,8 @@ void Framebuffer::Resize(unsigned int newWidth, unsigned int newHeight) {
}
}
-Framebuffer &Framebuffer::GetDefault()
-{
+Framebuffer &Framebuffer::GetDefault() {
+ OPTICK_EVENT();
static char fboDefaultData[sizeof(Framebuffer)];
static Framebuffer *fboDefault = nullptr;
if (fboDefault == nullptr) {
@@ -111,8 +115,8 @@ Framebuffer &Framebuffer::GetDefault()
return *fboDefault;
}
-void Framebuffer::Clear(bool color, bool depth, bool stencil)
-{
+void Framebuffer::Clear(bool color, bool depth, bool stencil) {
+ OPTICK_EVENT();
Activate();
GLbitfield clearBits = 0;
if (color)
diff --git a/src/Game.cpp b/src/Game.cpp
new file mode 100644
index 0000000..c69ff5d
--- /dev/null
+++ b/src/Game.cpp
@@ -0,0 +1,241 @@
+#include "Game.hpp"
+
+#include <memory>
+
+#include <optick.h>
+
+#include "Render.hpp"
+#include "GameState.hpp"
+#include "NetworkClient.hpp"
+#include "Plugin.hpp"
+
+bool isRunning = true;
+bool isMoving[5] = { 0,0,0,0,0 };
+State state;
+std::unique_ptr<NetworkClient> nc;
+std::unique_ptr<GameState> gs;
+std::unique_ptr<Render> render;
+std::unique_ptr<LoopExecutionTimeController> timer;
+EventListener listener;
+
+void InitEvents() {
+ /*
+ * Network Events
+ */
+
+ listener.RegisterHandler("ConnectToServer", [](const Event & eventData) {
+ auto data = eventData.get <std::tuple<std::string, unsigned short, std::string>>(); //address,port,username
+ if (std::get<0>(data) == "" || std::get<1>(data) == 0)
+ LOG(FATAL) << "NOT VALID CONNECT-TO-SERVER EVENT";
+ if (nc != nullptr) {
+ LOG(ERROR) << "Already connected";
+ return;
+ }
+ LOG(INFO) << "Connecting to server at address " + std::get<0>(data) + ":" + std::to_string(std::get<1>(data)) + " as " + std::get<2>(data);
+ PUSH_EVENT("Connecting",0);
+ gs = std::make_unique<GameState>();
+ try {
+ nc = std::make_unique<NetworkClient>(std::get<0>(data),
+ std::get<1>(data),
+ std::get<2>(data));
+ } catch (std::exception &e) {
+ LOG(WARNING) << "Connection failed";
+ PUSH_EVENT("ConnectionFailed", std::string(e.what()));
+ gs.reset();
+ return;
+ }
+ LOG(INFO) << "Connected to server";
+ PUSH_EVENT("ConnectionSuccessfull", 0);
+ });
+
+ listener.RegisterHandler("Disconnect", [](const Event& eventData) {
+ auto data = eventData.get<std::string>();
+ PUSH_EVENT("Disconnected", data);
+ LOG(INFO) << "Disconnected: " << data;
+ nc.reset();
+ });
+
+ listener.RegisterHandler("NetworkClientException", [](const Event& eventData) {
+ auto data = eventData.get < std::string>();
+ PUSH_EVENT("Disconnect", data);
+ });
+
+ /*
+ * GameState Events
+ */
+
+ listener.RegisterHandler("Exit", [](const Event&) {
+ isRunning = false;
+ });
+
+ listener.RegisterHandler("Disconnected", [](const Event&) {
+ if (!gs)
+ return;
+ gs.reset();
+ });
+
+ listener.RegisterHandler("SendChatMessage", [](const Event& eventData) {
+ auto message = eventData.get<std::string>();
+ if (message[0] == '!' && message[1] != '!') {
+ PluginSystem::Execute(message.substr(1));
+ return;
+ }
+ if (message[0] == '!')
+ message = message.substr(1);
+ auto packet = std::static_pointer_cast<Packet>(std::make_shared<PacketChatMessageSB>(message));
+ PUSH_EVENT("SendPacket",packet);
+ });
+
+ /*
+ * Phys Events
+ */
+
+ listener.RegisterHandler("KeyPressed", [](const Event& eventData) {
+ if (!gs)
+ return;
+ switch (eventData.get<SDL_Scancode>()) {
+ case SDL_SCANCODE_W:
+ isMoving[GameState::FORWARD] = true;
+ break;
+ case SDL_SCANCODE_A:
+ isMoving[GameState::LEFT] = true;
+ break;
+ case SDL_SCANCODE_S:
+ isMoving[GameState::BACKWARD] = true;
+ break;
+ case SDL_SCANCODE_D:
+ isMoving[GameState::RIGHT] = true;
+ break;
+ case SDL_SCANCODE_SPACE:
+ isMoving[GameState::JUMP] = true;
+ break;
+ default:
+ break;
+ }
+ });
+
+ listener.RegisterHandler("KeyReleased", [](const Event& eventData) {
+ if (!gs)
+ return;
+ switch (eventData.get<SDL_Scancode>()) {
+ case SDL_SCANCODE_W:
+ isMoving[GameState::FORWARD] = false;
+ break;
+ case SDL_SCANCODE_A:
+ isMoving[GameState::LEFT] = false;
+ break;
+ case SDL_SCANCODE_S:
+ isMoving[GameState::BACKWARD] = false;
+ break;
+ case SDL_SCANCODE_D:
+ isMoving[GameState::RIGHT] = false;
+ break;
+ case SDL_SCANCODE_SPACE:
+ isMoving[GameState::JUMP] = false;
+ break;
+ default:
+ break;
+ }
+ });
+
+ listener.RegisterHandler("MouseMove", [](const Event& eventData) {
+ if (!gs)
+ return;
+ auto data = eventData.get<std::tuple<double,double>>();
+ gs->HandleRotation(std::get<0>(data),std::get<1>(data));
+ });
+
+ listener.RegisterHandler("ReceivedPacket", [](const Event& eventData) {
+ if (!gs)
+ return;
+ std::shared_ptr<Packet> packet = eventData.get<std::shared_ptr<Packet>>();
+ gs->UpdatePacket(packet);
+ });
+
+ listener.RegisterHandler("LmbPressed",[](const Event& eventData) {
+ if (!gs)
+ return;
+ gs->StartDigging();
+ });
+
+ listener.RegisterHandler("LmbReleased",[](const Event& eventData) {
+ if (!gs)
+ return;
+ gs->CancelDigging();
+ });
+
+ listener.RegisterHandler("RmbPressed", [](const Event& eventData) {
+ if (!gs)
+ return;
+ gs->PlaceBlock();
+ });
+
+ listener.RegisterHandler("SelectedBlockChanged", [](const Event& eventData) {
+ if (!gs)
+ return;
+ //TODO:
+ //gs->CancelDigging();
+ });
+}
+
+void RunGame() {
+ OPTICK_THREAD("Main");
+ InitEvents();
+
+ timer = std::make_unique<LoopExecutionTimeController>(std::chrono::milliseconds(16));
+
+ render = std::make_unique<Render>(900, 480, "AltCraft");
+
+ SetState(State::MainMenu);
+
+ while (isRunning) {
+ OPTICK_FRAME("MainThread");
+ listener.HandleAllEvents();
+ PluginSystem::CallOnTick(timer->GetRealDeltaS());
+ if (gs) {
+ if (GetState() == State::Playing) {
+ if (isMoving[GameState::FORWARD])
+ gs->HandleMovement(GameState::FORWARD, timer->GetRealDeltaS());
+ if (isMoving[GameState::BACKWARD])
+ gs->HandleMovement(GameState::BACKWARD, timer->GetRealDeltaS());
+ if (isMoving[GameState::LEFT])
+ gs->HandleMovement(GameState::LEFT, timer->GetRealDeltaS());
+ if (isMoving[GameState::RIGHT])
+ gs->HandleMovement(GameState::RIGHT, timer->GetRealDeltaS());
+ if (isMoving[GameState::JUMP])
+ gs->HandleMovement(GameState::JUMP, timer->GetRealDeltaS());
+ }
+ gs->Update(timer->GetRealDeltaS());
+ }
+ render->Update();
+ timer->Update();
+ }
+
+ render.reset();
+}
+
+State GetState() {
+ return state;
+}
+
+void SetState(State newState) {
+ if (newState != state)
+ PUSH_EVENT("StateUpdated", 0);
+ state = newState;
+}
+
+GameState *GetGameState() {
+ return gs.get();
+}
+
+Render *GetRender() {
+ return render.get();
+}
+
+NetworkClient *GetNetworkClient() {
+ return nc.get();
+}
+
+LoopExecutionTimeController* GetTime() {
+ return timer.get();
+}
diff --git a/src/Game.hpp b/src/Game.hpp
new file mode 100644
index 0000000..f7efd11
--- /dev/null
+++ b/src/Game.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+class GameState;
+class Render;
+class NetworkClient;
+class LoopExecutionTimeController;
+
+enum class State {
+ InitialLoading,
+ MainMenu,
+ Loading,
+ Playing,
+ Paused,
+ Inventory,
+ Chat,
+};
+
+void RunGame();
+
+State GetState();
+
+void SetState(State newState);
+
+GameState* GetGameState();
+
+Render* GetRender();
+
+NetworkClient* GetNetworkClient();
+
+LoopExecutionTimeController *GetTime(); \ No newline at end of file
diff --git a/src/GameState.cpp b/src/GameState.cpp
index ace2488..e4278ec 100644
--- a/src/GameState.cpp
+++ b/src/GameState.cpp
@@ -2,11 +2,13 @@
#include <glm/gtc/matrix_transform.hpp>
#include <easylogging++.h>
+#include <optick.h>
#include "Event.hpp"
#include "Packet.hpp"
-void GameState::Update(float deltaTime) {
+void GameState::Update(double deltaTime) {
+ OPTICK_EVENT();
if (!gameStatus.isGameStarted)
return;
diff --git a/src/GameState.hpp b/src/GameState.hpp
index 8318c8a..5489ac6 100644
--- a/src/GameState.hpp
+++ b/src/GameState.hpp
@@ -70,7 +70,7 @@ class GameState {
std::vector<Window> openedWindows;
public:
- void Update(float deltaTime);
+ void Update(double deltaTime);
void UpdatePacket(std::shared_ptr<Packet> ptr);
diff --git a/src/GlobalState.cpp b/src/GlobalState.cpp
deleted file mode 100644
index afa1a56..0000000
--- a/src/GlobalState.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-#include "GlobalState.hpp"
-
-#include "NetworkClient.hpp"
-#include "GameState.hpp"
-#include "Render.hpp"
-#include "DebugInfo.hpp"
-#include "Event.hpp"
-
-//Global game variables
-std::unique_ptr<NetworkClient> nc;
-std::unique_ptr<GameState> gs;
-std::shared_ptr<GameState> gsReadOnly;
-std::unique_ptr<Render> render;
-bool isRunning;
-bool isPhysRunning;
-EventListener listener;
-bool isMoving[5] = { 0,0,0,0,0 };
-std::thread threadPhys;
-State state;
-std::mutex gsCopyMutex;
-
-void PhysExec();
-
-void InitEvents() {
- /*
- * Network Events
- */
-
- listener.RegisterHandler("Exit", [](const Event&) {
- isRunning = false;
- });
-
- listener.RegisterHandler("ConnectToServer", [](const Event& eventData) {
- auto data = eventData.get <std::tuple<std::string, unsigned short, std::string>>(); //address,port,username
- if (std::get<0>(data) == "" || std::get<1>(data) == 0)
- LOG(FATAL) << "NOT VALID CONNECT-TO-SERVER EVENT";
- if (nc != nullptr) {
- LOG(ERROR) << "Already connected";
- return;
- }
- LOG(INFO) << "Connecting to server at address " + std::get<0>(data) + ":" + std::to_string(std::get<1>(data)) + " as " + std::get<2>(data);
- PUSH_EVENT("Connecting",0);
- gs = std::make_unique<GameState>();
- isPhysRunning = true;
- threadPhys = std::thread(&PhysExec);
- try {
- nc = std::make_unique<NetworkClient>(std::get<0>(data),
- std::get<1>(data),
- std::get<2>(data));
- } catch (std::exception &e) {
- LOG(WARNING) << "Connection failed";
- PUSH_EVENT("ConnectionFailed", std::string(e.what()));
- isPhysRunning = false;
- threadPhys.join();
- gs.reset();
- return;
- }
- LOG(INFO) << "Connected to server";
- PUSH_EVENT("ConnectionSuccessfull", 0);
- });
-
- listener.RegisterHandler("Disconnect", [](const Event& eventData) {
- auto data = eventData.get<std::string>();
- PUSH_EVENT("Disconnected", data);
- LOG(INFO) << "Disconnected: " << data;
- nc.reset();
- });
-
- listener.RegisterHandler("NetworkClientException", [](const Event& eventData) {
- auto data = eventData.get < std::string>();
- PUSH_EVENT("Disconnect", data);
- });
-
- /*
- * GameState Events
- */
-
- listener.RegisterHandler("Exit", [](const Event&) {
- isRunning = false;
- });
-
- listener.RegisterHandler("Disconnected", [](const Event&) {
- if (!gs)
- return;
- isPhysRunning = false;
- threadPhys.join();
- gs.reset();
- });
-
- listener.RegisterHandler("SendChatMessage", [](const Event& eventData) {
- auto message = eventData.get<std::string>();
- auto packet = std::static_pointer_cast<Packet>(std::make_shared<PacketChatMessageSB>(message));
- PUSH_EVENT("SendPacket",packet);
- });
-}
-
-void PhysExec() {
- EventListener listener;
-
- listener.RegisterHandler("KeyPressed", [](const Event& eventData) {
- if (!gs)
- return;
- switch (eventData.get<SDL_Scancode>()) {
- case SDL_SCANCODE_W:
- isMoving[GameState::FORWARD] = true;
- break;
- case SDL_SCANCODE_A:
- isMoving[GameState::LEFT] = true;
- break;
- case SDL_SCANCODE_S:
- isMoving[GameState::BACKWARD] = true;
- break;
- case SDL_SCANCODE_D:
- isMoving[GameState::RIGHT] = true;
- break;
- case SDL_SCANCODE_SPACE:
- isMoving[GameState::JUMP] = true;
- break;
- default:
- break;
- }
- });
-
- listener.RegisterHandler("KeyReleased", [](const Event& eventData) {
- if (!gs)
- return;
- switch (eventData.get<SDL_Scancode>()) {
- case SDL_SCANCODE_W:
- isMoving[GameState::FORWARD] = false;
- break;
- case SDL_SCANCODE_A:
- isMoving[GameState::LEFT] = false;
- break;
- case SDL_SCANCODE_S:
- isMoving[GameState::BACKWARD] = false;
- break;
- case SDL_SCANCODE_D:
- isMoving[GameState::RIGHT] = false;
- break;
- case SDL_SCANCODE_SPACE:
- isMoving[GameState::JUMP] = false;
- break;
- default:
- break;
- }
- });
-
- listener.RegisterHandler("MouseMove", [](const Event& eventData) {
- if (!gs)
- return;
- auto data = eventData.get<std::tuple<double,double>>();
- gs->HandleRotation(std::get<0>(data),std::get<1>(data));
- });
-
- listener.RegisterHandler("ReceivedPacket", [](const Event& eventData) {
- std::shared_ptr<Packet> packet = eventData.get<std::shared_ptr<Packet>>();
- gs->UpdatePacket(packet);
- });
-
- listener.RegisterHandler("LmbPressed",[](const Event& eventData) {
- gs->StartDigging();
- });
-
- listener.RegisterHandler("LmbReleased",[](const Event& eventData) {
- gs->CancelDigging();
- });
-
- listener.RegisterHandler("RmbPressed", [](const Event& eventData) {
- gs->PlaceBlock();
- });
-
- listener.RegisterHandler("SelectedBlockChanged", [](const Event& eventData) {
- //TODO:
- //gs->CancelDigging();
- });
-
- LoopExecutionTimeController timer(std::chrono::milliseconds(8));
-
- while (isPhysRunning) {
- DebugInfo::gameThreadTime = timer.GetRealDeltaS() * 1000'00.0f;
-
- if (state == State::Playing) {
- if (isMoving[GameState::FORWARD])
- gs->HandleMovement(GameState::FORWARD, timer.GetRealDeltaS());
- if (isMoving[GameState::BACKWARD])
- gs->HandleMovement(GameState::BACKWARD, timer.GetRealDeltaS());
- if (isMoving[GameState::LEFT])
- gs->HandleMovement(GameState::LEFT, timer.GetRealDeltaS());
- if (isMoving[GameState::RIGHT])
- gs->HandleMovement(GameState::RIGHT, timer.GetRealDeltaS());
- if (isMoving[GameState::JUMP])
- gs->HandleMovement(GameState::JUMP, timer.GetRealDeltaS());
- }
-
- gs->Update(timer.GetRealDeltaS());
-
- listener.HandleAllEvents();
-
- gsCopyMutex.lock();
- gsReadOnly = std::make_shared<GameState>(*gs.get());
- gsCopyMutex.unlock();
-
- timer.Update();
- }
-}
-
-void GlobalState::Exec() {
- render = std::make_unique<Render>(900, 480, "AltCraft");
- isRunning = true;
- InitEvents();
- GlobalState::SetState(State::MainMenu);
- while (isRunning) {
- render->Update();
- listener.HandleAllEvents();
- }
- PUSH_EVENT("Exit", 0);
- isRunning = false;
- render.reset();
-}
-
-std::shared_ptr<GameState> GlobalState::GetGameState() {
- std::lock_guard<std::mutex> guard(gsCopyMutex);
- return gsReadOnly;
-}
-
-Render *GlobalState::GetRender() {
- return render.get();
-}
-
-State GlobalState::GetState() {
- return state;
-}
-
-void GlobalState::SetState(const State &newState) {
- if (newState != state)
- PUSH_EVENT("StateUpdated", 0);
- state = newState;
-}
diff --git a/src/GlobalState.hpp b/src/GlobalState.hpp
deleted file mode 100644
index bc7224f..0000000
--- a/src/GlobalState.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include <memory>
-
-class NetworkClient;
-class GameState;
-class Render;
-
-enum class State {
- InitialLoading,
- MainMenu,
- Loading,
- Playing,
- Paused,
- Inventory,
- Chat,
-};
-
-struct GlobalState {
- static std::shared_ptr<GameState> GetGameState();
- static Render *GetRender();
- static void Exec();
- static State GetState();
- static void SetState(const State &newState);
-}; \ No newline at end of file
diff --git a/src/Plugin.cpp b/src/Plugin.cpp
new file mode 100644
index 0000000..8d2de94
--- /dev/null
+++ b/src/Plugin.cpp
@@ -0,0 +1,261 @@
+#include "Plugin.hpp"
+
+#include <vector>
+
+#include <easylogging++.h>
+#include <sol.hpp>
+#include <optick.h>
+
+#include "GameState.hpp"
+#include "Game.hpp"
+#include "Event.hpp"
+#include "AssetManager.hpp"
+
+
+struct Plugin {
+ int errors;
+ const std::string name;
+ const std::string displayName;
+ const std::function<void()> onLoad;
+ const std::function<void()> onUnload;
+ const std::function<void(std::string)> onChangeState;
+ const std::function<void(double)> onTick;
+ const std::function<BlockInfo(Vector)> onRequestBlockInfo;
+};
+
+
+std::vector<Plugin> plugins;
+sol::state lua;
+
+
+namespace PluginApi {
+
+ void RegisterPlugin(sol::table plugin) {
+ Plugin nativePlugin {
+ 0,
+ plugin["name"].get_or<std::string>(""),
+ plugin["displayName"].get_or<std::string>(""),
+ plugin["onLoad"].get_or(std::function<void()>()),
+ plugin["onUnload"].get_or(std::function<void()>()),
+ plugin["onChangeState"].get_or(std::function<void(std::string)>()),
+ plugin["onTick"].get_or(std::function<void(double)>()),
+ plugin["onRequestBlockInfo"].get_or(std::function<BlockInfo(Vector)>()),
+ };
+ plugins.push_back(nativePlugin);
+ nativePlugin.onLoad();
+
+ LOG(INFO) << "Loaded plugin " << (!nativePlugin.displayName.empty() ? nativePlugin.displayName : nativePlugin.name);
+ }
+
+ void LogWarning(std::string text) {
+ LOG(WARNING) << text;
+ }
+
+ void LogInfo(std::string text) {
+ LOG(INFO) << text;
+ }
+
+ void LogError(std::string text) {
+ LOG(ERROR) << text;
+ }
+
+ GameState *GetGameState() {
+ return ::GetGameState();
+ }
+
+ void RegisterBlock(BlockId blockId, bool collides, std::string blockstate, std::string variant) {
+ RegisterStaticBlockInfo(blockId, BlockInfo{
+ collides,
+ blockstate,
+ variant
+ });
+ }
+}
+
+int LoadFileRequire(lua_State* L) {
+ std::string path = sol::stack::get<std::string>(L);
+
+ std::string package = path.substr(0, path.find('/'));
+ std::string script = path.substr(path.find('/') + 1);
+
+ std::string scriptPath = "/" + package + "/scripts/" + script;
+
+ AssetScript *asset = AssetManager::GetAsset<AssetScript>(scriptPath);
+ if (!asset) {
+ sol::stack::push(L, "Module '" + scriptPath + "' not found");
+ return 1;
+ }
+
+ luaL_loadbuffer(L, asset->code.data(), asset->code.size(), path.c_str());
+ return 1;
+}
+
+void PluginSystem::Init() {
+ OPTICK_EVENT();
+ LOG(INFO) << "Initializing plugin system";
+ for (Plugin &plugin : plugins) {
+ if (plugin.onUnload && plugin.errors < 10)
+ plugin.onUnload();
+ }
+
+ plugins.clear();
+ lua = sol::state();
+ lua.open_libraries();
+
+ lua["package"]["searchers"] = lua.create_table_with(
+ 1, LoadFileRequire
+ );
+
+ lua.new_usertype<Entity>("Entity",
+ "pos", &Entity::pos);
+
+ lua.new_usertype<GameState>("GameState",
+ "GetPlayer", &GameState::GetPlayer,
+ "GetWorld", &GameState::GetWorld,
+ "GetTimeStatus", &GameState::GetTimeStatus,
+ "GetGameStatus", &GameState::GetGameStatus,
+ "GetPlayerStatus", &GameState::GetPlayerStatus,
+ "GetSelectionStatus", &GameState::GetSelectionStatus,
+ "GetInventory", &GameState::GetInventory);
+
+ lua.new_usertype<TimeStatus>("TimeStatus",
+ "interpolatedTimeOfDay", &TimeStatus::interpolatedTimeOfDay,
+ "worldAge", &TimeStatus::worldAge,
+ "timeOfDay", &TimeStatus::timeOfDay,
+ "doDaylightCycle", &TimeStatus::doDaylightCycle);
+
+ lua.new_usertype<GameStatus>("GameStatus",
+ "levelType", &GameStatus::levelType,
+ "spawnPosition", &GameStatus::spawnPosition,
+ "gamemode", &GameStatus::gamemode,
+ "dimension", &GameStatus::dimension,
+ "difficulty", &GameStatus::difficulty,
+ "maxPlayers", &GameStatus::maxPlayers,
+ "isGameStarted", &GameStatus::isGameStarted,
+ "reducedDebugInfo", &GameStatus::reducedDebugInfo);
+
+ lua.new_usertype<SelectionStatus>("SelectionStatus",
+ "raycastHit", &SelectionStatus::raycastHit,
+ "selectedBlock", &SelectionStatus::selectedBlock,
+ "distanceToSelectedBlock", &SelectionStatus::distanceToSelectedBlock,
+ "isBlockSelected", &SelectionStatus::isBlockSelected);
+
+ lua.new_usertype<PlayerStatus>("PlayerStatus",
+ "uid", &PlayerStatus::uid,
+ "name", &PlayerStatus::name,
+ "flyingSpeed", &PlayerStatus::flyingSpeed,
+ "fovModifier", &PlayerStatus::fovModifier,
+ "health", &PlayerStatus::health,
+ "eid", &PlayerStatus::eid,
+ "invulnerable", &PlayerStatus::invulnerable,
+ "flying", &PlayerStatus::flying,
+ "allowFlying", &PlayerStatus::allowFlying,
+ "creativeMode", &PlayerStatus::creativeMode);
+
+ lua.new_usertype<World>("World",
+ "GetEntitiesList", &World::GetEntitiesList,
+ "GetEntity",&World::GetEntityPtr,
+ "Raycast", &World::Raycast,
+ "GetBlockId", &World::GetBlockId,
+ "SetBlockId", &World::SetBlockId);
+
+ auto bidFactory1 = []() {
+ return BlockId{ 0,0 };
+ };
+ auto bidFactory2 = [](unsigned short id, unsigned char state) {
+ return BlockId{ id,state };
+ };
+
+ lua.new_usertype<BlockId>("BlockId",
+ "new", sol::factories([]() {return BlockId{ 0,0 };},
+ [](unsigned short id, unsigned char state) {return BlockId{ id, state };}),
+ "id", sol::property(
+ [](BlockId & bid) { return bid.id; },
+ [](BlockId & bid, unsigned short id) { bid.id = id; }),
+ "state", sol::property(
+ [](BlockId & bid) { return bid.state; },
+ [](BlockId & bid, unsigned char state) { bid.state = state; }));
+
+ lua.new_usertype<Vector>("Vector",
+ sol::constructors<Vector(),Vector(long long, long long, long long)>(),
+ "x", &Vector::x,
+ "y", &Vector::y,
+ "z", &Vector::z);
+
+ lua.new_usertype<VectorF>("VectorF",
+ sol::constructors<VectorF(), VectorF(double, double, double)>(),
+ "x", &VectorF::x,
+ "y", &VectorF::y,
+ "z", &VectorF::z);
+
+ lua.new_usertype<BlockInfo>("BlockInfo",
+ "collides", &BlockInfo::collides,
+ "blockstate", &BlockInfo::blockstate,
+ "variant", &BlockInfo::variant);
+
+ sol::table apiTable = lua["AC"].get_or_create<sol::table>();
+
+ apiTable["RegisterPlugin"] = PluginApi::RegisterPlugin;
+ apiTable["LogWarning"] = PluginApi::LogWarning;
+ apiTable["LogInfo"] = PluginApi::LogInfo;
+ apiTable["LogError"] = PluginApi::LogError;
+ apiTable["GetGameState"] = PluginApi::GetGameState;
+ apiTable["RegisterBlock"] = PluginApi::RegisterBlock;
+}
+
+void PluginSystem::Execute(const std::string &luaCode, bool except) {
+ OPTICK_EVENT();
+ try {
+ lua.safe_script(luaCode);
+ } catch (sol::error &e) {
+ LOG(ERROR) << e.what();
+ if (except)
+ throw;
+ }
+}
+
+void PluginSystem::CallOnChangeState(std::string newState) {
+ OPTICK_EVENT();
+ for (Plugin &plugin : plugins) {
+ if (plugin.onChangeState && plugin.errors < 10)
+ try {
+ plugin.onChangeState(newState);
+ }
+ catch (sol::error &e) {
+ LOG(ERROR) << e.what();
+ plugin.errors++;
+ }
+ }
+}
+
+void PluginSystem::CallOnTick(double deltaTime) {
+ OPTICK_EVENT();
+ for (Plugin& plugin : plugins) {
+ if (plugin.onTick && plugin.errors < 10)
+ try {
+ plugin.onTick(deltaTime);
+ }
+ catch (sol::error &e) {
+ LOG(ERROR) << e.what();
+ plugin.errors++;
+ }
+ }
+}
+
+BlockInfo PluginSystem::RequestBlockInfo(Vector blockPos) {
+ OPTICK_EVENT();
+ BlockInfo ret;
+ for (Plugin& plugin : plugins) {
+ if (plugin.onRequestBlockInfo && plugin.errors < 10)
+ try {
+ ret = plugin.onRequestBlockInfo(blockPos);
+ if (!ret.blockstate.empty())
+ break;
+ }
+ catch (sol::error & e) {
+ LOG(ERROR) << e.what();
+ plugin.errors++;
+ }
+ }
+ return ret;
+}
diff --git a/src/Plugin.hpp b/src/Plugin.hpp
new file mode 100644
index 0000000..a849f5c
--- /dev/null
+++ b/src/Plugin.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <string>
+
+#include "Vector.hpp"
+
+class BlockInfo;
+
+namespace PluginSystem {
+ void Init();
+
+ void Execute(const std::string &luaCode, bool except = false);
+
+ void CallOnChangeState(std::string newState);
+
+ void CallOnTick(double deltaTime);
+
+ BlockInfo RequestBlockInfo(Vector blockPos);
+} \ No newline at end of file
diff --git a/src/Render.cpp b/src/Render.cpp
index cf108e4..128c877 100644
--- a/src/Render.cpp
+++ b/src/Render.cpp
@@ -2,22 +2,23 @@
#include <imgui.h>
#include <easylogging++.h>
+#include <optick.h>
#include "imgui_impl_sdl_gl3.h"
#include "Shader.hpp"
#include "AssetManager.hpp"
#include "Event.hpp"
#include "DebugInfo.hpp"
-#include "GlobalState.hpp"
+#include "Game.hpp"
#include "World.hpp"
#include "GameState.hpp"
#include "RendererWorld.hpp"
#include "Settings.hpp"
#include "Framebuffer.hpp"
+#include "Plugin.hpp"
Render::Render(unsigned int windowWidth, unsigned int windowHeight,
- std::string windowTitle)
- : timer(std::chrono::milliseconds(16)) {
+ std::string windowTitle) {
InitEvents();
Settings::Load();
@@ -47,9 +48,9 @@ Render::Render(unsigned int windowWidth, unsigned int windowHeight,
if (fieldSensetivity != sensetivity)
sensetivity = fieldSensetivity;
isWireframe = fieldWireframe;
- timer.SetDelayLength(std::chrono::duration<double, std::milli>(1.0 / fieldTargetFps * 1000.0));
+ GetTime()->SetDelayLength(std::chrono::duration<double, std::milli>(1.0 / fieldTargetFps * 1000.0));
if (fieldVsync) {
- timer.SetDelayLength(std::chrono::milliseconds(0));
+ GetTime()->SetDelayLength(std::chrono::milliseconds(0));
SDL_GL_SetSwapInterval(1);
}
else
@@ -71,7 +72,9 @@ Render::~Render() {
Settings::WriteDouble("brightness", fieldBrightness);
Settings::WriteDouble("resolutionScale", fieldResolutionScale);
Settings::Save();
-
+
+ PluginSystem::Init();
+
framebuffer.reset();
ImGui_ImplSdlGL3_Shutdown();
SDL_GL_DeleteContext(glContext);
@@ -171,6 +174,7 @@ void Render::UpdateKeyboard() {
}
void Render::RenderFrame() {
+ OPTICK_EVENT();
framebuffer->Clear();
Framebuffer::GetDefault().Clear();
@@ -188,10 +192,12 @@ void Render::RenderFrame() {
RenderGui();
if (world) {
- world->Update(timer.RemainTimeMs());
+ world->Update(GetTime()->RemainTimeMs());
}
- SDL_GL_SwapWindow(window);
+
+ OPTICK_EVENT("VSYNC");
+ SDL_GL_SwapWindow(window);
}
void Render::HandleEvents() {
@@ -225,11 +231,11 @@ void Render::HandleEvents() {
case SDL_WINDOWEVENT_FOCUS_LOST: {
HasFocus = false;
- auto state = GlobalState::GetState();
+ State state = GetState();
if (state == State::Inventory ||
state == State::Playing ||
state == State::Chat) {
- GlobalState::SetState(State::Paused);
+ SetState(State::Paused);
}
break;
}
@@ -241,13 +247,13 @@ void Render::HandleEvents() {
case SDL_KEYDOWN: {
switch (event.key.keysym.scancode) {
case SDL_SCANCODE_ESCAPE: {
- auto state = GlobalState::GetState();
+ auto state = GetState();
if (state == State::Playing) {
- GlobalState::SetState(State::Paused);
+ SetState(State::Paused);
} else if (state == State::Paused ||
state == State::Inventory ||
state == State::Chat) {
- GlobalState::SetState(State::Playing);
+ SetState(State::Playing);
} else if (state == State::MainMenu) {
LOG(INFO) << "Received close event by esc";
PUSH_EVENT("Exit", 0);
@@ -257,11 +263,11 @@ void Render::HandleEvents() {
}
case SDL_SCANCODE_E: {
- auto state = GlobalState::GetState();
+ auto state = GetState();
if (state == State::Playing) {
- GlobalState::SetState(State::Inventory);
+ SetState(State::Inventory);
} else if (state == State::Inventory) {
- GlobalState::SetState(State::Playing);
+ SetState(State::Playing);
}
break;
@@ -270,11 +276,11 @@ void Render::HandleEvents() {
case SDL_SCANCODE_SLASH:
case SDL_SCANCODE_T: {
if (!ImGui::GetIO().WantCaptureKeyboard) {
- auto state = GlobalState::GetState();
+ auto state = GetState();
if (state == State::Playing) {
- GlobalState::SetState(State::Chat);
+ SetState(State::Chat);
} else if (state == State::Chat) {
- GlobalState::SetState(State::Playing);
+ SetState(State::Playing);
}
}
@@ -348,20 +354,18 @@ void Render::SetMouseCapture(bool IsCaptured) {
}
void Render::Update() {
- if (world)
- world->UpdateGameState(GlobalState::GetGameState());
-
+ OPTICK_EVENT();
HandleEvents();
- if (HasFocus && GlobalState::GetState() == State::Playing) UpdateKeyboard();
+ if (HasFocus && GetState() == State::Playing) UpdateKeyboard();
if (isMouseCaptured) HandleMouseCapture();
glCheckError();
RenderFrame();
listener.HandleAllEvents();
- timer.Update();
}
void Render::RenderGui() {
+ OPTICK_EVENT();
ImGui_ImplSdlGL3_NewFrame(window);
if (isMouseCaptured) {
@@ -385,9 +389,9 @@ void Render::RenderGui() {
ImGui::Text("FPS: %.1f (%.3fms)", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate);
float gameTime = DebugInfo::gameThreadTime / 100.0f;
if (world) {
- Entity *playerPtr = world->GameStatePtr()->GetPlayer();
- SelectionStatus selectionStatus = world->GameStatePtr()->GetSelectionStatus();
- const World *worldPtr = &world->GameStatePtr()->GetWorld();
+ Entity *playerPtr = GetGameState()->GetPlayer();
+ SelectionStatus selectionStatus = GetGameState()->GetSelectionStatus();
+ const World *worldPtr = &GetGameState()->GetWorld();
ImGui::Text("TPS: %.1f (%.2fms)", 1000.0f / gameTime, gameTime);
ImGui::Text("Sections loaded: %d", (int) DebugInfo::totalSections);
@@ -428,7 +432,7 @@ void Render::RenderGui() {
ImGui::Text(
"Player health: %.1f/%.1f",
- world->GameStatePtr()->GetPlayerStatus().health, 20.0f);
+ GetGameState()->GetPlayerStatus().health, 20.0f);
ImGui::Text(
"Selected block: %d %d %d : %.1f",
@@ -447,13 +451,13 @@ void Render::RenderGui() {
AssetManager::GetAssetNameByBlockId(BlockId{ worldPtr->GetBlockId(selectionStatus.selectedBlock).id,0 }).c_str());
ImGui::Text("Selected block variant: %s:%s",
- TransformBlockIdToBlockStateName(worldPtr->GetBlockId(selectionStatus.selectedBlock)).first.c_str(),
- TransformBlockIdToBlockStateName(worldPtr->GetBlockId(selectionStatus.selectedBlock)).second.c_str());
+ GetBlockInfo(worldPtr->GetBlockId(selectionStatus.selectedBlock)).blockstate.c_str(),
+ GetBlockInfo(worldPtr->GetBlockId(selectionStatus.selectedBlock)).variant.c_str());
}
ImGui::End();
- switch (GlobalState::GetState()) {
+ switch (GetState()) {
case State::MainMenu: {
ImGui::SetNextWindowPosCenter();
ImGui::Begin("Menu", 0, windowFlags);
@@ -510,7 +514,7 @@ void Render::RenderGui() {
};
ImGui::SetNextWindowPosCenter();
ImGui::Begin("Inventory", 0, windowFlags);
- const Window& inventory = world->GameStatePtr()->GetInventory();
+ const Window& inventory = GetGameState()->GetInventory();
//Hand and drop slots
if (renderSlot(inventory.handSlot, -1)) {
@@ -597,7 +601,7 @@ void Render::RenderGui() {
ImGui::SetNextWindowPosCenter();
ImGui::Begin("Pause Menu", 0, windowFlags);
if (ImGui::Button("Continue")) {
- GlobalState::SetState(State::Playing);
+ SetState(State::Playing);
}
ImGui::Separator();
@@ -626,12 +630,12 @@ void Render::RenderGui() {
if (fieldSensetivity != sensetivity)
sensetivity = fieldSensetivity;
- world->GameStatePtr()->GetPlayer()->isFlying = fieldFlight;
+ GetGameState()->GetPlayer()->isFlying = fieldFlight;
isWireframe = fieldWireframe;
- timer.SetDelayLength(std::chrono::duration<double, std::milli>(1.0 / fieldTargetFps * 1000.0));
+ GetTime()->SetDelayLength(std::chrono::duration<double, std::milli>(1.0 / fieldTargetFps * 1000.0));
if (fieldVsync) {
- timer.SetDelayLength(std::chrono::milliseconds(0));
+ GetTime()->SetDelayLength(std::chrono::milliseconds(0));
SDL_GL_SetSwapInterval(1);
} else
SDL_GL_SetSwapInterval(0);
@@ -672,7 +676,7 @@ void Render::InitEvents() {
listener.RegisterHandler("PlayerConnected", [this](const Event&) {
stateString = "Loading terrain...";
- world = std::make_unique<RendererWorld>(GlobalState::GetGameState());
+ world = std::make_unique<RendererWorld>();
world->MaxRenderingDistance = fieldDistance;
PUSH_EVENT("UpdateSectionsRender", 0);
});
@@ -680,9 +684,9 @@ void Render::InitEvents() {
listener.RegisterHandler("RemoveLoadingScreen", [this](const Event&) {
stateString = "Playing";
renderWorld = true;
- GlobalState::SetState(State::Playing);
+ SetState(State::Playing);
glClearColor(0, 0, 0, 1.0f);
- world->GameStatePtr()->GetPlayer()->isFlying = this->fieldFlight;
+ GetGameState()->GetPlayer()->isFlying = this->fieldFlight;
PUSH_EVENT("SetMinLightLevel", fieldBrightness);
});
@@ -690,7 +694,7 @@ void Render::InitEvents() {
stateString = "Connection failed: " + eventData.get <std::string>();
renderWorld = false;
world.reset();
- GlobalState::SetState(State::MainMenu);
+ SetState(State::MainMenu);
glClearColor(0.8, 0.8, 0.8, 1.0f);
});
@@ -698,13 +702,13 @@ void Render::InitEvents() {
stateString = "Disconnected: " + eventData.get<std::string>();
renderWorld = false;
world.reset();
- GlobalState::SetState(State::MainMenu);
+ SetState(State::MainMenu);
glClearColor(0.8, 0.8, 0.8, 1.0f);
});
listener.RegisterHandler("Connecting", [this](const Event&) {
stateString = "Connecting to the server...";
- GlobalState::SetState(State::Loading);
+ SetState(State::Loading);
});
listener.RegisterHandler("ChatMessageReceived", [this](const Event& eventData) {
@@ -714,16 +718,33 @@ void Render::InitEvents() {
});
listener.RegisterHandler("StateUpdated", [this](const Event& eventData) {
- switch (GlobalState::GetState()) {
+ switch (GetState()) {
case State::Playing:
SetMouseCapture(true);
+ PluginSystem::CallOnChangeState("Playing");
break;
case State::InitialLoading:
+ PluginSystem::CallOnChangeState("InitialLoading");
+ SetMouseCapture(false);
+ break;
case State::MainMenu:
+ PluginSystem::CallOnChangeState("MainMenu");
+ SetMouseCapture(false);
+ break;
case State::Loading:
+ PluginSystem::CallOnChangeState("Loading");
+ SetMouseCapture(false);
+ break;
case State::Paused:
+ PluginSystem::CallOnChangeState("Paused");
+ SetMouseCapture(false);
+ break;
case State::Inventory:
+ PluginSystem::CallOnChangeState("Inventory");
+ SetMouseCapture(false);
+ break;
case State::Chat:
+ PluginSystem::CallOnChangeState("Chat");
SetMouseCapture(false);
break;
}
diff --git a/src/Render.hpp b/src/Render.hpp
index eea5450..8e2e233 100644
--- a/src/Render.hpp
+++ b/src/Render.hpp
@@ -25,7 +25,6 @@ class Render {
std::unique_ptr<RendererWorld> world;
bool renderWorld = false;
RenderState renderState;
- LoopExecutionTimeController timer;
std::map<SDL_Scancode, bool> isKeyPressed;
bool HasFocus=true;
float sensetivity = 0.1f;
diff --git a/src/Renderer.cpp b/src/Renderer.cpp
index 0db23db..947fd6f 100644
--- a/src/Renderer.cpp
+++ b/src/Renderer.cpp
@@ -1,6 +1,9 @@
#include "Renderer.hpp"
+#include <optick.h>
+
void RenderState::SetActiveVao(GLuint Vao) {
+ OPTICK_EVENT();
glBindVertexArray(Vao);
ActiveVao = Vao;
}
diff --git a/src/RendererEntity.cpp b/src/RendererEntity.cpp
index 25403be..fcbf79a 100644
--- a/src/RendererEntity.cpp
+++ b/src/RendererEntity.cpp
@@ -2,12 +2,12 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
+#include <optick.h>
#include "Entity.hpp"
#include "GameState.hpp"
#include "Renderer.hpp"
#include "AssetManager.hpp"
-#include "GlobalState.hpp"
const GLfloat vertices[] = {
-0.5f, 0.5f, 0.5f,
@@ -124,6 +124,7 @@ RendererEntity::~RendererEntity() {
}
void RendererEntity::Render(RenderState& renderState, const World *world) {
+ OPTICK_EVENT();
glm::mat4 model = glm::mat4(1.0);
const Entity &entity = world->GetEntity(entityId);
model = glm::translate(model, entity.pos.glm());
diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp
index 1521c6f..d797771 100644
--- a/src/RendererSection.cpp
+++ b/src/RendererSection.cpp
@@ -1,6 +1,7 @@
#include "RendererSection.hpp"
#include <easylogging++.h>
+#include <optick.h>
#include "Utility.hpp"
#include "Renderer.hpp"
@@ -31,6 +32,7 @@ GLuint RendererSection::VboVertices = magicUniqueConstant;
GLuint RendererSection::VboUvs = magicUniqueConstant;
RendererSection::RendererSection(const RendererSectionData &data) {
+ OPTICK_EVENT();
if (VboVertices == magicUniqueConstant) {
glGenBuffers(1, &VboVertices);
glGenBuffers(1, &VboUvs);
@@ -155,6 +157,7 @@ void swap(RendererSection & lhs, RendererSection & rhs) {
}
void RendererSection::Render(RenderState &renderState) {
+ OPTICK_EVENT();
renderState.SetActiveVao(Vao);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, numOfFaces);
glCheckError();
@@ -169,6 +172,7 @@ size_t RendererSection::GetHash() {
}
void RendererSection::UpdateData(const RendererSectionData & data) {
+ OPTICK_EVENT();
glBindBuffer(GL_ARRAY_BUFFER, Vbo[TEXTURES]);
glBufferData(GL_ARRAY_BUFFER, data.textures.size() * sizeof(glm::vec4), data.textures.data(), GL_DYNAMIC_DRAW);
diff --git a/src/RendererSectionData.cpp b/src/RendererSectionData.cpp
index 3b51809..69ed665 100644
--- a/src/RendererSectionData.cpp
+++ b/src/RendererSectionData.cpp
@@ -3,6 +3,7 @@
#include <array>
#include <glm/gtc/matrix_transform.hpp>
+#include <optick.h>
#include "World.hpp"
@@ -101,8 +102,8 @@ std::array<BlockId, 4096> SetBlockIdData(const SectionsData &sections) {
return blockIdData;
}
-RendererSectionData ParseSection(const SectionsData &sections)
-{
+RendererSectionData ParseSection(const SectionsData &sections) {
+ OPTICK_EVENT();
RendererSectionData data;
std::vector<std::pair<BlockId, BlockFaces*>> idModels;
diff --git a/src/RendererSky.cpp b/src/RendererSky.cpp
index d0e9518..1eab369 100644
--- a/src/RendererSky.cpp
+++ b/src/RendererSky.cpp
@@ -1,5 +1,7 @@
#include "RendererSky.hpp"
+#include <optick.h>
+
#include "Renderer.hpp"
#include "Utility.hpp"
@@ -127,16 +129,15 @@ RendererSky::RendererSky() {
glCheckError();
}
-RendererSky::~RendererSky()
-{
+RendererSky::~RendererSky() {
glDeleteBuffers(1, &VboVert);
glDeleteBuffers(1, &VboUv);
glDeleteVertexArrays(1, &Vao);
//glCheckError();
}
-void RendererSky::Render(RenderState &renderState)
-{
+void RendererSky::Render(RenderState &renderState) {
+ OPTICK_EVENT();
renderState.SetActiveVao(Vao);
glDrawArrays(GL_TRIANGLES, 0, 36);
glCheckError();
diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp
index 7f7c850..ebb049d 100644
--- a/src/RendererWorld.cpp
+++ b/src/RendererWorld.cpp
@@ -2,6 +2,7 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
+#include <optick.h>
#include "DebugInfo.hpp"
#include "Frustum.hpp"
@@ -12,11 +13,14 @@
#include "GameState.hpp"
#include "Section.hpp"
#include "RendererSectionData.hpp"
+#include "Game.hpp"
void RendererWorld::WorkerFunction(size_t workerId) {
+ OPTICK_THREAD("Worker");
EventListener tasksListener;
tasksListener.RegisterHandler("ParseSection", [&](const Event &eventData) {
+ OPTICK_EVENT("EV_ParseSection");
auto data = eventData.get<std::tuple<size_t, size_t, bool>>();
if (std::get<0>(data) != workerId)
return;
@@ -36,6 +40,7 @@ void RendererWorld::WorkerFunction(size_t workerId) {
}
void RendererWorld::ParseQueueUpdate() {
+ OPTICK_EVENT();
while (!parseQueue.empty()) {
size_t id = 0;
for (; id < RendererWorld::parsingBufferSize && parsing[id].parsing; ++id) {}
@@ -52,13 +57,13 @@ void RendererWorld::ParseQueueUpdate() {
vec.y -= 4500;
}
- parsing[id].data.section = gs->GetWorld().GetSection(vec);
- parsing[id].data.north = gs->GetWorld().GetSection(vec + Vector(0, 0, 1));
- parsing[id].data.south = gs->GetWorld().GetSection(vec + Vector(0, 0, -1));
- parsing[id].data.west = gs->GetWorld().GetSection(vec + Vector(1, 0, 0));
- parsing[id].data.east = gs->GetWorld().GetSection(vec + Vector(-1, 0, 0));
- parsing[id].data.bottom = gs->GetWorld().GetSection(vec + Vector(0, -1, 0));
- parsing[id].data.top = gs->GetWorld().GetSection(vec + Vector(0, 1, 0));
+ parsing[id].data.section = GetGameState()->GetWorld().GetSection(vec);
+ parsing[id].data.north = GetGameState()->GetWorld().GetSection(vec + Vector(0, 0, 1));
+ parsing[id].data.south = GetGameState()->GetWorld().GetSection(vec + Vector(0, 0, -1));
+ parsing[id].data.west = GetGameState()->GetWorld().GetSection(vec + Vector(1, 0, 0));
+ parsing[id].data.east = GetGameState()->GetWorld().GetSection(vec + Vector(-1, 0, 0));
+ parsing[id].data.bottom = GetGameState()->GetWorld().GetSection(vec + Vector(0, -1, 0));
+ parsing[id].data.top = GetGameState()->GetWorld().GetSection(vec + Vector(0, 1, 0));
parsing[id].parsing = true;
@@ -69,6 +74,7 @@ void RendererWorld::ParseQueueUpdate() {
}
void RendererWorld::ParseQeueueRemoveUnnecessary() {
+ OPTICK_EVENT();
size_t size = parseQueue.size();
static std::vector<Vector> elements;
elements.clear();
@@ -86,7 +92,7 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() {
if (std::find(elements.begin(), elements.end(), vec) != elements.end())
continue;
- const Section& section = gs->GetWorld().GetSection(vec);
+ const Section& section = GetGameState()->GetWorld().GetSection(vec);
bool skip = false;
@@ -112,10 +118,11 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() {
}
void RendererWorld::UpdateAllSections(VectorF playerPos) {
- Vector playerChunk(std::floor(gs->GetPlayer()->pos.x / 16), 0, std::floor(gs->GetPlayer()->pos.z / 16));
+ OPTICK_EVENT();
+ Vector playerChunk(std::floor(GetGameState()->GetPlayer()->pos.x / 16), 0, std::floor(GetGameState()->GetPlayer()->pos.z / 16));
std::vector<Vector> suitableChunks;
- auto chunks = gs->GetWorld().GetSectionsList();
+ auto chunks = GetGameState()->GetWorld().GetSectionsList();
for (auto& it : chunks) {
double distance = (Vector(it.x, 0, it.z) - playerChunk).GetLength();
if (distance > MaxRenderingDistance)
@@ -134,7 +141,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) {
PUSH_EVENT("DeleteSectionRender", it);
}
- playerChunk.y = std::floor(gs->GetPlayer()->pos.y / 16.0);
+ playerChunk.y = std::floor(GetGameState()->GetPlayer()->pos.y / 16.0);
std::sort(suitableChunks.begin(), suitableChunks.end(), [playerChunk](Vector lhs, Vector rhs) {
double leftLengthToPlayer = (playerChunk - lhs).GetLength();
double rightLengthToPlayer = (playerChunk - rhs).GetLength();
@@ -146,8 +153,8 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) {
}
}
-RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr) {
- gs = ptr;
+RendererWorld::RendererWorld() {
+ OPTICK_EVENT();
MaxRenderingDistance = 2;
numOfWorkers = _max(1, (signed int) std::thread::hardware_concurrency() - 2);
@@ -158,6 +165,7 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr) {
PrepareRender();
listener->RegisterHandler("DeleteSectionRender", [this](const Event& eventData) {
+ OPTICK_EVENT("EV_DeleteSectionRender");
auto vec = eventData.get<Vector>();
auto it = sections.find(vec);
if (it == sections.end())
@@ -166,6 +174,7 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr) {
});
listener->RegisterHandler("SectionParsed",[this](const Event &eventData) {
+ OPTICK_EVENT("EV_SectionParsed");
auto id = eventData.get<size_t>();
parsing[id].parsing = false;
@@ -185,8 +194,9 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr) {
});
listener->RegisterHandler("EntityChanged", [this](const Event& eventData) {
+ OPTICK_EVENT("EV_EntityChanged");
auto data = eventData.get<unsigned int>();
- for (unsigned int entityId : gs->GetWorld().GetEntitiesList()) {
+ for (unsigned int entityId : GetGameState()->GetWorld().GetEntitiesList()) {
if (entityId == data) {
entities.push_back(RendererEntity(entityId));
}
@@ -194,11 +204,12 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr) {
});
listener->RegisterHandler("ChunkChanged", [this](const Event& eventData) {
+ OPTICK_EVENT("EV_ChunkChanged");
auto vec = eventData.get<Vector>();
if (vec == Vector())
return;
- Vector playerChunk(std::floor(gs->GetPlayer()->pos.x / 16), 0, std::floor(gs->GetPlayer()->pos.z / 16));
+ Vector playerChunk(std::floor(GetGameState()->GetPlayer()->pos.x / 16), 0, std::floor(GetGameState()->GetPlayer()->pos.z / 16));
double distanceToChunk = (Vector(vec.x, 0, vec.z) - playerChunk).GetLength();
if (MaxRenderingDistance != 1000 && distanceToChunk > MaxRenderingDistance) {
@@ -211,11 +222,12 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr) {
});
listener->RegisterHandler("ChunkChangedForce", [this](const Event& eventData) {
+ OPTICK_EVENT("EV_ChunkChangedForce");
auto vec = eventData.get<Vector>();
if (vec == Vector())
return;
- Vector playerChunk(std::floor(gs->GetPlayer()->pos.x / 16), 0, std::floor(gs->GetPlayer()->pos.z / 16));
+ Vector playerChunk(std::floor(GetGameState()->GetPlayer()->pos.x / 16), 0, std::floor(GetGameState()->GetPlayer()->pos.z / 16));
double distanceToChunk = (Vector(vec.x, 0, vec.z) - playerChunk).GetLength();
if (MaxRenderingDistance != 1000 && distanceToChunk > MaxRenderingDistance) {
@@ -230,7 +242,7 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr) {
});
listener->RegisterHandler("UpdateSectionsRender", [this](const Event&) {
- UpdateAllSections(gs->GetPlayer()->pos);
+ UpdateAllSections(GetGameState()->GetPlayer()->pos);
});
listener->RegisterHandler("PlayerPosChanged", [this](const Event& eventData) {
@@ -271,12 +283,13 @@ RendererWorld::~RendererWorld() {
}
void RendererWorld::Render(RenderState & renderState) {
+ OPTICK_EVENT();
//Common
glm::mat4 projection = glm::perspective(
glm::radians(70.0f), (float) renderState.WindowWidth / (float) renderState.WindowHeight,
0.1f, 10000000.0f
);
- glm::mat4 view = gs->GetViewMatrix();
+ glm::mat4 view = GetGameState()->GetViewMatrix();
glm::mat4 projView = projection * view;
//Render Entities
@@ -286,14 +299,14 @@ void RendererWorld::Render(RenderState & renderState) {
entityShader->SetUniform("projection", projection);
entityShader->SetUniform("view", view);
glCheckError();
-
+
renderState.SetActiveVao(RendererEntity::GetVao());
for (auto& it : entities) {
- it.Render(renderState, &gs->GetWorld());
+ it.Render(renderState, &GetGameState()->GetWorld());
}
//Render selected block
- Vector selectedBlock = gs->GetSelectionStatus().selectedBlock;
+ Vector selectedBlock = GetGameState()->GetSelectionStatus().selectedBlock;
if (selectedBlock != Vector()) {
glLineWidth(2.0f);
{
@@ -311,7 +324,7 @@ void RendererWorld::Render(RenderState & renderState) {
//Render raycast hit
const bool renderHit = false;
if (renderHit) {
- VectorF hit = gs->GetSelectionStatus().raycastHit;
+ VectorF hit = GetGameState()->GetSelectionStatus().raycastHit;
glLineWidth(2.0f);
{
glm::mat4 model;
@@ -331,16 +344,16 @@ void RendererWorld::Render(RenderState & renderState) {
glCheckError();
//Render sky
- renderState.TimeOfDay = gs->GetTimeStatus().timeOfDay;
+ renderState.TimeOfDay = GetGameState()->GetTimeStatus().timeOfDay;
Shader *skyShader = AssetManager::GetAsset<AssetShader>("/altcraft/shaders/sky")->shader.get();
skyShader->Activate();
skyShader->SetUniform("projection", projection);
skyShader->SetUniform("view", view);
glm::mat4 model = glm::mat4(1.0);
- model = glm::translate(model, gs->GetPlayer()->pos.glm());
+ model = glm::translate(model, GetGameState()->GetPlayer()->pos.glm());
const float scale = 1000000.0f;
model = glm::scale(model, glm::vec3(scale, scale, scale));
- float shift = gs->GetTimeStatus().interpolatedTimeOfDay / 24000.0f;
+ float shift = GetGameState()->GetTimeStatus().interpolatedTimeOfDay / 24000.0f;
if (shift < 0)
shift *= -1.0f;
model = glm::rotate(model, glm::radians(90.0f), glm::vec3(0, 1.0f, 0.0f));
@@ -357,7 +370,7 @@ void RendererWorld::Render(RenderState & renderState) {
const float moonriseLength = moonriseMax - moonriseMin;
float mixLevel = 0;
- float dayTime = gs->GetTimeStatus().interpolatedTimeOfDay;
+ float dayTime = GetGameState()->GetTimeStatus().interpolatedTimeOfDay;
if (dayTime < 0)
dayTime *= -1;
while (dayTime > 24000)
@@ -434,6 +447,7 @@ void RendererWorld::PrepareRender() {
}
void RendererWorld::Update(double timeToUpdate) {
+ OPTICK_EVENT();
static auto timeSincePreviousUpdate = std::chrono::steady_clock::now();
if (parseQueueNeedRemoveUnnecessary)
@@ -451,7 +465,3 @@ void RendererWorld::Update(double timeToUpdate) {
DebugInfo::readyRenderer = parseQueue.size();
DebugInfo::renderSections = sections.size();
}
-
-GameState* RendererWorld::GameStatePtr() {
- return gs.get();
-}
diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp
index 913e510..d031179 100644
--- a/src/RendererWorld.hpp
+++ b/src/RendererWorld.hpp
@@ -27,7 +27,6 @@ class RendererWorld {
};
//General
- std::shared_ptr<GameState> gs;
std::unique_ptr<EventListener> listener;
size_t numOfWorkers;
size_t currentWorker = 0;
@@ -51,7 +50,7 @@ class RendererWorld {
Texture *skyTexture;
RendererSky rendererSky;
public:
- RendererWorld(std::shared_ptr<GameState> ptr);
+ RendererWorld();
~RendererWorld();
void Render(RenderState& renderState);
@@ -61,11 +60,5 @@ public:
void Update(double timeToUpdate);
- GameState *GameStatePtr();
-
int culledSections = 0;
-
- inline void UpdateGameState(std::shared_ptr<GameState> newPtr) {
- gs = newPtr;
- }
}; \ No newline at end of file
diff --git a/src/Utility.cpp b/src/Utility.cpp
index 848ee02..09696fd 100644
--- a/src/Utility.cpp
+++ b/src/Utility.cpp
@@ -2,9 +2,11 @@
#include <thread>
+#include <optick.h>
#include <easylogging++.h>
GLenum glCheckError_(const char *file, int line) {
+ OPTICK_EVENT();
GLenum errorCode;
while ((errorCode = glGetError()) != GL_NO_ERROR) {
std::string error;
diff --git a/src/World.cpp b/src/World.cpp
index da0a33b..00a1a19 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2,6 +2,7 @@
#include <bitset>
#include <glm/glm.hpp>
+#include <optick.h>
#include "Event.hpp"
#include "DebugInfo.hpp"
@@ -97,7 +98,7 @@ bool World::isPlayerCollides(double X, double Y, double Z) const {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
BlockId block = section.GetBlockId(Vector(x, y, z));
- if (block.id == 0 || block.id == 31 || block.id == 37 || block.id == 38 || block.id == 175)
+ if (!GetBlockInfo(block).collides)
continue;
AABB blockColl{ (x + it.x * 16.0),
(y + it.y * 16.0),
@@ -131,6 +132,7 @@ const Section &World::GetSection(Vector sectionPos) const {
// TODO: skip liquid blocks
RaycastResult World::Raycast(glm::vec3 position, glm::vec3 direction) const {
+ OPTICK_EVENT();
const float maxLen = 5.0;
const float step = 0.01;
glm::vec3 pos = glm::vec3(0.0);
@@ -150,6 +152,7 @@ RaycastResult World::Raycast(glm::vec3 position, glm::vec3 direction) const {
}
void World::UpdatePhysics(float delta) {
+ OPTICK_EVENT();
struct CollisionResult {
bool isCollide;
//Vector block;
@@ -158,6 +161,7 @@ void World::UpdatePhysics(float delta) {
};
auto testCollision = [this](double width, double height, VectorF pos)->CollisionResult {
+ OPTICK_EVENT("testCollision");
int blockXBegin = pos.x - width - 1.0;
int blockXEnd = pos.x + width + 0.5;
int blockYBegin = pos.y - 0.5;
@@ -177,9 +181,10 @@ void World::UpdatePhysics(float delta) {
for (int y = blockYBegin; y <= blockYEnd; y++) {
for (int z = blockZBegin; z <= blockZEnd; z++) {
for (int x = blockXBegin; x <= blockXEnd; x++) {
+ OPTICK_EVENT("testCollision");
BlockId block = this->GetBlockId(Vector(x, y, z));
- if (block.id == 0 || block.id == 31 || block.id == 37 || block.id == 38 || block.id == 175 || block.id == 78)
- continue;
+ if (block.id == 0 || !GetBlockInfo(block).collides)
+ continue;
AABB blockColl{ x,y,z,1.0,1.0,1.0 };
if (TestCollision(entityCollBox, blockColl)) {
return { true };
@@ -191,6 +196,7 @@ void World::UpdatePhysics(float delta) {
};
for (auto& it : entities) {
+ OPTICK_EVENT("Foreach entities");
if (it.isFlying) {
VectorF newPos = it.pos + VectorF(it.vel.x, it.vel.y, it.vel.z) * delta;
auto coll = testCollision(it.width, it.height, newPos);
diff --git a/src/main.cpp b/src/main.cpp
index cb2daa8..2ed2b85 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,6 +1,6 @@
#include "Event.hpp"
#include "Utility.hpp"
-#include "GlobalState.hpp"
+#include "Game.hpp"
#include <set>
@@ -48,7 +48,7 @@ int main(int argc, char** argv) {
return -1;
}
- GlobalState::Exec();
+ RunGame();
return 0;
} \ No newline at end of file