Lua trees, ores, desert, review changes, merge
This commit is contained in:
parent
53bb1c14c0
commit
474cdd16c4
@ -1,3 +1,4 @@
|
||||
The following people have contributed code to this project and hold the copyright on some portions (see the commit history for details):
|
||||
* Pedro Gimeno Fortea (pgimeno) \<pgimeno@users.noreply.notabug.org\>
|
||||
* Nikola Schordinger (DeatHunter) \<Discord: DH#9367\>
|
||||
* Kurt Spencer (K.jpg) \<https://github.com/KdotJPG\>
|
@ -49,6 +49,41 @@ Item &Registry::registerSerializedItem(sf::Packet &packet) {
|
||||
return m_items.back();
|
||||
}
|
||||
|
||||
|
||||
Tree &Registry::registerTree(const std::string &stringID, const std::string &label) {
|
||||
size_t id = m_trees.size();
|
||||
m_treesID.emplace(stringID, id);
|
||||
m_trees.emplace_back(id, stringID, label);
|
||||
return m_trees.back();
|
||||
}
|
||||
|
||||
Tree &Registry::registerSerializedTree(sf::Packet &packet) {
|
||||
m_trees.emplace_back();
|
||||
m_trees.back().deserialize(packet);
|
||||
|
||||
size_t id = m_trees.size() - 1;
|
||||
m_treesID.emplace(m_trees.back().stringID(), id);
|
||||
|
||||
return m_trees.back();
|
||||
}
|
||||
|
||||
Biome &Registry::registerBiome(const std::string &stringID, const std::string &label) {
|
||||
size_t id = m_biomes.size();
|
||||
m_biomesID.emplace(stringID, id);
|
||||
m_biomes.emplace_back(id, stringID, label);
|
||||
return m_biomes.back();
|
||||
}
|
||||
|
||||
Biome &Registry::registerSerializedBiome(sf::Packet &packet) {
|
||||
m_biomes.emplace_back();
|
||||
m_biomes.back().deserialize(packet);
|
||||
|
||||
size_t id = m_biomes.size() - 1;
|
||||
m_biomesID.emplace(m_biomes.back().stringID(), id);
|
||||
|
||||
return m_biomes.back();
|
||||
}
|
||||
|
||||
const Block &Registry::getBlockFromStringID(const std::string &stringID) {
|
||||
if (stringID.empty()) return getBlock(0);
|
||||
auto it = m_blocksID.find(stringID);
|
||||
@ -65,6 +100,24 @@ const Item &Registry::getItemFromStringID(const std::string &stringID) {
|
||||
return getItem(it->second);
|
||||
}
|
||||
|
||||
const Tree &Registry::getTreeFromStringID(const std::string &stringID) {
|
||||
if (stringID.empty())
|
||||
throw EXCEPTION("Trying to get tree from empty string ID.");
|
||||
auto it = m_treesID.find(stringID);
|
||||
if (it == m_treesID.end())
|
||||
throw EXCEPTION("Unknown tree:", stringID);
|
||||
return getTree(it->second);
|
||||
}
|
||||
|
||||
const Biome &Registry::getBiomeFromStringID(const std::string &stringID) {
|
||||
if (stringID.empty())
|
||||
throw EXCEPTION("Trying to get tree from empty string ID.");
|
||||
auto it = m_biomesID.find(stringID);
|
||||
if (it == m_biomesID.end())
|
||||
throw EXCEPTION("Unknown tree:", stringID);
|
||||
return getBiome(it->second);
|
||||
}
|
||||
|
||||
const Recipe *Registry::getRecipe(const Inventory &inventory) const {
|
||||
for (auto &recipe : m_recipes) {
|
||||
if (recipe->isMatching(inventory))
|
||||
@ -87,8 +140,12 @@ void Registry::serialize(sf::Packet &packet) const {
|
||||
<< *it;
|
||||
}
|
||||
|
||||
for (auto &it : m_trees) {
|
||||
packet << u8(DataType::Tree) << it;
|
||||
}
|
||||
|
||||
for (auto &it : m_biomes) {
|
||||
packet << u8(DataType::Biome) << *it;
|
||||
packet << u8(DataType::Biome) << it;
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +166,10 @@ void Registry::deserialize(sf::Packet &packet) {
|
||||
registerRecipe<SmeltingRecipe>()->deserialize(packet);
|
||||
}
|
||||
else if (type == u8(DataType::Biome)) {
|
||||
registerSerializedBiome<Biome>(packet);
|
||||
registerSerializedBiome(packet);
|
||||
}
|
||||
else if (type == u8(DataType::Tree)) {
|
||||
registerSerializedTree(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,11 +31,12 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "Biome.hpp"
|
||||
#include "Block.hpp"
|
||||
#include "Item.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "Recipe.hpp"
|
||||
#include "Biome.hpp"
|
||||
#include "Tree.hpp"
|
||||
|
||||
class Registry : public ISerializable {
|
||||
public:
|
||||
@ -67,41 +68,31 @@ class Registry : public ISerializable {
|
||||
return m_recipes.back().get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto registerBiome(const std::string &stringID, const std::string &label) -> typename std::enable_if<std::is_base_of<Biome, T>::value, T&>::type {
|
||||
size_t id = m_biomes.size();
|
||||
m_biomesID.emplace(stringID, id);
|
||||
m_biomes.emplace_back(std::make_unique<T>(id, stringID, label));
|
||||
return *static_cast<T*>(m_biomes.back().get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto registerSerializedBiome(sf::Packet &packet) -> typename std::enable_if<std::is_base_of<Biome, T>::value, T&>::type {
|
||||
m_biomes.emplace_back(std::make_unique<T>());
|
||||
m_biomes.back()->deserialize(packet);
|
||||
|
||||
size_t id = m_biomes.size() - 1;
|
||||
m_biomesID.emplace(m_biomes.back()->stringID(), id);
|
||||
|
||||
return *static_cast<T*>(m_biomes.back().get());
|
||||
}
|
||||
Tree ®isterTree(const std::string &stringID, const std::string &label);
|
||||
Tree ®isterSerializedTree(sf::Packet &packet);
|
||||
Biome ®isterBiome(const std::string &stringID, const std::string &label);
|
||||
Biome ®isterSerializedBiome(sf::Packet &packet);
|
||||
|
||||
const Block &getBlock(std::size_t id) const { return *m_blocks.at(id).get(); }
|
||||
const Item &getItem(std::size_t id) const { return m_items.at(id); }
|
||||
|
||||
const Block &getBlockFromStringID(const std::string &stringID);
|
||||
const Item &getItemFromStringID(const std::string &stringID);
|
||||
const Tree &getTreeFromStringID(const std::string &stringID);
|
||||
const Biome &getBiomeFromStringID(const std::string &stringID);
|
||||
|
||||
const Recipe *getRecipe(const Inventory &inventory) const;
|
||||
|
||||
const Biome &getBiome(std::size_t id) const { return *m_biomes.at(id).get(); }
|
||||
const Tree &getTree(u32 id) const { return m_trees.at(id); }
|
||||
const Biome &getBiome(u32 id) const { return m_biomes.at(id); }
|
||||
|
||||
void serialize(sf::Packet &packet) const override;
|
||||
void deserialize(sf::Packet &packet) override;
|
||||
|
||||
const std::vector<std::unique_ptr<Block>> &blocks() const { return m_blocks; }
|
||||
const std::vector<Item> &items() const { return m_items; }
|
||||
const std::vector<std::unique_ptr<Biome>> &biomes() const { return m_biomes; }
|
||||
const std::vector<Tree> &trees() const { return m_trees; }
|
||||
const std::vector<Biome> &biomes() const { return m_biomes; }
|
||||
|
||||
static Registry &getInstance() { return *s_instance; }
|
||||
static void setInstance(Registry &instance) { s_instance = &instance; }
|
||||
@ -112,10 +103,12 @@ class Registry : public ISerializable {
|
||||
std::vector<std::unique_ptr<Block>> m_blocks;
|
||||
std::vector<Item> m_items;
|
||||
std::vector<std::unique_ptr<Recipe>> m_recipes;
|
||||
std::vector<std::unique_ptr<Biome>> m_biomes;
|
||||
std::vector<Tree> m_trees;
|
||||
std::vector<Biome> m_biomes;
|
||||
|
||||
std::unordered_map<std::string, u32> m_blocksID;
|
||||
std::unordered_map<std::string, u32> m_itemsID;
|
||||
std::unordered_map<std::string, u32> m_treesID;
|
||||
std::unordered_map<std::string, u32> m_biomesID;
|
||||
|
||||
enum class DataType {
|
||||
@ -123,6 +116,7 @@ class Registry : public ISerializable {
|
||||
Item,
|
||||
CraftingRecipe,
|
||||
SmeltingRecipe,
|
||||
Tree,
|
||||
Biome
|
||||
};
|
||||
};
|
||||
|
@ -24,20 +24,21 @@
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "Biome.hpp"
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
|
||||
#include "Biome.hpp"
|
||||
#include "NetworkUtils.hpp"
|
||||
|
||||
Biome::Biome(u32 id, const std::string &stringID, const std::string &label) {
|
||||
Biome::Biome(u16 id, const std::string &stringID, const std::string &label) {
|
||||
m_id = id;
|
||||
std::string m_stringID;
|
||||
std::string m_label;
|
||||
m_stringID = stringID;
|
||||
m_label = label;
|
||||
}
|
||||
|
||||
void Biome::serialize(sf::Packet &packet) const {
|
||||
packet << u32(m_id) << m_stringID << m_label << m_params << m_topBlock << m_groundBlock << m_beachBlock << m_liquidBlock;
|
||||
packet << m_id << m_stringID << m_label << m_params << m_topBlockID << m_groundBlockID << m_deepBlockID << m_beachBlockID << m_liquidBlockID << m_flora << m_ores << m_trees;
|
||||
}
|
||||
|
||||
void Biome::deserialize(sf::Packet &packet) {
|
||||
packet >> m_id >> m_stringID >> m_label >> m_params >> m_topBlock >> m_groundBlock >> m_beachBlock >> m_liquidBlock;
|
||||
}
|
||||
packet >> m_id >> m_stringID >> m_label >> m_params >> m_topBlockID >> m_groundBlockID >> m_deepBlockID >> m_beachBlockID >> m_liquidBlockID >> m_flora >> m_ores >> m_trees;
|
||||
}
|
||||
|
@ -29,46 +29,77 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gk/core/IntTypes.hpp>
|
||||
|
||||
#include "ISerializable.hpp"
|
||||
#include "PlacementEntry.hpp"
|
||||
|
||||
class Biome : public ISerializable {
|
||||
public:
|
||||
Biome() = default;
|
||||
Biome(u32 id, const std::string &stringID, const std::string &label);
|
||||
~Biome() = default;
|
||||
public:
|
||||
Biome() = default;
|
||||
Biome(u16 id, const std::string &stringID, const std::string &label);
|
||||
|
||||
void serialize(sf::Packet &packet) const override;
|
||||
void deserialize(sf::Packet &packet) override;
|
||||
void serialize(sf::Packet &packet) const override;
|
||||
void deserialize(sf::Packet &packet) override;
|
||||
|
||||
const std::string &stringID() const { return m_stringID; }
|
||||
const std::string &label() const { return m_label; }
|
||||
void setLabel(const std::string &label) { m_label = label; }
|
||||
u16 id() const { return m_id; }
|
||||
const std::string &stringID() const { return m_stringID; }
|
||||
const std::string &label() const { return m_label; }
|
||||
void setLabel(const std::string &label) { m_label = label; }
|
||||
|
||||
std::vector<double> getParams() { return m_params; }
|
||||
const u16 getTopBlock() const { return m_topBlock; }
|
||||
const u16 getGroundBlock() const { return m_groundBlock; }
|
||||
const u16 getBeachBlock() const { return m_beachBlock; }
|
||||
const u16 getLiquidBlock() const { return m_liquidBlock; }
|
||||
const std::vector<double> &getParams() const { return m_params; }
|
||||
|
||||
void setParams(std::vector<double> value) { m_params = value; }
|
||||
void setTopBlock(u16 value) { m_topBlock = value; }
|
||||
void setGroundBlock(u16 value) { m_groundBlock = value; }
|
||||
void setBeachBlock(u16 value) { m_beachBlock = value; }
|
||||
void setLiquidBlock(u16 value) { m_liquidBlock = value; }
|
||||
u16 getTopBlockID() const { return m_topBlockID; }
|
||||
u16 getGroundBlockID() const { return m_groundBlockID; }
|
||||
u16 getDeepBlockID() const { return m_deepBlockID; }
|
||||
u16 getBeachBlockID() const { return m_beachBlockID; }
|
||||
u16 getLiquidBlockID() const { return m_liquidBlockID; }
|
||||
const std::vector<PlacementEntry::Flora> &getFlora() const { return m_flora; }
|
||||
const std::vector<PlacementEntry::Ore> &getOres() const { return m_ores; }
|
||||
const std::vector<PlacementEntry::Tree> &getTrees() const { return m_trees; }
|
||||
|
||||
private:
|
||||
u32 m_id;
|
||||
std::string m_stringID;
|
||||
std::string m_label;
|
||||
void setParams(std::vector<double> &value) { m_params = value; }
|
||||
|
||||
// TODO something to distinguish the worldtype of biome
|
||||
std::vector<double> m_params;
|
||||
u16 m_topBlock;
|
||||
u16 m_groundBlock;
|
||||
u16 m_beachBlock;
|
||||
u16 m_liquidBlock;
|
||||
void setTopBlockID(u16 value) { m_topBlockID = value; }
|
||||
void setGroundBlockID(u16 value) { m_groundBlockID = value; }
|
||||
void setDeepBlockID(u16 value) { m_deepBlockID = value; }
|
||||
void setBeachBlockID(u16 value) { m_beachBlockID = value; }
|
||||
void setLiquidBlockID(u16 value) { m_liquidBlockID = value; }
|
||||
void setFlora(std::vector<PlacementEntry::Flora> &value) { m_flora = value; }
|
||||
void setOres(std::vector<PlacementEntry::Ore> &value) { m_ores = value; }
|
||||
void setTrees(std::vector<PlacementEntry::Tree> &value) { m_trees = value; }
|
||||
|
||||
PlacementEntry::Flora &addFlora() {
|
||||
m_flora.emplace_back();
|
||||
return m_flora.back();
|
||||
}
|
||||
|
||||
PlacementEntry::Ore &addOre() {
|
||||
m_ores.emplace_back();
|
||||
return m_ores.back();
|
||||
}
|
||||
|
||||
PlacementEntry::Tree &addTree() {
|
||||
m_trees.emplace_back();
|
||||
return m_trees.back();
|
||||
}
|
||||
|
||||
private:
|
||||
u16 m_id;
|
||||
std::string m_stringID;
|
||||
std::string m_label;
|
||||
|
||||
// TODO something to distinguish the worldtype of biome
|
||||
std::vector<double> m_params;
|
||||
u16 m_topBlockID;
|
||||
u16 m_groundBlockID;
|
||||
u16 m_deepBlockID;
|
||||
u16 m_beachBlockID;
|
||||
u16 m_liquidBlockID;
|
||||
std::vector<PlacementEntry::Flora> m_flora;
|
||||
std::vector<PlacementEntry::Ore> m_ores;
|
||||
std::vector<PlacementEntry::Tree> m_trees;
|
||||
};
|
||||
|
||||
#endif // BIOME_HPP_
|
||||
#endif // BIOME_HPP_
|
||||
|
80
common/source/world/PlacementEntry.hpp
Normal file
80
common/source/world/PlacementEntry.hpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* OpenMiner
|
||||
*
|
||||
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
|
||||
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
|
||||
*
|
||||
* This file is part of OpenMiner.
|
||||
*
|
||||
* OpenMiner is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* OpenMiner is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef PLACEMENTENTRY_HPP_
|
||||
#define PLACEMENTENTRY_HPP_
|
||||
|
||||
#include <gk/core/IntTypes.hpp>
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
|
||||
#include "ISerializable.hpp"
|
||||
|
||||
namespace PlacementEntry {
|
||||
|
||||
struct Flora : public ISerializable {
|
||||
u16 blockID;
|
||||
u16 spawnsOnBlockID;
|
||||
double probability;
|
||||
|
||||
void serialize(sf::Packet &packet) const override {
|
||||
packet << blockID << spawnsOnBlockID << probability;
|
||||
}
|
||||
|
||||
void deserialize(sf::Packet &packet) override {
|
||||
packet >> blockID >> spawnsOnBlockID >> probability;
|
||||
}
|
||||
};
|
||||
|
||||
struct Ore : public ISerializable {
|
||||
u16 blockID;
|
||||
double probability;
|
||||
double size;
|
||||
|
||||
void serialize(sf::Packet &packet) const override {
|
||||
packet << blockID << probability << size;
|
||||
}
|
||||
|
||||
void deserialize(sf::Packet &packet) override {
|
||||
packet >> blockID >> probability >> size;
|
||||
}
|
||||
};
|
||||
|
||||
struct Tree : public ISerializable {
|
||||
u16 treeID;
|
||||
double probability;
|
||||
|
||||
void serialize(sf::Packet &packet) const override {
|
||||
packet << treeID << probability;
|
||||
}
|
||||
|
||||
void deserialize(sf::Packet &packet) override {
|
||||
packet >> treeID >> probability;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace PlacementEntry
|
||||
|
||||
#endif // PLACEMENTENTRY_HPP_
|
44
common/source/world/Tree.cpp
Normal file
44
common/source/world/Tree.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* OpenMiner
|
||||
*
|
||||
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
|
||||
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
|
||||
*
|
||||
* This file is part of OpenMiner.
|
||||
*
|
||||
* OpenMiner is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* OpenMiner is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
|
||||
#include "Tree.hpp"
|
||||
#include "NetworkUtils.hpp"
|
||||
|
||||
Tree::Tree(u16 id, const std::string &stringID, const std::string &label) {
|
||||
m_id = id;
|
||||
m_stringID = stringID;
|
||||
m_label = label;
|
||||
}
|
||||
|
||||
void Tree::serialize(sf::Packet &packet) const {
|
||||
packet << m_id << m_stringID << m_label << m_logBlockID << m_leavesBlockID;
|
||||
}
|
||||
|
||||
void Tree::deserialize(sf::Packet &packet) {
|
||||
packet >> m_id >> m_stringID >> m_label >> m_logBlockID >> m_leavesBlockID;
|
||||
}
|
65
common/source/world/Tree.hpp
Normal file
65
common/source/world/Tree.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* OpenMiner
|
||||
*
|
||||
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
|
||||
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
|
||||
*
|
||||
* This file is part of OpenMiner.
|
||||
*
|
||||
* OpenMiner is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* OpenMiner is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef TREE_HPP_
|
||||
#define TREE_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <gk/core/IntTypes.hpp>
|
||||
|
||||
#include "ISerializable.hpp"
|
||||
|
||||
class Tree : public ISerializable
|
||||
{
|
||||
public:
|
||||
Tree() = default;
|
||||
Tree(u16 id, const std::string &stringID, const std::string &label);
|
||||
|
||||
void serialize(sf::Packet &packet) const override;
|
||||
void deserialize(sf::Packet &packet) override;
|
||||
|
||||
u16 id() const { return m_id; }
|
||||
const std::string &stringID() const { return m_stringID; }
|
||||
const std::string &label() const { return m_label; }
|
||||
void setLabel(const std::string &label) { m_label = label; }
|
||||
|
||||
u16 getLogBlockID() const { return m_logBlockID; }
|
||||
u16 getLeavesBlockID() const { return m_leavesBlockID; }
|
||||
|
||||
void setLogBlockID(u16 value) { m_logBlockID = value; }
|
||||
void setLeavesBlockID(u16 value) { m_leavesBlockID = value; }
|
||||
|
||||
private:
|
||||
u16 m_id;
|
||||
std::string m_stringID;
|
||||
std::string m_label;
|
||||
|
||||
u16 m_logBlockID;
|
||||
u16 m_leavesBlockID;
|
||||
};
|
||||
|
||||
#endif // TREE_HPP_
|
@ -26,63 +26,89 @@
|
||||
--
|
||||
|
||||
mod:biome {
|
||||
id = "default:grassland",
|
||||
name = "Grassland",
|
||||
id = "grassland",
|
||||
name = "Grassland",
|
||||
|
||||
params = {
|
||||
temperature = -0.6,
|
||||
precipitation = 0.4
|
||||
},
|
||||
params = {
|
||||
temperature = 0.5,
|
||||
precipitation = 0.3
|
||||
},
|
||||
|
||||
top_block = "default:grass",
|
||||
ground_block = "default:dirt",
|
||||
beach_block = "default:sand",
|
||||
liquid_block = "default:water",
|
||||
|
||||
flora = {
|
||||
{
|
||||
block = "default:tallgrass",
|
||||
spawns_on = "default:grass",
|
||||
probability = 0.25
|
||||
},
|
||||
{
|
||||
block = "default:flower",
|
||||
spawns_on = "default:grass",
|
||||
probability = 0.1
|
||||
}
|
||||
}
|
||||
top_block = "default:grass",
|
||||
ground_block = "default:dirt",
|
||||
deep_block = "default:stone",
|
||||
beach_block = "default:sand",
|
||||
liquid_block = "default:water",
|
||||
|
||||
trees = {
|
||||
{
|
||||
type = "default:oak",
|
||||
probability = 0.01041666667
|
||||
}
|
||||
},
|
||||
|
||||
-- Currently, all ores are defined per-biome. In a later update,
|
||||
-- we could see ores defined mostly by worldtype, and some extras
|
||||
-- added per biome. In addition, given the large world depth, we
|
||||
-- could decide whether ores at a point very far down should
|
||||
-- still depend on the surface biome, or only on the worldtype.
|
||||
ores = {
|
||||
{
|
||||
block = "default:iron_ore",
|
||||
probability = 0.0003,
|
||||
size = 8
|
||||
}
|
||||
},
|
||||
|
||||
flora = {
|
||||
{
|
||||
block = "default:tallgrass",
|
||||
spawns_on = "default:grass",
|
||||
probability = 0.25
|
||||
},
|
||||
{
|
||||
block = "default:dandelion",
|
||||
spawns_on = "default:grass",
|
||||
probability = 0.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod:biome {
|
||||
id = "default:mountain",
|
||||
name = "Mountain",
|
||||
id = "mountain",
|
||||
name = "Mountain",
|
||||
|
||||
params = {
|
||||
temperature = 0.5,
|
||||
precipitation = 0.3
|
||||
},
|
||||
params = {
|
||||
temperature = -0.6,
|
||||
precipitation = 0.4
|
||||
},
|
||||
|
||||
top_block = "default:stone",
|
||||
ground_block = "default:stone",
|
||||
beach_block = "default:stone",
|
||||
liquid_block = "default:water",
|
||||
|
||||
flora = { }
|
||||
top_block = "default:stone",
|
||||
ground_block = "default:stone",
|
||||
deep_block = "default:stone",
|
||||
beach_block = "default:stone",
|
||||
liquid_block = "default:water",
|
||||
|
||||
trees = {
|
||||
{
|
||||
type = "default:oak",
|
||||
probability = 0.00390625
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod:biome {
|
||||
id = "default:barren",
|
||||
name = "Barren",
|
||||
id = "desert",
|
||||
name = "Desert",
|
||||
|
||||
params = {
|
||||
temperature = 0.3,
|
||||
precipitation = -0.7
|
||||
},
|
||||
params = {
|
||||
temperature = -0.3,
|
||||
precipitation = -0.7
|
||||
},
|
||||
|
||||
top_block = "default:dirt",
|
||||
ground_block = "default:dirt",
|
||||
beach_block = "default:dirt",
|
||||
liquid_block = "default:water",
|
||||
|
||||
flora = { }
|
||||
}
|
||||
top_block = "default:sand",
|
||||
ground_block = "default:sand",
|
||||
deep_block = "default:stone",
|
||||
beach_block = "default:sand",
|
||||
liquid_block = "default:water"
|
||||
}
|
||||
|
@ -29,21 +29,9 @@ mod = LuaMod.new("default")
|
||||
dofile("mods/default/blocks.lua")
|
||||
dofile("mods/default/items.lua")
|
||||
dofile("mods/default/recipes.lua")
|
||||
dofile("mods/default/trees.lua")
|
||||
dofile("mods/default/biomes.lua")
|
||||
|
||||
openminer:world():terrain_generator():set_blocks({
|
||||
dirt = "default:dirt",
|
||||
grass = "default:grass",
|
||||
stone = "default:stone",
|
||||
log = "default:oak_wood",
|
||||
leaves = "default:oak_leaves",
|
||||
flower = "default:dandelion",
|
||||
water = "default:water",
|
||||
sand = "default:sand",
|
||||
tallgrass = "default:tallgrass",
|
||||
iron_ore = "default:iron_ore"
|
||||
})
|
||||
|
||||
function init(player)
|
||||
local player_inv = player:inventory()
|
||||
|
||||
|
33
mods/default/trees.lua
Normal file
33
mods/default/trees.lua
Normal file
@ -0,0 +1,33 @@
|
||||
--
|
||||
-- =====================================================================================
|
||||
--
|
||||
-- OpenMiner
|
||||
--
|
||||
-- Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
|
||||
-- Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
|
||||
--
|
||||
-- This file is part of OpenMiner.
|
||||
--
|
||||
-- OpenMiner is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- OpenMiner is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public License
|
||||
-- along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
|
||||
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
--
|
||||
-- =====================================================================================
|
||||
--
|
||||
|
||||
mod:tree {
|
||||
id = "oak",
|
||||
name = "Oak",
|
||||
log_block = "default:oak_wood",
|
||||
leaves_block = "default:oak_leaves"
|
||||
}
|
@ -26,12 +26,14 @@
|
||||
*/
|
||||
#include <map>
|
||||
|
||||
#include "Biome.hpp"
|
||||
#include "CraftingRecipe.hpp"
|
||||
#include "LuaMod.hpp"
|
||||
#include "PlacementEntry.hpp"
|
||||
#include "Registry.hpp"
|
||||
#include "ServerBlock.hpp"
|
||||
#include "Biome.hpp"
|
||||
#include "SmeltingRecipe.hpp"
|
||||
#include "Tree.hpp"
|
||||
|
||||
void LuaMod::registerBlock(const sol::table &table) {
|
||||
TilesDef tiles;
|
||||
@ -143,13 +145,23 @@ void LuaMod::registerSmeltingRecipe(const sol::table &table) {
|
||||
Registry::getInstance().registerRecipe<SmeltingRecipe>(input, output);
|
||||
}
|
||||
|
||||
void LuaMod::registerTree(const sol::table &table) {
|
||||
std::string stringID = m_id + ":" + table["id"].get<std::string>();
|
||||
std::string label = table["name"].get<std::string>();
|
||||
|
||||
Tree &tree = Registry::getInstance().registerTree(stringID, label);
|
||||
tree.setLogBlockID(Registry::getInstance().getBlockFromStringID(table["log_block"]).id());
|
||||
tree.setLeavesBlockID(Registry::getInstance().getBlockFromStringID(table["leaves_block"]).id());
|
||||
}
|
||||
|
||||
void LuaMod::registerBiome(const sol::table &table) {
|
||||
std::string stringID = m_id + ":" + table["id"].get<std::string>();
|
||||
std::string label = table["name"].get<std::string>();
|
||||
|
||||
Biome &biome = Registry::getInstance().registerBiome<Biome>(stringID, label);
|
||||
Biome &biome = Registry::getInstance().registerBiome(stringID, label);
|
||||
|
||||
// TODO eventually a WorldType could have a list of biome parameter names in order, and we could use those as the ordered keys.
|
||||
// TODO eventually a WorldType could have a list of biome parameter names in order,
|
||||
// and we could use those as the ordered keys.
|
||||
// Currently hardcoding "temperature" and "precipitation" to get something functional.
|
||||
size_t nBiomeParams = 2;
|
||||
std::vector<double> params(nBiomeParams);
|
||||
@ -157,10 +169,46 @@ void LuaMod::registerBiome(const sol::table &table) {
|
||||
params[1] = table["params"]["precipitation"];
|
||||
biome.setParams(params);
|
||||
|
||||
biome.setTopBlock(Registry::getInstance().getBlockFromStringID(table["top_block"]).id());
|
||||
biome.setGroundBlock(Registry::getInstance().getBlockFromStringID(table["ground_block"]).id());
|
||||
biome.setBeachBlock(Registry::getInstance().getBlockFromStringID(table["beach_block"]).id());
|
||||
biome.setLiquidBlock(Registry::getInstance().getBlockFromStringID(table["liquid_block"]).id());
|
||||
biome.setTopBlockID(Registry::getInstance().getBlockFromStringID(table["top_block"]).id());
|
||||
biome.setGroundBlockID(Registry::getInstance().getBlockFromStringID(table["ground_block"]).id());
|
||||
biome.setDeepBlockID(Registry::getInstance().getBlockFromStringID(table["deep_block"]).id());
|
||||
biome.setBeachBlockID(Registry::getInstance().getBlockFromStringID(table["beach_block"]).id());
|
||||
biome.setLiquidBlockID(Registry::getInstance().getBlockFromStringID(table["liquid_block"]).id());
|
||||
|
||||
sol::optional<sol::table> treeDefinitions = table["trees"];
|
||||
if (treeDefinitions != sol::nullopt) {
|
||||
for (const auto &it : treeDefinitions.value()) {
|
||||
sol::table treeDefinition = it.second.as<sol::table>();
|
||||
|
||||
PlacementEntry::Tree &treeEntry = biome.addTree();
|
||||
treeEntry.treeID = Registry::getInstance().getTreeFromStringID(treeDefinition["type"]).id();
|
||||
treeEntry.probability = treeDefinition["probability"];
|
||||
}
|
||||
}
|
||||
|
||||
sol::optional<sol::table> floraDefinitions = table["flora"];
|
||||
if (floraDefinitions != sol::nullopt) {
|
||||
for (const auto &it : floraDefinitions.value()) {
|
||||
sol::table floraDefinition = it.second.as<sol::table>();
|
||||
|
||||
PlacementEntry::Flora &floraEntry = biome.addFlora();
|
||||
floraEntry.blockID = Registry::getInstance().getBlockFromStringID(floraDefinition["block"]).id();
|
||||
floraEntry.spawnsOnBlockID = Registry::getInstance().getBlockFromStringID(floraDefinition["spawns_on"]).id();
|
||||
floraEntry.probability = floraDefinition["probability"];
|
||||
}
|
||||
}
|
||||
|
||||
sol::optional<sol::table> oreDefinitions = table["ore"];
|
||||
if (oreDefinitions != sol::nullopt) {
|
||||
for (const auto &it : oreDefinitions.value()) {
|
||||
sol::table oreDefinition = it.second.as<sol::table>();
|
||||
|
||||
PlacementEntry::Ore &oreEntry = biome.addOre();
|
||||
oreEntry.blockID = Registry::getInstance().getBlockFromStringID(oreDefinition["block"]).id();
|
||||
oreEntry.probability = oreDefinition["probability"];
|
||||
oreEntry.size = oreDefinition["size"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LuaMod::initUsertype(sol::state &lua) {
|
||||
@ -168,10 +216,11 @@ void LuaMod::initUsertype(sol::state &lua) {
|
||||
sol::constructors<LuaMod(std::string)>(),
|
||||
"id", &LuaMod::id,
|
||||
"block", &LuaMod::registerBlock,
|
||||
"biome", &LuaMod::registerBiome,
|
||||
"item", &LuaMod::registerItem,
|
||||
"crafting_recipe", &LuaMod::registerCraftingRecipe,
|
||||
"smelting_recipe", &LuaMod::registerSmeltingRecipe
|
||||
"smelting_recipe", &LuaMod::registerSmeltingRecipe,
|
||||
"tree", &LuaMod::registerTree,
|
||||
"biome", &LuaMod::registerBiome
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ class LuaMod {
|
||||
void registerItem(const sol::table &table);
|
||||
void registerCraftingRecipe(const sol::table &table);
|
||||
void registerSmeltingRecipe(const sol::table &table);
|
||||
void registerTree(const sol::table &table);
|
||||
void registerBiome(const sol::table &table);
|
||||
|
||||
const std::string &id() const { return m_id; }
|
||||
|
@ -67,10 +67,6 @@ void ScriptEngine::initUsertypes() {
|
||||
"terrain_generator", &ServerWorld::terrainGenerator
|
||||
);
|
||||
|
||||
m_lua.new_usertype<TerrainGenerator>("TerrainGenerator",
|
||||
"set_blocks", &TerrainGenerator::setBlocksFromLuaTable
|
||||
);
|
||||
|
||||
m_lua.new_usertype<Chunk>("Chunk",
|
||||
"get_block", &Chunk::getBlock,
|
||||
"get_data", &Chunk::getData,
|
||||
|
@ -24,32 +24,25 @@
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "TerrainBiomeSampler.hpp"
|
||||
#include "Registry.hpp"
|
||||
#include "Biome.hpp"
|
||||
#include "Registry.hpp"
|
||||
#include "TerrainBiomeSampler.hpp"
|
||||
|
||||
TerrainBiomeSampler::TerrainBiomeSampler() {
|
||||
|
||||
paramNoisesPtr = new FastNoise[nBiomeParams];
|
||||
for (u8 i = 0; i < nBiomeParams; i++) {
|
||||
paramNoisesPtr[i].SetNoiseType(FastNoise::NoiseType::SimplexFractal);
|
||||
paramNoisesPtr[i].SetFrequency(1 / 800.0f);
|
||||
paramNoisesPtr[i].SetFractalOctaves(5);
|
||||
paramNoisesPtr[i].SetSeed(i);
|
||||
m_paramNoises = std::vector<FastNoise>(biomeParamCount);
|
||||
for (u8 i = 0; i < biomeParamCount; i++) {
|
||||
m_paramNoises[i].SetNoiseType(FastNoise::NoiseType::SimplexFractal);
|
||||
m_paramNoises[i].SetFrequency(1 / 800.0f);
|
||||
m_paramNoises[i].SetFractalOctaves(5);
|
||||
m_paramNoises[i].SetSeed(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TerrainBiomeSampler::~TerrainBiomeSampler() {
|
||||
delete paramNoisesPtr;
|
||||
}
|
||||
|
||||
u16 TerrainBiomeSampler::getBiomeIndexAt(s32 x, s32 y) const {
|
||||
|
||||
// Compute noise instances
|
||||
double* biomeParamsPtr = new double[nBiomeParams];
|
||||
for (u8 i = 0; i < nBiomeParams; i++) {
|
||||
biomeParamsPtr[i] = paramNoisesPtr[i].GetNoise(x, y);
|
||||
std::vector<double> biomeParams(biomeParamCount);
|
||||
for (u8 i = 0; i < biomeParamCount; i++) {
|
||||
biomeParams[i] = m_paramNoises[i].GetNoise(x, y);
|
||||
}
|
||||
|
||||
// TODO with a lot of biomes, perhaps we want an R-Tree or similar, instead of a long loop.
|
||||
@ -58,12 +51,12 @@ u16 TerrainBiomeSampler::getBiomeIndexAt(s32 x, s32 y) const {
|
||||
// True temp/precip values can then be re-interpolated out from the Voronoi diagram using a neighborhood figure "kernel".
|
||||
// TODO with multiple worldtypes added, need to only consider biomes in one worldtype.
|
||||
u16 decidedBiomeIndex = 0;
|
||||
double decidedBiomeDeviation = 0xFFFF;
|
||||
double decidedBiomeDeviation = INFINITY;
|
||||
u16 j = 0;
|
||||
for (auto &biome : Registry::getInstance().biomes()) {
|
||||
double deviation = 0;
|
||||
for (int i = 0; i < nBiomeParams; i++) {
|
||||
double dp = biomeParamsPtr[i] - biome.get()->getParams()[i];
|
||||
for (int i = 0; i < biomeParamCount; i++) {
|
||||
double dp = biomeParams[i] - biome.getParams()[i];
|
||||
deviation += dp * dp;
|
||||
}
|
||||
if (deviation < decidedBiomeDeviation) {
|
||||
@ -73,6 +66,5 @@ u16 TerrainBiomeSampler::getBiomeIndexAt(s32 x, s32 y) const {
|
||||
j++;
|
||||
}
|
||||
|
||||
delete biomeParamsPtr;
|
||||
return decidedBiomeIndex;
|
||||
}
|
||||
}
|
||||
|
@ -27,21 +27,23 @@
|
||||
#ifndef TERRAINBIOMESAMPLER_HPP_
|
||||
#define TERRAINBIOMESAMPLER_HPP_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gk/core/IntTypes.hpp>
|
||||
#include "FastNoise.hpp"
|
||||
|
||||
#include "Biome.hpp"
|
||||
#include "FastNoise.hpp"
|
||||
|
||||
class TerrainBiomeSampler {
|
||||
public:
|
||||
TerrainBiomeSampler(); // TODO should eventually take a worldtype
|
||||
~TerrainBiomeSampler();
|
||||
public:
|
||||
TerrainBiomeSampler(); // TODO should eventually take a worldtype
|
||||
|
||||
u16 getBiomeIndexAt(s32 x, s32 y) const;
|
||||
//std::vector<WeightedIndex> getWeightedBiomeIndicesAt(double x, double y);
|
||||
u16 getBiomeIndexAt(s32 x, s32 y) const;
|
||||
//std::vector<WeightedIndex> getWeightedBiomeIndicesAt(double x, double y);
|
||||
|
||||
private:
|
||||
u8 nBiomeParams = 2; // TODO should be defined in the worldtype
|
||||
FastNoise* paramNoisesPtr;
|
||||
private:
|
||||
static const u8 biomeParamCount = 2; // TODO if kept, should be defined in the worldtype, dynamically.
|
||||
std::vector<FastNoise> m_paramNoises;
|
||||
};
|
||||
|
||||
#endif // TERRAINBIOMESAMPLER_HPP_
|
||||
#endif // TERRAINBIOMESAMPLER_HPP_
|
||||
|
@ -40,19 +40,6 @@ void TerrainGenerator::generate(ServerChunk &chunk) const {
|
||||
fastNoiseGeneration(chunk);
|
||||
}
|
||||
|
||||
void TerrainGenerator::setBlocksFromLuaTable(const sol::table &table) {
|
||||
m_dirtBlockID = Registry::getInstance().getBlockFromStringID(table["dirt"].get<std::string>()).id();
|
||||
m_grassBlockID = Registry::getInstance().getBlockFromStringID(table["grass"].get<std::string>()).id();
|
||||
m_stoneBlockID = Registry::getInstance().getBlockFromStringID(table["stone"].get<std::string>()).id();
|
||||
m_logBlockID = Registry::getInstance().getBlockFromStringID(table["log"].get<std::string>()).id();
|
||||
m_leavesBlockID = Registry::getInstance().getBlockFromStringID(table["leaves"].get<std::string>()).id();
|
||||
m_flowerBlockID = Registry::getInstance().getBlockFromStringID(table["flower"].get<std::string>()).id();
|
||||
m_waterBlockID = Registry::getInstance().getBlockFromStringID(table["water"].get<std::string>()).id();
|
||||
m_sandBlockID = Registry::getInstance().getBlockFromStringID(table["sand"].get<std::string>()).id();
|
||||
m_tallgrassBlockID = Registry::getInstance().getBlockFromStringID(table["tallgrass"].get<std::string>()).id();
|
||||
m_ironOreBlockID = Registry::getInstance().getBlockFromStringID(table["iron_ore"].get<std::string>()).id();
|
||||
}
|
||||
|
||||
void TerrainGenerator::fastNoiseGeneration(ServerChunk &chunk) const {
|
||||
FastNoise noise;
|
||||
noise.SetNoiseType(FastNoise::NoiseType::SimplexFractal);
|
||||
@ -65,7 +52,7 @@ void TerrainGenerator::fastNoiseGeneration(ServerChunk &chunk) const {
|
||||
for(int x = 0 ; x < CHUNK_WIDTH ; x++) {
|
||||
|
||||
u16 biomeIndex = biomeSampler.getBiomeIndexAt(x + chunk.x() * CHUNK_WIDTH, y + chunk.y() * CHUNK_DEPTH);
|
||||
auto &biome = Registry::getInstance().getBiome(biomeIndex);
|
||||
const Biome &biome = Registry::getInstance().getBiome(biomeIndex);
|
||||
|
||||
// Land height
|
||||
double n = noise.GetNoise(-x - chunk.x() * CHUNK_WIDTH, y + chunk.y() * CHUNK_DEPTH);
|
||||
@ -78,57 +65,92 @@ void TerrainGenerator::fastNoiseGeneration(ServerChunk &chunk) const {
|
||||
for(int z = 0 ; z < CHUNK_HEIGHT ; z++) {
|
||||
// Are we above "ground" level?
|
||||
if(z + chunk.z() * CHUNK_HEIGHT > h) {
|
||||
|
||||
// If we are not yet up to sea level, fill with water blocks
|
||||
if(z + chunk.z() * CHUNK_HEIGHT < SEALEVEL) {
|
||||
chunk.setBlockRaw(x, y, z, m_waterBlockID);
|
||||
if (z + chunk.z() * CHUNK_HEIGHT < SEALEVEL) {
|
||||
chunk.setBlockRaw(x, y, z, biome.getLiquidBlockID());
|
||||
}
|
||||
// Otherwise we are in the air, so try to make a tree
|
||||
else if(chunk.getBlock(x, y, z - 1) == m_grassBlockID && (rand() % 64) == 0 && n < 4) {
|
||||
// Trunk
|
||||
int h = (rand() & 3) + 3;
|
||||
for(int i = 0 ; i < h ; i++) {
|
||||
chunk.setBlockRaw(x, y, z + i, m_logBlockID);
|
||||
}
|
||||
// Otherwise we are in the air
|
||||
else {
|
||||
bool placedTree = false;
|
||||
if (chunk.getBlock(x, y, z - 1) == biome.getTopBlockID()) {
|
||||
for (const PlacementEntry::Tree &treePlacement : biome.getTrees()) {
|
||||
if (rand() > RAND_MAX * treePlacement.probability) continue;
|
||||
const Tree &tree = Registry::getInstance().getTree(treePlacement.treeID);
|
||||
|
||||
// Leaves
|
||||
for(int iz = -3 ; iz <= 3 ; iz++) {
|
||||
for(int iy = -3 ; iy <= 3 ; iy++) {
|
||||
for(int ix = -3 ; ix <= 3 ; ix++) {
|
||||
if(ix * ix + iy * iy + iz * iz < 8 + (rand() & 1) && !chunk.getBlock(x + ix, y + iy, z + h + iz)) {
|
||||
chunk.setBlockRaw(x + ix, y + iy, z + h + iz, m_leavesBlockID);
|
||||
// Trunk
|
||||
int h = (rand() & 3) + 3;
|
||||
for (int i = 0; i < h; i++) {
|
||||
chunk.setBlockRaw(x, y, z + i, tree.getLogBlockID());
|
||||
}
|
||||
|
||||
// FIXME: This is a temporary fix for the second part of #41
|
||||
chunk.lightmap().setSunlight(x + ix, y + iy, z + h + iz, 0);
|
||||
// Leaves
|
||||
for (int iz = -3; iz <= 3; iz++) {
|
||||
for (int iy = -3; iy <= 3; iy++) {
|
||||
for (int ix = -3; ix <= 3; ix++) {
|
||||
if (ix * ix + iy * iy + iz * iz < 8 + (rand() & 1) && !chunk.getBlock(x + ix, y + iy, z + h + iz)) {
|
||||
chunk.setBlockRaw(x + ix, y + iy, z + h + iz, tree.getLeavesBlockID());
|
||||
|
||||
// FIXME: This is a temporary fix for the second part of #41
|
||||
chunk.lightmap().setSunlight(x + ix, y + iy, z + h + iz, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
placedTree = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise try to place flora.
|
||||
if (!placedTree) {
|
||||
bool placedFlora = false;
|
||||
for (const PlacementEntry::Flora &flora : biome.getFlora()) {
|
||||
if (chunk.getBlock(x, y, z - 1) != flora.spawnsOnBlockID) continue;
|
||||
if (rand() > RAND_MAX * flora.probability) continue;
|
||||
chunk.setBlockRaw(x, y, z, flora.blockID);
|
||||
placedFlora = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise set sunlight.
|
||||
if (!placedFlora && z == CHUNK_HEIGHT - 1) {
|
||||
chunk.lightmap().addSunlight(x, y, z, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Or tallgrass
|
||||
else if(chunk.getBlock(x, y, z - 1) == m_grassBlockID && (rand() % 32) == 0) {
|
||||
chunk.setBlockRaw(x, y, z, m_tallgrassBlockID);
|
||||
}
|
||||
// Or a flower
|
||||
else if(chunk.getBlock(x, y, z - 1) == m_grassBlockID && (rand() & 0xff) == 0) {
|
||||
chunk.setBlockRaw(x, y, z, m_flowerBlockID);
|
||||
}
|
||||
// If we are on the top block of the chunk, add sunlight
|
||||
else if (z == CHUNK_HEIGHT - 1) {
|
||||
chunk.lightmap().addSunlight(x, y, z, 15);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (z + chunk.z() * CHUNK_HEIGHT >= h - 1 && z + chunk.z() * CHUNK_HEIGHT > SEALEVEL - 1)
|
||||
chunk.setBlockRaw(x, y, z, biome.getTopBlock());
|
||||
chunk.setBlockRaw(x, y, z, biome.getTopBlockID());
|
||||
else if (z + chunk.z() * CHUNK_HEIGHT <= SEALEVEL - 1 && h < SEALEVEL && z + chunk.z() * CHUNK_HEIGHT > h - 3)
|
||||
chunk.setBlockRaw(x, y, z, biome.getBeachBlock());
|
||||
chunk.setBlockRaw(x, y, z, biome.getBeachBlockID());
|
||||
else if (z + chunk.z() * CHUNK_HEIGHT > h - 3)
|
||||
chunk.setBlockRaw(x, y, z, biome.getGroundBlock());
|
||||
chunk.setBlockRaw(x, y, z, biome.getGroundBlockID());
|
||||
else
|
||||
chunk.setBlockRaw(x, y, z, m_stoneBlockID);
|
||||
chunk.setBlockRaw(x, y, z, biome.getDeepBlockID());
|
||||
|
||||
if ((rand() % 4096) == 0)
|
||||
oreFloodFill(chunk, x, y, z, m_stoneBlockID, m_ironOreBlockID, 2);
|
||||
// Populate ores.
|
||||
// TODO: Like trees, ores should be able to seamlessly cross chunk boundaries.
|
||||
// This could be achieved either by setting up a generation pipeline with stages,
|
||||
// processing neighboring chunks' ores every time, or generating them with noise.
|
||||
for (const PlacementEntry::Ore &ore : biome.getOres()) {
|
||||
if (rand() > RAND_MAX * ore.probability) continue;
|
||||
oreFloodFill(chunk, x, y, z, biome.getDeepBlockID(), ore.blockID, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
// Caves
|
||||
float n2 = noise2d(-(x + chunk.x() * CHUNK_WIDTH) / 256.0, (y + chunk.y() * CHUNK_DEPTH) / 256.0, 8, 0.3) * 4;
|
||||
float r2 = noise3d_abs(-(x + chunk.x() * CHUNK_WIDTH) / 512.0f, (z + chunk.z() * CHUNK_HEIGHT) / 512.0f, (y + chunk.y() * CHUNK_DEPTH) / 512.0f, 4, 0.1);
|
||||
float r3 = noise3d_abs(-(x + chunk.x() * CHUNK_WIDTH) / 512.0f, (z + chunk.z() * CHUNK_HEIGHT) / 128.0f, (y + chunk.y() * CHUNK_DEPTH) / 512.0f, 4, 1);
|
||||
float r4 = n2 * 5 + r2 * r3 * 20;
|
||||
if (r4 > 6 && r4 < 8 && h > SEALEVEL) {
|
||||
chunk.setBlockRaw(x, y, z - 1, 0);
|
||||
chunk.setBlockRaw(x, y, z, 0);
|
||||
chunk.setBlockRaw(x, y, z + 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (topChunk && topChunk->isInitialized()) {
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <gk/core/IntTypes.hpp>
|
||||
#include <sol.hpp>
|
||||
|
||||
#include "TerrainBiomeSampler.hpp"
|
||||
|
||||
class ServerChunk;
|
||||
@ -39,8 +40,6 @@ class TerrainGenerator {
|
||||
|
||||
void generate(ServerChunk &chunk) const;
|
||||
|
||||
void setBlocksFromLuaTable(const sol::table &table);
|
||||
|
||||
private:
|
||||
void fastNoiseGeneration(ServerChunk &chunk) const;
|
||||
|
||||
@ -49,17 +48,6 @@ class TerrainGenerator {
|
||||
static float noise3d_abs(double x, double y, double z, int octaves, float persistence);
|
||||
|
||||
TerrainBiomeSampler biomeSampler;
|
||||
|
||||
u16 m_dirtBlockID = 0;
|
||||
u16 m_grassBlockID = 0;
|
||||
u16 m_stoneBlockID = 0;
|
||||
u16 m_logBlockID = 0;
|
||||
u16 m_leavesBlockID = 0;
|
||||
u16 m_flowerBlockID = 0;
|
||||
u16 m_waterBlockID = 0;
|
||||
u16 m_sandBlockID = 0;
|
||||
u16 m_tallgrassBlockID = 0;
|
||||
u16 m_ironOreBlockID = 0;
|
||||
};
|
||||
|
||||
#endif // TERRAINGENERATOR_HPP_
|
||||
|
Loading…
x
Reference in New Issue
Block a user