Generify RIE parsing, implement setBiome

master
Nicole Collings 2020-02-14 14:39:39 -08:00
parent ee94e691ae
commit 7c87b002d2
4 changed files with 139 additions and 110 deletions

View File

@ -274,6 +274,6 @@ set(ZEPHA_SRC
util/net/Serializer.h
util/net/Deserializer.h
lua/api/type/ServerLocalLuaEntity.cpp
lua/api/type/ServerLocalLuaEntity.h lua/api/modules/register_item.h lua/api/modules/register_biome.h lua/api/modules/delay.h lua/api/modules/register_block.h lua/api/modules/register_blockmodel.h lua/api/modules/register_entity.h game/scene/world/World.cpp game/scene/world/World.h lua/api/modules/set_block.h lua/api/modules/get_block.h lua/api/modules/remove_block.h lua/register/RegisterBiomes.h lua/register/RegisterBlocks.h lua/register/RegisterItems.h lua/register/RegisterKeybinds.h lua/api/type/LocalLuaAnimationManager.cpp lua/api/type/LocalLuaAnimationManager.h lua/api/type/cLocalLuaAnimationManager.h game/scene/world/Schematic.cpp game/scene/world/Schematic.h lua/VenusParser.cpp lua/VenusParser.h lua/ErrorFormatter.cpp lua/ErrorFormatter.h)
lua/api/type/ServerLocalLuaEntity.h lua/api/modules/register_item.h lua/api/modules/register_biome.h lua/api/modules/delay.h lua/api/modules/register_block.h lua/api/modules/register_blockmodel.h lua/api/modules/register_entity.h game/scene/world/World.cpp game/scene/world/World.h lua/api/modules/set_block.h lua/api/modules/get_block.h lua/api/modules/remove_block.h lua/register/RegisterBiomes.h lua/register/RegisterBlocks.h lua/register/RegisterItems.h lua/register/RegisterKeybinds.h lua/api/type/LocalLuaAnimationManager.cpp lua/api/type/LocalLuaAnimationManager.h lua/api/type/cLocalLuaAnimationManager.h game/scene/world/Schematic.cpp game/scene/world/Schematic.h lua/VenusParser.cpp lua/VenusParser.h lua/ErrorFormatter.cpp lua/ErrorFormatter.h util/RIE.h)
add_library (Zepha_Core ${ZEPHA_SRC})

116
src/util/RIE.h Normal file
View File

@ -0,0 +1,116 @@
//
// Created by aurailus on 2020-02-14.
//
#pragma once
#include <vector>
#include <type_traits>
struct RIE {
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> static T read(
const unsigned int ind, const std::vector<T>& data, const unsigned int dataLen) {
if (ind >= dataLen) return 0;
for (unsigned int i = 0; i < data.size(); i += 2) {
if (data[i] > ind) return data[i - 1];
}
return data[data.size() - 1];
}
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> static bool write(
const unsigned int ind, const T val, std::vector<T>& data, const unsigned int dataLen) {
if (ind >= dataLen) return false;
if (read(ind, data, dataLen) == val) return false;
if (ind == 0) {
if (data[2] == ind + 1) {
data[1] = val;
return true;
}
else {
data.insert(data.begin() + 2, 2, ind);
data[2] = 1;
data[3] = data[1];
data[1] = val;
return true;
}
}
for (unsigned int i = 0; i < data.size(); i += 2) {
if (data[i] == ind) {
// We found an index equating to the block we are going to be setting.
if (data[i - 1] == val) {
// The last block strip is the same block ID as what we are setting,
// So we should extend that strip.
if (data.size() > i + 2 && data[i + 2] == ind + 1) {
// The next block is one later, meaning we can simply remove this found block
// To cause the next strip to cascade over its position.
data.erase(data.begin() + i, data.begin() + i + 2);
return true;
}
else {
// The next strip is multiple blocks over, so just add one to our found block index.
data[i] += 1;
return true;
}
}
else {
// The last strip is not the same block.
if (data.size() > i + 2 && data[i + 2] == ind + 1) {
// There is only one of our block, so we can just update its id.
data[i + 1] = val;
return true;
}
else {
// The next strip is multiple blocks over, so we need to copy the previous block to the right
// and then set our block into its place
data.insert(data.begin() + i, 2, ind);
data[i + 1] = val;
data[i + 2] = ind + 1;
return true;
}
}
}
else if (data[i] > ind) {
// We found a strip with an index *larger* than our ind.
// We can assume the last strip is not our block, because the getBlock() catch would have caught that.
if (data[i] == ind + 1) {
if (data[i + 1] == val) {
// The next block over is the same, so we can just decrement our index by one.
data[i]--;
return true;
}
else {
// There is only one of our block to be placed, directly before our current strip
data.insert(data.begin() + i, 2, ind);
data[i + 1] = val;
return true;
}
}
else {
// The next strip is multiple blocks over, so we need to insert both our block
// *and* the previous strip's block after
data.insert(data.begin() + i, 4, ind);
data[i + 1] = val;
data[i + 2] = ind + 1;
data[i + 3] = data[i - 1];
return true;
}
}
}
// Escaped the for loop, meaning there's no index greater than ours.
// We will insert our index at the end of the array, and insert the previous block after
// if we're not at the end of the chunk.
data.push_back(ind);
data.push_back(val);
if (ind >= dataLen - 1) return true; // Don't add the reset if at the end of the chunk.
data.push_back(ind + 1);
data.push_back(data[data.size() - 4]);
return true;
}
};

