Brandling Safari: LAN safari-zone creature catching on the HD-2D engine
- Authoritative 30 Hz server (ENet, SQLite): accounts, characters, wild AI, tall grass / water / wandering spawns, fishing, captures, follower chains, clock + weather, LAN beacon - Client: title / join / character creator / play screens, prediction + reconciliation, interpolated players and parties, HD-2D UI (dialogue with Professor Henry, HUD, collection) - Shared deterministic zone generator, movement, protocol, roster, appearance - Paper-doll character art pipeline (PixelLab base walk + per-item animation edits) - Brandling roster from the company list (logo colors, jev types), Blender safari props - Headless test bot
This commit is contained in:
143
shared/Protocol.cpp
Normal file
143
shared/Protocol.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "Protocol.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace bs {
|
||||
|
||||
namespace {
|
||||
const char* kWeatherNames[] = {"clear", "cloudy", "rain", "storm", "fog"};
|
||||
}
|
||||
|
||||
const char* weatherName(Weather w) {
|
||||
int i = int(w);
|
||||
return i >= 0 && i < int(Weather::Count) ? kWeatherNames[i] : "clear";
|
||||
}
|
||||
|
||||
bool parseWeather(const std::string& s, Weather& out) {
|
||||
for (int i = 0; i < int(Weather::Count); ++i)
|
||||
if (s == kWeatherNames[i]) {
|
||||
out = Weather(i);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void writeAppearance(Writer& w, const Appearance& a) {
|
||||
w.str(a.body);
|
||||
w.u8(a.skin);
|
||||
for (int s = 0; s < kSlotCount; ++s) {
|
||||
w.str(a.items[s]);
|
||||
w.u32(a.colors[s]);
|
||||
}
|
||||
}
|
||||
|
||||
Appearance readAppearance(Reader& r) {
|
||||
Appearance a;
|
||||
a.body = r.str();
|
||||
a.skin = r.u8();
|
||||
for (int s = 0; s < kSlotCount; ++s) {
|
||||
a.items[s] = r.str();
|
||||
a.colors[s] = r.u32();
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void InputMsg::write(Writer& w) const {
|
||||
size_t n = std::min<size_t>(cmds.size(), 4);
|
||||
w.u8(uint8_t(n));
|
||||
for (size_t i = cmds.size() - n; i < cmds.size(); ++i) {
|
||||
w.u32(cmds[i].seq);
|
||||
w.i8(cmds[i].moveX);
|
||||
w.i8(cmds[i].moveZ);
|
||||
w.u8(cmds[i].flags);
|
||||
}
|
||||
}
|
||||
|
||||
void InputMsg::read(Reader& r) {
|
||||
uint8_t n = std::min<uint8_t>(r.u8(), 4);
|
||||
cmds.resize(n);
|
||||
for (InputCmd& c : cmds) {
|
||||
c.seq = r.u32();
|
||||
c.moveX = r.i8();
|
||||
c.moveZ = r.i8();
|
||||
c.flags = r.u8();
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileMsg::write(Writer& w) const {
|
||||
w.u32(entityId);
|
||||
w.str(name);
|
||||
writeAppearance(w, look);
|
||||
w.i32(capsules);
|
||||
w.u8(introDone);
|
||||
w.u32(seen);
|
||||
w.u32(caught);
|
||||
w.u32(uint32_t(creatures.size()));
|
||||
for (const OwnedCreature& c : creatures) {
|
||||
w.u32(c.uid);
|
||||
w.u16(c.species);
|
||||
w.u8(c.inParty);
|
||||
w.i64(c.caughtAt);
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileMsg::read(Reader& r) {
|
||||
entityId = r.u32();
|
||||
name = r.str();
|
||||
look = readAppearance(r);
|
||||
capsules = r.i32();
|
||||
introDone = r.u8();
|
||||
seen = r.u32();
|
||||
caught = r.u32();
|
||||
uint32_t n = std::min<uint32_t>(r.u32(), 100000);
|
||||
creatures.clear();
|
||||
for (uint32_t i = 0; i < n && r.ok(); ++i) {
|
||||
OwnedCreature c;
|
||||
c.uid = r.u32();
|
||||
c.species = r.u16();
|
||||
c.inParty = r.u8();
|
||||
c.caughtAt = r.i64();
|
||||
creatures.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
void SnapshotMsg::write(Writer& w) const {
|
||||
w.u32(tick);
|
||||
w.u32(ackInput);
|
||||
w.f32(hour);
|
||||
w.u8(uint8_t(weather));
|
||||
w.f32(weatherBlend);
|
||||
w.u16(uint16_t(entities.size()));
|
||||
for (const EntityState& e : entities) {
|
||||
w.u32(e.id);
|
||||
w.u8(uint8_t(e.kind));
|
||||
w.u8(uint8_t(e.anim));
|
||||
w.u16(e.species);
|
||||
w.u32(e.owner);
|
||||
w.vec3(e.pos);
|
||||
w.f32(e.yaw);
|
||||
w.u8(e.order);
|
||||
}
|
||||
}
|
||||
|
||||
void SnapshotMsg::read(Reader& r) {
|
||||
tick = r.u32();
|
||||
ackInput = r.u32();
|
||||
hour = r.f32();
|
||||
weather = Weather(std::min<uint8_t>(r.u8(), uint8_t(Weather::Count) - 1));
|
||||
weatherBlend = r.f32();
|
||||
uint16_t n = r.u16();
|
||||
entities.resize(n);
|
||||
for (EntityState& e : entities) {
|
||||
e.id = r.u32();
|
||||
e.kind = EntityKind(r.u8());
|
||||
e.anim = Anim(r.u8());
|
||||
e.species = r.u16();
|
||||
e.owner = r.u32();
|
||||
e.pos = r.vec3();
|
||||
e.yaw = r.f32();
|
||||
e.order = r.u8();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bs
|
||||
Reference in New Issue
Block a user