コード例 #1
0
bool CComponentManager::ComputeStateHash(std::string& outHash, bool quick)
{
	// Hash serialization: this includes the minimal data necessary to detect
	// differences in the state, and ignores things like counts and names

	// If 'quick' is set, this checks even fewer things, so that it will
	// be fast enough to run every turn but will typically detect any
	// out-of-syncs fairly soon

	CHashSerializer serializer(m_ScriptInterface);

	serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32);

	std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator cit = m_ComponentsByTypeId.begin();
	for (; cit != m_ComponentsByTypeId.end(); ++cit)
	{
		// In quick mode, only check unit positions
		if (quick && !(cit->first == CID_Position))
			continue;

		// Only emit component types if they have a component that will be serialized
		bool needsSerialization = false;
		for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)
		{
			// Don't serialize local entities
			if (ENTITY_IS_LOCAL(eit->first))
				continue;

			needsSerialization = true;
			break;
		}

		if (!needsSerialization)
			continue;

		serializer.NumberI32_Unbounded("component type id", cit->first);

		for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)
		{
			// Don't serialize local entities
			if (ENTITY_IS_LOCAL(eit->first))
				continue;

			serializer.NumberU32_Unbounded("entity id", eit->first);
			eit->second->Serialize(serializer);
		}
	}

	outHash = std::string((const char*)serializer.ComputeHash(), serializer.GetHashLength());

	// TODO: catch exceptions
	return true;
}
コード例 #2
0
bool CComponentManager::DumpDebugState(std::ostream& stream)
{
	CDebugSerializer serializer(m_ScriptInterface, stream);

	serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32);

	serializer.TextLine("entities:");

	// We want the output to be grouped by entity ID, so invert the CComponentManager data structures
	std::map<entity_id_t, std::map<ComponentTypeId, IComponent*> > components;
	std::map<ComponentTypeId, std::string> names;

	std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator ctit = m_ComponentsByTypeId.begin();
	for (; ctit != m_ComponentsByTypeId.end(); ++ctit)
	{
		std::map<entity_id_t, IComponent*>::const_iterator eit = ctit->second.begin();
		for (; eit != ctit->second.end(); ++eit)
		{
			components[eit->first][ctit->first] = eit->second;
		}
	}

	std::map<entity_id_t, std::map<ComponentTypeId, IComponent*> >::const_iterator cit = components.begin();
	for (; cit != components.end(); ++cit)
	{
		std::stringstream n;
		n << "- id: " << cit->first;
		serializer.TextLine(n.str());

		if (ENTITY_IS_LOCAL(cit->first))
			serializer.TextLine("  type: local");

		std::map<ComponentTypeId, IComponent*>::const_iterator ctit = cit->second.begin();
		for (; ctit != cit->second.end(); ++ctit)
		{
			std::stringstream n;
			n << "  " << LookupComponentTypeName(ctit->first) << ":";
			serializer.TextLine(n.str());
			serializer.Indent(4);
			ctit->second->Serialize(serializer);
			serializer.Dedent(4);
		}
		serializer.TextLine("");
	}

	// TODO: catch exceptions
	return true;
}
コード例 #3
0
bool CComponentManager::SerializeState(std::ostream& stream)
{
	CStdSerializer serializer(m_ScriptInterface, stream);

	// We don't serialize the destruction queue, since we'd have to be careful to skip local entities etc
	// and it's (hopefully) easier to just expect callers to flush the queue before serializing
	ENSURE(m_DestructionQueue.empty());

	serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32);
	serializer.NumberU32_Unbounded("next entity id", m_NextEntityId);

	uint32_t numComponentTypes = 0;

	std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator cit;

	for (cit = m_ComponentsByTypeId.begin(); cit != m_ComponentsByTypeId.end(); ++cit)
	{
		if (cit->second.empty())
			continue;

		numComponentTypes++;
	}

	serializer.NumberU32_Unbounded("num component types", numComponentTypes);

	for (cit = m_ComponentsByTypeId.begin(); cit != m_ComponentsByTypeId.end(); ++cit)
	{
		if (cit->second.empty())
			continue;

		std::map<ComponentTypeId, ComponentType>::const_iterator ctit = m_ComponentTypesById.find(cit->first);
		if (ctit == m_ComponentTypesById.end())
		{
			debug_warn(L"Invalid ctit"); // this should never happen
			return false;
		}

		serializer.StringASCII("name", ctit->second.name, 0, 255);

		std::map<entity_id_t, IComponent*>::const_iterator eit;

		// Count the components before serializing any of them
		uint32_t numComponents = 0;
		for (eit = cit->second.begin(); eit != cit->second.end(); ++eit)
		{
			// Don't serialize local entities
			if (ENTITY_IS_LOCAL(eit->first))
				continue;

			numComponents++;
		}

		// Emit the count
		serializer.NumberU32_Unbounded("num components", numComponents);

		// Serialize the components now
		for (eit = cit->second.begin(); eit != cit->second.end(); ++eit)
		{
			// Don't serialize local entities
			if (ENTITY_IS_LOCAL(eit->first))
				continue;

			serializer.NumberU32_Unbounded("entity id", eit->first);
			eit->second->Serialize(serializer);
		}
	}

	// TODO: catch exceptions
	return true;
}