Compare commits
3 Commits
71a52bd7e3
...
3666fc2ed8
Author | SHA1 | Date |
---|---|---|
May B. | 3666fc2ed8 | |
May B. | ec467ca037 | |
May B. | 5fdff56f8f |
|
@ -90,6 +90,7 @@ cmake <options> ..
|
|||
```
|
||||
|
||||
CMake options: `-DKEY=VAL`
|
||||
|
||||
Key | Usage | Default
|
||||
--- | --- | ---
|
||||
SIMD_LEVEL | SIMD processor acceleration (sse2, sse4.1, avx2, avx512f) | `avx2`
|
||||
|
@ -144,6 +145,7 @@ Distributed under the MIT License. See [LICENSE](LICENSE) for more information.
|
|||
<!-- CONTACT -->
|
||||
## Contact
|
||||
|
||||
Maelys Bois - [/me](https://git.wadza.fr/me) - me@wadza.fr
|
||||
Shu - [/me](https://git.wadza.fr/me) - me@wadza.fr
|
||||
|
||||
Project Link: [https://git.wadza.fr/me/univerxel](https://git.wadza.fr/me/univerxel)
|
||||
Public releases: [https://framagit.org/univerxel/univerxel](https://framagit.org/univerxel/univerxel)
|
||||
Working repo: [https://git.wadza.fr/me/univerxel](https://git.wadza.fr/me/univerxel)
|
||||
|
|
20
TODO.md
20
TODO.md
|
@ -25,22 +25,24 @@
|
|||
- [ ] Local prediction
|
||||
- [ ] Contouring service
|
||||
- [~] Edit
|
||||
- [ ] Shape iterators
|
||||
- Cube
|
||||
- Sphere
|
||||
- [ ] More types
|
||||
- Anchor
|
||||
- Prevent suffocation
|
||||
- [x] Shape iterators
|
||||
- [ ] More shapes
|
||||
- [ ] Anchor
|
||||
- [x] Prevent suffocation
|
||||
- [ ] Local prediction
|
||||
- [~] Occlusion Culling
|
||||
- [ ] Iterator ray
|
||||
- [ ] Cast from chunk center
|
||||
- [x] Transparency
|
||||
- [~] Entities
|
||||
- Get models
|
||||
- [ ] Collide
|
||||
- [ ] Get models
|
||||
|
||||
## Hello universe
|
||||
|
||||
- [ ] CI build
|
||||
- CMake package
|
||||
- GitLab / Drone pipeline
|
||||
- [ ] Universe
|
||||
- [ ] Galaxy
|
||||
- [ ] Rotation
|
||||
|
@ -56,7 +58,8 @@
|
|||
- https://imgur.com/kM8b5Zq
|
||||
- https://imgur.com/a/bh2iy
|
||||
- https://speciesdevblog.files.wordpress.com/2012/11/biomemap.png
|
||||
- Curvature
|
||||
- [ ] Planet scale LOD
|
||||
- [~] Curvature
|
||||
- [~] CubeSphere
|
||||
- [ ] Area corrected CubeSphere
|
||||
- [ ] Corrected Normals
|
||||
|
@ -67,6 +70,7 @@
|
|||
## Hello industry
|
||||
|
||||
- [ ] Multiblock
|
||||
- [ ] Inventory
|
||||
|
||||
## Hello darkness
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ void Client::run(server_handle* const localHandle) {
|
|||
if(auto target = std::get_if<world::Universe::ray_target>(&ray_result)) {
|
||||
state.look_at = *target;
|
||||
const auto &tool = options.editor.tool;
|
||||
state.can_fill = true; //FIXME: world->canFill(target->pos, tool.shape, tool.radius);
|
||||
state.can_fill = world->isAreaFree(target->pos, world::action::ToGeometry(tool.shape), tool.radius);
|
||||
} else {
|
||||
state.look_at = {};
|
||||
}
|
||||
|
@ -79,9 +79,10 @@ void Client::run(server_handle* const localHandle) {
|
|||
if (inputs.isPressing(Mouse::Left))
|
||||
world->emit(world::action::FillShape(
|
||||
state.look_at.value().pos, world::Voxel(world::materials::AIR, tool.emptyAir * world::Voxel::DENSITY_MAX), tool.shape, tool.radius));
|
||||
else if (inputs.isPressing(Mouse::Right))
|
||||
else if (const auto voxel = world::Voxel(tool.material, world::Voxel::DENSITY_MAX);
|
||||
inputs.isPressing(Mouse::Right) && (state.can_fill || !voxel.is_solid()))
|
||||
world->emit(world::action::FillShape(
|
||||
state.look_at.value().pos, world::Voxel(tool.material, world::Voxel::DENSITY_MAX), tool.shape, tool.radius));
|
||||
state.look_at.value().pos, voxel, tool.shape, tool.radius));
|
||||
}
|
||||
if (inputs.isDown(Input::Throw)) {
|
||||
//FIXME: register entity type world->addEntity(entity_id(0), {state.position * options.voxel_density, glm::vec3(10, 0, 0)});
|
||||
|
@ -197,8 +198,9 @@ void Client::run(server_handle* const localHandle) {
|
|||
const auto pass = pipeline->beginIndicatorPass();
|
||||
if(state.look_at.has_value()) { // Indicator
|
||||
const auto model = glm::scale(glm::translate(glm::scale(glm::mat4(1), 1.f / glm::vec3(options.voxel_density)), glm::vec3(state.look_at.value().pos.second + state.look_at.value().offset - offset * glm::llvec3(options.voxel_density)) - glm::vec3(.5 + options.editor.tool.radius)), glm::vec3(1 + options.editor.tool.radius * 2));
|
||||
const auto color = state.can_fill ? glm::vec4(1, 1, 1, .5) : (world::materials::solidity[options.editor.tool.material] ? glm::vec4(1, 0, 0, .5) : glm::vec4(1, .5, 0, .5));
|
||||
reports.models_count++;
|
||||
reports.tris_count += pass(model, options.editor.tool.shape, state.can_fill ? glm::vec4(1, 1, 1, .5) : glm::vec4(1, 0, 0, .5));
|
||||
reports.tris_count += pass(model, options.editor.tool.shape, color);
|
||||
}
|
||||
}
|
||||
pipeline->postProcess();
|
||||
|
|
|
@ -253,6 +253,16 @@ namespace contouring {
|
|||
}
|
||||
ImGui::Columns(1);
|
||||
}
|
||||
if (ImGui::Button("Flush buffers")) {
|
||||
//TODO: prefer unique_ptr
|
||||
for(auto& buffer: buffers) {
|
||||
for(auto& val: buffer.second.second) {
|
||||
delete val.second.first;
|
||||
delete val.second.second;
|
||||
}
|
||||
}
|
||||
buffers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void FlatDualMC::render(const surrounding::corners &surrounding, render::LodModel::LodData &out, std::vector<render::VertexData> &tmp, Layer layer) const {
|
||||
|
|
|
@ -269,6 +269,18 @@ Universe::ray_result DistantUniverse::raycast(const geometry::Ray &ray) const {
|
|||
return Raycast(ray, areas);
|
||||
}
|
||||
|
||||
bool DistantUniverse::isAreaFree(const area_<voxel_pos> &pos, const geometry::Shape shape, const uint16_t radius) const {
|
||||
if (const auto it = areas.find(pos.first); it != areas.end()) {
|
||||
const auto center = pos.second + it->second->getOffset().as_voxel();
|
||||
return !entities.contains([&](size_t, const Entity &entity) {
|
||||
return entity.instances.contains([&](size_t, const Universe::Entity::Instance &inst) {
|
||||
return geometry::InShape(shape, center, radius, inst.pos.as_voxel(), entity.size);
|
||||
});
|
||||
});
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
void DistantUniverse::getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>& call,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density)
|
||||
{
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace world::client {
|
|||
|
||||
ray_result raycast(const geometry::Ray &) const override;
|
||||
|
||||
bool isAreaFree(const area_<voxel_pos> &pos, geometry::Shape shape, uint16_t radius) const override;
|
||||
|
||||
void getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>&,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density) override;
|
||||
|
||||
|
|
|
@ -55,6 +55,17 @@ void LocalUniverse::emit(const action::packet &packet) {
|
|||
Universe::ray_result LocalUniverse::raycast(const geometry::Ray& ray) const {
|
||||
return handle->raycast(ray);
|
||||
}
|
||||
bool LocalUniverse::isAreaFree(const area_<voxel_pos> &pos, const geometry::Shape shape, const uint16_t radius) const {
|
||||
if (const auto it = handle->areas->find(pos.first); it != handle->areas->end()) {
|
||||
const auto center = pos.second + it->second->getOffset().as_voxel();
|
||||
return !handle->entities->contains([&](entity_id, const Entity &entity) {
|
||||
return entity.instances.contains([&](entity_id, const Entity::Instance &inst) {
|
||||
return geometry::InShape(shape, center, radius, inst.pos.as_voxel(), entity.size);
|
||||
});
|
||||
});
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
void LocalUniverse::getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>& call,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density)
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace world::client {
|
|||
|
||||
ray_result raycast(const geometry::Ray &ray) const override;
|
||||
|
||||
bool isAreaFree(const area_<voxel_pos> &pos, geometry::Shape shape, uint16_t radius) const override;
|
||||
|
||||
void getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>&,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density) override;
|
||||
|
||||
|
|
|
@ -264,6 +264,16 @@ namespace data::generational {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename predicate>
|
||||
bool contains(predicate fn) const {
|
||||
for (size_t i = 0; i < this->size(); i++) {
|
||||
if(this->at(i).has_value() && fn(i, this->at(i).value())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t count() const {
|
||||
return std::count_if(this->begin(), this->end(),
|
||||
[](const std::optional<T> &e) { return e.has_value(); });
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "../flags.hpp"
|
||||
#include "../data/math.hpp"
|
||||
#include "IBox.hpp"
|
||||
|
||||
namespace geometry {
|
||||
|
||||
enum class Shape {
|
||||
Cube,
|
||||
Sphere
|
||||
};
|
||||
|
||||
static _FORCE_INLINE_ bool InShape(Shape shape, glm::llvec3 center, int radius, glm::llvec3 pos, glm::vec3 size) {
|
||||
switch (shape) {
|
||||
case Shape::Cube:
|
||||
return IBox::fromCenter(center, radius).contains(
|
||||
IBox::fromMin(pos, size)) != IBox::ContainmentType::Disjoint;
|
||||
|
||||
case Shape::Sphere:
|
||||
return glm::length2(center - pos) < glm::pow2(radius + (int)size.x);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -1,27 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
|
||||
/// Interger sphere fill
|
||||
struct SphereIterator {
|
||||
SphereIterator(const glm::ivec3 ¢er, int radius): center(center), radius(radius) { }
|
||||
|
||||
glm::ivec3 center;
|
||||
int radius;
|
||||
|
||||
void vector(std::vector<glm::ivec3>& out) {
|
||||
int top = center.y - radius, bottom = center.y + radius;
|
||||
|
||||
for (int y = top; y <= bottom; y++) {
|
||||
int dy = y - center.y, dxz = floor(sqrt(radius * radius - dy * dy));
|
||||
int minx = center.x - dxz, maxx = center.x + dxz;
|
||||
int minz = center.z - dxz, maxz = center.z + dxz;
|
||||
out.reserve(out.size() + dxz * dxz);
|
||||
for (int z = minz; z <= maxz; z++) {
|
||||
for (int x = minx; x <= maxx; x++) {
|
||||
out.emplace_back(x, y, z);
|
||||
}}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
#include "Voxel.hpp"
|
||||
#include "position.h"
|
||||
#include "../geometry/Ray.hpp"
|
||||
#include "../geometry/Shapes.hpp"
|
||||
|
||||
namespace world {
|
||||
/// Whole abstract universe container
|
||||
|
@ -43,6 +44,10 @@ namespace world {
|
|||
/// @note ray in world scale
|
||||
virtual ray_result raycast(const geometry::Ray &ray) const = 0;
|
||||
|
||||
/// Check for entity in shape
|
||||
/// MAYBE: multiarea
|
||||
virtual bool isAreaFree(const area_<voxel_pos> &pos, geometry::Shape shape, uint16_t radius) const = 0;
|
||||
|
||||
/// Check for collision on movement
|
||||
bool collide(const glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius = 0) const;
|
||||
/// Move with collision check
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "forward.h"
|
||||
#include "Voxel.hpp"
|
||||
#include <variant>
|
||||
#include "../flags.hpp"
|
||||
#include "../geometry/Shapes.hpp"
|
||||
|
||||
/// Client action on world
|
||||
namespace world::action {
|
||||
|
@ -17,9 +19,10 @@ struct Fill: part::Ping {
|
|||
const area_<voxel_pos> pos;
|
||||
const Voxel val;
|
||||
};
|
||||
enum class Shape : uint8_t {
|
||||
|
||||
enum class Shape: uint8_t {
|
||||
Cube,
|
||||
Sphere,
|
||||
RawSphere,
|
||||
/*SmoothSphere,
|
||||
CylinderX,
|
||||
CylinderY,
|
||||
|
@ -32,7 +35,16 @@ enum class Shape : uint8_t {
|
|||
ConeNZ,
|
||||
*/
|
||||
};
|
||||
constexpr auto SHAPES = "Cube\0Sphere\0";
|
||||
constexpr auto SHAPES = "Cube\0RawSphere\0";
|
||||
static _FORCE_INLINE_ geometry::Shape ToGeometry(Shape shape) {
|
||||
switch (shape) {
|
||||
case Shape::RawSphere:
|
||||
return geometry::Shape::Sphere;
|
||||
default:
|
||||
return geometry::Shape::Cube;
|
||||
}
|
||||
}
|
||||
|
||||
struct FillShape: Fill {
|
||||
FillShape(const area_<voxel_pos> &pos, const Voxel &val, Shape shape, uint8_t radius):
|
||||
Fill(pos, val), shape(shape), radius(radius) {}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
#include "iterators.hpp"
|
||||
|
||||
using namespace world::iterator;
|
||||
|
||||
std::unique_ptr<Abstract> world::iterator::Get(world::action::Shape shape, uint16_t radius) {
|
||||
switch (shape) {
|
||||
case world::action::Shape::Cube:
|
||||
return std::make_unique<Cube>(radius);
|
||||
case world::action::Shape::RawSphere:
|
||||
return std::make_unique<RawSphere>(radius);
|
||||
default:
|
||||
return std::unique_ptr<Abstract>(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool Cube::next(pair& out) {
|
||||
if (pos.z > radius)
|
||||
return false;
|
||||
|
||||
out.first = pos;
|
||||
out.second = 1;
|
||||
|
||||
// MAYBE: use linear idx to make branch less
|
||||
if (pos.x < radius) {
|
||||
pos.x++;
|
||||
} else {
|
||||
pos.x = -radius;
|
||||
if (pos.y < radius) {
|
||||
pos.y++;
|
||||
} else {
|
||||
pos.y = -radius;
|
||||
pos.z++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RawSphere::next(pair& out) {
|
||||
if (pos.x > radius)
|
||||
return false;
|
||||
|
||||
out.first = pos;
|
||||
out.second = 1;
|
||||
|
||||
if (pos.z < dz) {
|
||||
pos.z++;
|
||||
} else {
|
||||
if (pos.y < dy) {
|
||||
pos.y++;
|
||||
} else {
|
||||
pos.x++;
|
||||
dy = floor(sqrt(radius * radius - pos.x * pos.x));
|
||||
pos.y = -dy;
|
||||
}
|
||||
dz = floor(sqrt(dy * dy - pos.y * pos.y));
|
||||
pos.z = -dz;
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "position.h"
|
||||
#include "actions.hpp"
|
||||
|
||||
namespace world::iterator {
|
||||
|
||||
using pair = std::pair<glm::ivec3, float>;
|
||||
|
||||
class Abstract {
|
||||
public:
|
||||
virtual bool next(pair&) = 0;
|
||||
|
||||
protected:
|
||||
static constexpr uint32_t Diam(uint16_t radius) { return radius * 2 + 1; }
|
||||
};
|
||||
|
||||
/// From -radius to radius
|
||||
std::unique_ptr<Abstract> Get(action::Shape, uint16_t radius);
|
||||
|
||||
class Cube final: public Abstract {
|
||||
public:
|
||||
bool next(pair&) override;
|
||||
|
||||
Cube(uint16_t radius): radius(radius), pos(-radius, -radius, -radius) { }
|
||||
|
||||
private:
|
||||
const uint16_t radius;
|
||||
glm::ivec3 pos;
|
||||
};
|
||||
|
||||
/// Interger sphere
|
||||
class RawSphere final: public Abstract {
|
||||
public:
|
||||
bool next(pair&) override;
|
||||
|
||||
RawSphere(uint16_t radius): radius(radius), pos(-radius, 0, 0), dy(0), dz(0) { }
|
||||
|
||||
private:
|
||||
const uint16_t radius;
|
||||
glm::ivec3 pos;
|
||||
int dy;
|
||||
int dz;
|
||||
};
|
||||
}
|
|
@ -15,10 +15,8 @@ SharedUniverse::SharedUniverse(const options &o, server_handle *const localHandl
|
|||
localHandle->entities = &entities;
|
||||
localHandle->emit = std::function([&](const world::action::packet &packet) {
|
||||
if(const auto fill = std::get_if<world::action::FillShape>(&packet)) {
|
||||
if (fill->shape == world::action::Shape::Cube)
|
||||
this->setCube(fill->pos, fill->val, fill->radius);
|
||||
else
|
||||
this->setSphere(fill->pos, fill->val, fill->radius);
|
||||
//NOTE: LocalUniverse had already check for entities
|
||||
this->set(fill->pos, fill->radius, fill->shape, fill->val);
|
||||
} else if(const auto message = std::get_if<world::action::Message>(&packet)) {
|
||||
this->broadcastMessage("Player" + std::to_string(id.index) + ": " + message->text);
|
||||
} else if(const auto move = std::get_if<world::action::Move>(&packet)) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "Chunk.hpp"
|
||||
#include "../../core/world/raycast.hpp"
|
||||
#include "../../core/world/iterators.hpp"
|
||||
#include "../../core/world/actions.hpp"
|
||||
#include "../../core/net/PacketView.hpp"
|
||||
|
||||
|
@ -454,12 +455,12 @@ void Universe::pullNetwork() {
|
|||
case client_packet_type::FILL_SHAPE: {
|
||||
if(const auto fill = PacketReader(packet).read<world::action::FillShape>()) {
|
||||
//TODO: check ray
|
||||
//TODO: check entities
|
||||
if (fill->val.is_solid() && !isAreaFree(fill->pos, world::action::ToGeometry(fill->shape), fill->radius)) {
|
||||
LOG_T("Entity in solid fill area");
|
||||
break;
|
||||
}
|
||||
set(fill->pos, fill->radius, fill->shape, fill->val);
|
||||
//TODO: handle inventory
|
||||
if (fill->shape == world::action::Shape::Cube)
|
||||
setCube(fill->pos, fill->val, fill->radius);
|
||||
else
|
||||
setSphere(fill->pos, fill->val, fill->radius);
|
||||
} else {
|
||||
LOG_T("Bad fill");
|
||||
}
|
||||
|
@ -542,30 +543,32 @@ Universe::ray_result Universe::raycast(const geometry::Ray &ray) const {
|
|||
return Raycast(ray, areas);
|
||||
}
|
||||
|
||||
std::optional<world::Item> Universe::set(const area_<voxel_pos>& pos, const Voxel& val) {
|
||||
if(const auto it = areas.find(pos.first); it != areas.end()) {
|
||||
auto &chunks = it->second->setChunks();
|
||||
const auto split = glm::splitIdx(pos.second);
|
||||
if(chunks.inRange(split.first))
|
||||
if(const auto chunk = chunks.findInRange(split.first))
|
||||
return {std::dynamic_pointer_cast<Chunk>(chunk.value())->replace(split.second, val)};
|
||||
}
|
||||
return {};
|
||||
bool Universe::isAreaFree(const area_<voxel_pos> &pos, const geometry::Shape shape, const uint16_t radius) const {
|
||||
if (const auto it = areas.find(pos.first); it != areas.end()) {
|
||||
const auto center = pos.second + it->second->getOffset().as_voxel();
|
||||
return !entities.contains([&](entity_id, const Entity &entity) {
|
||||
return entity.instances.contains([&](entity_id, const Entity::Instance &inst) {
|
||||
return geometry::InShape(shape, center, radius, inst.pos.as_voxel(), entity.size);
|
||||
});
|
||||
});
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
world::ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val, int radius) {
|
||||
|
||||
world::ItemList Universe::set(const area_<voxel_pos>& pos, int radius, action::Shape shape, const Voxel& val) {
|
||||
ZoneScopedN("Fill");
|
||||
ItemList list;
|
||||
if(const auto it = areas.find(pos.first); it != areas.end()) {
|
||||
robin_hood::unordered_map<chunk_pos, std::vector<Chunk::Edit>> edits;
|
||||
auto &chunks = it->second->setChunks();
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
//TODO: list.pop(val)
|
||||
const auto offset = voxel_pos(x, y, z);
|
||||
auto iterator = world::iterator::Get(shape, radius);
|
||||
world::iterator::pair point;
|
||||
while (iterator->next(point)) {
|
||||
const voxel_pos offset = point.first;
|
||||
const auto split = glm::splitIdx(pos.second + offset);
|
||||
if(chunks.inRange(split.first))
|
||||
if(chunks.inRange(split.first)) {
|
||||
if(const auto chunk = it->second->setChunks().findInRange(split.first)) {
|
||||
//TODO: use ratio in point.second
|
||||
auto ck = std::dynamic_pointer_cast<Chunk>(chunk.value());
|
||||
auto prev = ck->get(split.second);
|
||||
if(prev.value != val.value) {
|
||||
|
@ -576,56 +579,9 @@ world::ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val,
|
|||
ck->replace(split.second, val, delay);
|
||||
}
|
||||
}
|
||||
}}}
|
||||
ZoneScopedN("Packet");
|
||||
size_t size = sizeof(area_id);
|
||||
for(const auto& part: edits) {
|
||||
size += sizeof(chunk_pos);
|
||||
size += sizeof(chunk_voxel_idx);
|
||||
size += sizeof(Chunk::Edit) * part.second.size();
|
||||
}
|
||||
auto packet = net::Server::makePacket(net::server_packet_type::EDITS, NULL, size, 0);
|
||||
packet.write(pos.first);
|
||||
for(const auto& part: edits) {
|
||||
packet.write(part.first);
|
||||
packet.write<chunk_voxel_idx>(part.second.size());
|
||||
packet.write(part.second.data(), part.second.size() * sizeof(Chunk::Edit));
|
||||
}
|
||||
}
|
||||
|
||||
assert(packet.isFull());
|
||||
host.broadcast(packet.get(), net::channel_type::NOTIFY);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
world::ItemList Universe::setSphere(const area_<voxel_pos>& pos, const Voxel& val, int radius) {
|
||||
ZoneScopedN("FillSphere");
|
||||
ItemList list;
|
||||
if(const auto it = areas.find(pos.first); it != areas.end()) {
|
||||
robin_hood::unordered_map<chunk_pos, std::vector<Chunk::Edit>> edits;
|
||||
auto &chunks = it->second->setChunks();
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
const auto offset = voxel_pos(x, y, z);
|
||||
//FIXME: refactor with voxel_pos iterator
|
||||
if (glm::length2(offset) > glm::pow2(radius))
|
||||
continue;
|
||||
|
||||
//TODO: list.pop(val)
|
||||
const auto split = glm::splitIdx(pos.second + offset);
|
||||
if(chunks.inRange(split.first))
|
||||
if(const auto chunk = it->second->setChunks().findInRange(split.first)) {
|
||||
auto ck = std::dynamic_pointer_cast<Chunk>(chunk.value());
|
||||
auto prev = ck->get(split.second);
|
||||
if(prev.value != val.value) {
|
||||
//TODO: apply break table
|
||||
//TODO: inventory
|
||||
const auto delay = glm::length2(offset) / radius * .05f;
|
||||
edits[split.first].push_back(Chunk::Edit{split.second, val, delay});
|
||||
ck->replace(split.second, val, delay);
|
||||
}
|
||||
}
|
||||
}}}
|
||||
ZoneScopedN("Packet");
|
||||
size_t size = sizeof(area_id);
|
||||
for(const auto& part: edits) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <string>
|
||||
#include <thread>
|
||||
#include "../../core/world/Universe.hpp"
|
||||
#include "../../core/world/actions.hpp"
|
||||
#include "../../core/data/math.hpp"
|
||||
#include "../../core/data/safe_queue.hpp"
|
||||
#include "../../core/data/safe_priority_queue.hpp"
|
||||
|
@ -39,14 +40,9 @@ namespace world::server {
|
|||
/// Apply new options
|
||||
void setOptions(const options &);
|
||||
|
||||
/// Set voxel at pos
|
||||
std::optional<Item> set(const area_<voxel_pos> &pos, const Voxel &val);
|
||||
/// Set cube of voxel with pos as center
|
||||
/// Set volume of voxel with pos as center
|
||||
/// MAYBE: allow set multi area
|
||||
ItemList setCube(const area_<voxel_pos> &pos, const Voxel &val, int radius);
|
||||
/// Set sphere of voxel with pos as center
|
||||
/// MAYBE: allow set multi area
|
||||
ItemList setSphere(const area_<voxel_pos> &pos, const Voxel &val, int radius);
|
||||
ItemList set(const area_<voxel_pos> &pos, int radius, action::Shape shape, const Voxel &val);
|
||||
|
||||
/// Instante entity
|
||||
entity_instance_id addEntity(entity_id type, const Entity::Instance &instance);
|
||||
|
@ -59,6 +55,8 @@ namespace world::server {
|
|||
/// @note ray in world scale
|
||||
ray_result raycast(const geometry::Ray &ray) const override;
|
||||
|
||||
bool isAreaFree(const area_<voxel_pos> &pos, geometry::Shape shape, uint16_t radius) const override;
|
||||
|
||||
/// Check for collision on destination
|
||||
bool collide_end(const glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius) const;
|
||||
/// Check for collision at position
|
||||
|
|
Loading…
Reference in New Issue