protected dungeon ID optimization + /settileprotection improvements
This commit is contained in:
parent
9dbc4daacc
commit
8155ec6715
@ -211,32 +211,32 @@ Json jsonFromList(List<Value> const& list, Converter&& valueConvert) {
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
Set<Value> jsonToSet(Json const& v) {
|
||||
return jsonToSet<Value>(v, construct<Value>());
|
||||
template <typename SetType>
|
||||
SetType jsonToSet(Json const& v) {
|
||||
return jsonToSet<SetType>(v, construct<Value>());
|
||||
}
|
||||
|
||||
template <typename Value, typename Converter>
|
||||
Set<Value> jsonToSet(Json const& v, Converter&& valueConvert) {
|
||||
template <typename SetType, typename Converter>
|
||||
SetType jsonToSet(Json const& v, Converter&& valueConvert) {
|
||||
if (v.type() != Json::Type::Array)
|
||||
throw JsonException("Json type is not an array in jsonToSet");
|
||||
|
||||
Set<Value> res;
|
||||
SetType res;
|
||||
for (auto const& entry : v.iterateArray())
|
||||
res.add(valueConvert(entry));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
Json jsonFromSet(Set<Value> const& Set) {
|
||||
return jsonFromSet<Value>(Set, construct<Json>());
|
||||
template <typename SetType>
|
||||
Json jsonFromSet(SetType const& Set) {
|
||||
return jsonFromSet<SetType>(Set, construct<Json>());
|
||||
}
|
||||
|
||||
template <typename Value, typename Converter>
|
||||
Json jsonFromSet(Set<Value> const& Set, Converter&& valueConvert) {
|
||||
template <typename SetType, typename Converter>
|
||||
Json jsonFromSet(SetType const& Set, Converter&& valueConvert) {
|
||||
JsonArray res;
|
||||
for (auto entry : Set)
|
||||
for (auto& entry : Set)
|
||||
res.push_back(valueConvert(entry));
|
||||
|
||||
return res;
|
||||
|
@ -262,16 +262,33 @@ String CommandProcessor::setTileProtection(ConnectionId connectionId, String con
|
||||
return "Not enough arguments to /settileprotection. Use /settileprotection <dungeonId> <protected>";
|
||||
|
||||
try {
|
||||
DungeonId dungeonId = lexicalCast<DungeonId>(arguments.at(0));
|
||||
bool isProtected = lexicalCast<bool>(arguments.at(1));
|
||||
|
||||
bool done = m_universe->executeForClient(connectionId, [dungeonId, isProtected](WorldServer* world, PlayerPtr const&) {
|
||||
world->setTileProtection(dungeonId, isProtected);
|
||||
});
|
||||
|
||||
return done ? "" : "Failed to set block protection.";
|
||||
bool isProtected = lexicalCast<bool>(arguments.takeLast());
|
||||
List<DungeonId> dungeonIds;
|
||||
for (auto& banana : arguments) {
|
||||
auto slices = banana.split("..");
|
||||
auto it = slices.begin();
|
||||
DungeonId previous = 0;
|
||||
while (it != slices.end()) {
|
||||
DungeonId current = lexicalCast<DungeonId>(*it);
|
||||
dungeonIds.append(current);
|
||||
if (it++ != slices.begin() && previous != current) {
|
||||
if (current < previous) swap(previous, current);
|
||||
for (DungeonId id = previous + 1; id != current; ++id)
|
||||
dungeonIds.append(id);
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
}
|
||||
size_t changed = 0;
|
||||
if (!m_universe->executeForClient(connectionId, [&](WorldServer* world, PlayerPtr const&) {
|
||||
changed = world->setTileProtection(dungeonIds, isProtected);
|
||||
})) {
|
||||
return "Invalid client state";
|
||||
}
|
||||
String output = strf("{} {} dungeon IDs", isProtected ? "Protected" : "Unprotected", changed);
|
||||
return changed < dungeonIds.size() ? strf("{} ({} unchanged)", output, dungeonIds.size() - changed) : output;
|
||||
} catch (BadLexicalCast const&) {
|
||||
return strf("Could not parse /settileprotection parameters. Use /settileprotection <dungeonId> <protected>", argumentString);
|
||||
return strf("Could not parse /settileprotection parameters. Use /settileprotection <dungeonId...> <protected>", argumentString);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,14 +94,14 @@ void EffectEmitter::render(RenderCallback* renderCallback) {
|
||||
|
||||
Json EffectEmitter::toJson() const {
|
||||
return JsonObject{{"activeSources",
|
||||
jsonFromSet<pair<String, String>>(m_activeSources.get(),
|
||||
jsonFromSet<Set<pair<String, String>>>(m_activeSources.get(),
|
||||
[](pair<String, String> const& entry) {
|
||||
return JsonObject{{"position", entry.first}, {"source", entry.second}};
|
||||
})}};
|
||||
}
|
||||
|
||||
void EffectEmitter::fromJson(Json const& diskStore) {
|
||||
m_activeSources.set(jsonToSet<pair<String, String>>(diskStore.get("activeSources"),
|
||||
m_activeSources.set(jsonToSet<Set<pair<String, String>>>(diskStore.get("activeSources"),
|
||||
[](Json const& v) {
|
||||
return pair<String, String>{v.getString("position"), v.getString("source")};
|
||||
}));
|
||||
|
@ -415,7 +415,7 @@ struct WorldStartPacket : PacketBase<PacketType::WorldStart> {
|
||||
bool respawnInWorld;
|
||||
HashMap<DungeonId, float> dungeonIdGravity;
|
||||
HashMap<DungeonId, bool> dungeonIdBreathable;
|
||||
Set<DungeonId> protectedDungeonIds;
|
||||
StableHashSet<DungeonId> protectedDungeonIds;
|
||||
Json worldProperties;
|
||||
ConnectionId clientId;
|
||||
bool localInterpolationMode;
|
||||
|
@ -1435,7 +1435,7 @@ bool WorldClient::isTileProtected(Vec2I const& pos) const {
|
||||
if (!inWorld())
|
||||
return true;
|
||||
|
||||
auto tile = m_tileArray->tile(pos);
|
||||
auto const& tile = m_tileArray->tile(pos);
|
||||
return m_protectedDungeonIds.contains(tile.dungeonId);
|
||||
}
|
||||
|
||||
|
@ -367,7 +367,7 @@ private:
|
||||
|
||||
HashMap<DungeonId, float> m_dungeonIdGravity;
|
||||
HashMap<DungeonId, bool> m_dungeonIdBreathable;
|
||||
Set<DungeonId> m_protectedDungeonIds;
|
||||
StableHashSet<DungeonId> m_protectedDungeonIds;
|
||||
|
||||
HashMap<String, List<RpcPromiseKeeper<Vec2F>>> m_findUniqueEntityResponses;
|
||||
HashMap<Uuid, RpcPromiseKeeper<Json>> m_entityMessageResponses;
|
||||
|
@ -1190,10 +1190,14 @@ bool WorldServer::isTileProtected(Vec2I const& pos) const {
|
||||
if (!m_tileProtectionEnabled)
|
||||
return false;
|
||||
|
||||
auto tile = m_tileArray->tile(pos);
|
||||
auto const& tile = m_tileArray->tile(pos);
|
||||
return m_protectedDungeonIds.contains(tile.dungeonId);
|
||||
}
|
||||
|
||||
bool WorldServer::getTileProtection(DungeonId dungeonId) const {
|
||||
return m_protectedDungeonIds.contains(dungeonId);
|
||||
}
|
||||
|
||||
void WorldServer::setTileProtection(DungeonId dungeonId, bool isProtected) {
|
||||
bool updated = false;
|
||||
if (isProtected) {
|
||||
@ -1205,10 +1209,29 @@ void WorldServer::setTileProtection(DungeonId dungeonId, bool isProtected) {
|
||||
if (updated) {
|
||||
for (auto const& pair : m_clientInfo)
|
||||
pair.second->outgoingPackets.append(make_shared<UpdateTileProtectionPacket>(dungeonId, isProtected));
|
||||
}
|
||||
|
||||
Logger::info("Protected dungeonIds for world set to {}", m_protectedDungeonIds);
|
||||
}
|
||||
}
|
||||
|
||||
size_t WorldServer::setTileProtection(List<DungeonId> const& dungeonIds, bool isProtected) {
|
||||
List<PacketPtr> updates;
|
||||
updates.reserve(dungeonIds.size());
|
||||
for (auto const& dungeonId : dungeonIds)
|
||||
if (isProtected ? m_protectedDungeonIds.add(dungeonId) : m_protectedDungeonIds.remove(dungeonId))
|
||||
updates.append(make_shared<UpdateTileProtectionPacket>(dungeonId, isProtected));
|
||||
|
||||
if (updates.empty())
|
||||
return 0;
|
||||
|
||||
for (auto const& pair : m_clientInfo)
|
||||
pair.second->outgoingPackets.appendAll(updates);
|
||||
|
||||
auto newDungeonIds = m_protectedDungeonIds.values();
|
||||
sort(newDungeonIds);
|
||||
Logger::info("Protected dungeonIds for world set to {}", newDungeonIds);
|
||||
return updates.size();
|
||||
}
|
||||
|
||||
void WorldServer::setTileProtectionEnabled(bool enabled) {
|
||||
m_tileProtectionEnabled = enabled;
|
||||
@ -2345,7 +2368,7 @@ void WorldServer::readMetadata() {
|
||||
m_adjustPlayerStart = metadata.getBool("adjustPlayerStart");
|
||||
m_worldTemplate = make_shared<WorldTemplate>(metadata.get("worldTemplate"));
|
||||
m_centralStructure = WorldStructure(metadata.get("centralStructure"));
|
||||
m_protectedDungeonIds = jsonToSet<DungeonId>(metadata.get("protectedDungeonIds"), mem_fn(&Json::toUInt));
|
||||
m_protectedDungeonIds = jsonToSet<StableHashSet<DungeonId>>(metadata.get("protectedDungeonIds"), mem_fn(&Json::toUInt));
|
||||
m_worldProperties = metadata.getObject("worldProperties");
|
||||
m_spawner.setActive(metadata.getBool("spawningEnabled"));
|
||||
|
||||
|
@ -180,7 +180,10 @@ public:
|
||||
RpcPromise<Json> sendEntityMessage(Variant<EntityId, String> const& entity, String const& message, JsonArray const& args = {}) override;
|
||||
bool isTileProtected(Vec2I const& pos) const override;
|
||||
|
||||
bool getTileProtection(DungeonId dungeonId) const;
|
||||
void setTileProtection(DungeonId dungeonId, bool isProtected);
|
||||
// sets a provided list of DungeonIds all at once and returns how many were changed
|
||||
size_t setTileProtection(List<DungeonId> const& dungeonIds, bool isProtected);
|
||||
// used to globally, temporarily disable protection for certain operations
|
||||
void setTileProtectionEnabled(bool enabled);
|
||||
|
||||
@ -396,7 +399,7 @@ private:
|
||||
bool m_generatingDungeon;
|
||||
HashMap<DungeonId, float> m_dungeonIdGravity;
|
||||
HashMap<DungeonId, bool> m_dungeonIdBreathable;
|
||||
Set<DungeonId> m_protectedDungeonIds;
|
||||
StableHashSet<DungeonId> m_protectedDungeonIds;
|
||||
bool m_tileProtectionEnabled;
|
||||
|
||||
HashMap<Uuid, pair<ConnectionId, MVariant<ConnectionId, RpcPromiseKeeper<Json>>>> m_entityMessageResponses;
|
||||
|
Loading…
x
Reference in New Issue
Block a user