View File

@ -20,112 +20,20 @@ BlockChunk::BlockChunk(const std::vector<unsigned int>& blocks, const std::vecto
}
bool BlockChunk::setBlock(unsigned int ind, unsigned int blk) {
// Exit early if no manipulation is needed.
// Exit if someone is doing something stupid
if (ind >= 4096) return false;
const unsigned int existing = getBlock(ind);
if (existing == blk) return false;
// Deal with shouldHaveMesh
if (blk == DefinitionAtlas::AIR) {
if ((nonAirBlocks = fmax(nonAirBlocks - 1, 0)) == 0) {
empty = true;
shouldHaveMesh = false;
}
// Mesh emptiness manipulation
if (blk == DefinitionAtlas::AIR && (nonAirBlocks = fmax(nonAirBlocks - 1, 0)) == 0) {
empty = true;
shouldHaveMesh = false;
}
else if (existing == DefinitionAtlas::AIR) {
else if (blk != DefinitionAtlas::AIR && getBlock(ind) == DefinitionAtlas::AIR) {
if (nonAirBlocks == 0) shouldHaveMesh = true;
empty = false;
nonAirBlocks++;
}
if (ind == 0) {
if (blocks[2] == ind + 1) {
blocks[1] = blk;
return true;
}
else {
blocks.insert(blocks.begin() + 2, 2, ind);
blocks[2] = 1;
blocks[3] = blocks[1];
blocks[1] = blk;
return true;
}
}
for (unsigned int i = 0; i < blocks.size(); i += 2) {
if (blocks[i] == ind) {
// We found an index equating to the block we are going to be setting.
if (blocks[i - 1] == blk) {
// The last block strip is the same block ID as what we are setting,
// So we should extend that strip.
if (blocks.size() > i + 2 && blocks[i + 2] == ind + 1) {
// The next block is one later, meaning we can simply remove this found block
// To cause the next strip to cascade over its position.
blocks.erase(blocks.begin() + i, blocks.begin() + i + 2);
return true;
}
else {
// The next strip is multiple blocks over, so just add one to our found block index.
blocks[i] += 1;
return true;
}
}
else {
// The last strip is not the same block.
if (blocks.size() > i + 2 && blocks[i + 2] == ind + 1) {
// There is only one of our block, so we can just update its id.
blocks[i + 1] = blk;
return true;
}
else {
// The next strip is multiple blocks over, so we need to copy the previous block to the right
// and then set our block into its place
blocks.insert(blocks.begin() + i, 2, ind);
blocks[i + 1] = blk;
blocks[i + 2] = ind + 1;
return true;
}
}
}
else if (blocks[i] > ind) {
// We found a strip with an index *larger* than our ind.
// We can assume the last strip is not our block, because the getBlock() catch would have caught that.
if (blocks[i] == ind + 1) {
if (blocks[i + 1] == blk) {
// The next block over is the same, so we can just decrement our index by one.
blocks[i] --;
return true;
}
else {
// There is only one of our block to be placed, directly before our current strip
blocks.insert(blocks.begin() + i, 2, ind);
blocks[i + 1] = blk;
return true;
}
}
else {
// The next strip is multiple blocks over, so we need to insert both our block
// *and* the previous strip's block after
blocks.insert(blocks.begin() + i, 4, ind);
blocks[i + 1] = blk;
blocks[i + 2] = ind + 1;
blocks[i + 3] = blocks[i - 1];
return true;
}
}
}
// Escaped the for loop, meaning there's no index greater than ours.
// We will insert our index at the end of the array, and insert the previous block after
// if we're not at the end of the chunk.
blocks.push_back(ind);
blocks.push_back(blk);
if (ind >= 4095) return true; // Don't add the reset if at the end of the chunk.
blocks.push_back(ind + 1);
blocks.push_back(blocks[blocks.size() - 4]);
return true;
// Return the value
RIE::write(ind, blk, blocks, 4096);
}
const std::vector<unsigned int> &BlockChunk::cGetBlocks() const {

View File

@ -9,6 +9,7 @@
#include <glm/vec3.hpp>
#include "../../util/Log.h"
#include "../../util/Vec.h"
#include "../../util/RIE.h"
#include "../../util/Util.h"
#include "../../util/net/Packet.h"
#include "../../def/gen/BiomeAtlas.h"
@ -30,7 +31,8 @@ public:
inline unsigned int getBlock(unsigned int ind) const;
inline unsigned int getBlock(const glm::ivec3& pos) const;
// bool setBiome(const glm::ivec3& pos, unsigned int ind);
inline bool setBiome(unsigned int ind, unsigned short bio);
inline bool setBiome(const glm::ivec3& pos, unsigned short bio);
inline unsigned short getBiome(unsigned int ind) const;
inline unsigned short getBiome(const glm::ivec3& pos) const;
@ -73,10 +75,7 @@ inline bool BlockChunk::setBlock(const glm::ivec3& pos, unsigned int blk) {
inline unsigned int BlockChunk::getBlock(unsigned int ind) const {
if (ind >= 4096) return DefinitionAtlas::INVALID;
for (unsigned int i = 0; i < blocks.size(); i += 2) {
if (blocks[i] > ind) return blocks[i - 1];
}
return blocks[blocks.size() - 1];
return RIE::read<unsigned int>(ind, blocks, 4096);
}
inline unsigned int BlockChunk::getBlock(const glm::ivec3& pos) const {
@ -84,12 +83,18 @@ inline unsigned int BlockChunk::getBlock(const glm::ivec3& pos) const {
return getBlock(Space::Block::index(pos));
}
inline bool BlockChunk::setBiome(unsigned int ind, unsigned short bio) {
RIE::write(ind, bio, biomes, 4096);
}
inline bool BlockChunk::setBiome(const glm::ivec3& pos, unsigned short bio) {
if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return false;
return setBiome(Space::Block::index(pos), bio);
}
inline unsigned short BlockChunk::getBiome(unsigned int ind) const {
if (ind >= 4096) return BiomeAtlas::INVALID;
for (unsigned int i = 0; i < biomes.size(); i += 2) {
if (biomes[i] > ind) return biomes[i - 1];
}
return biomes[biomes.size() - 1];
return RIE::read<unsigned short>(ind, biomes, 4096);
}
inline unsigned short BlockChunk::getBiome(const glm::ivec3& pos) const {