Przeglądaj źródła

artifacts swap optimization

SoundSSGood 1 rok temu
rodzic
commit
ce3d407396

+ 1 - 1
client/NetPacksClient.cpp

@@ -301,7 +301,7 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
 		{
 			auto srcLoc = ArtifactLocation(pack.srcArtHolder, slotToMove.srcPos);
 			auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos);
-			MoveArtifact ma(&srcLoc, &dstLoc, false);
+			MoveArtifact ma(&srcLoc, &dstLoc, pack.askAssemble);
 			visitMoveArtifact(ma);
 		}
 	};

+ 6 - 0
lib/networkPacks/ArtifactLocation.h

@@ -31,6 +31,12 @@ struct ArtifactLocation
 		, creature(std::nullopt)
 	{
 	}
+	ArtifactLocation(const ObjectInstanceID id, const std::optional<SlotID> creatureSlot)
+		: artHolder(id)
+		, slot(ArtifactPosition::PRE_FIRST)
+		, creature(creatureSlot)
+	{
+	}
 
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{

+ 4 - 4
lib/networkPacks/NetPacksLib.cpp

@@ -1837,13 +1837,13 @@ void BulkMoveArtifacts::applyGs(CGameState * gs)
 			switch(operation)
 			{
 			case EBulkArtsOp::BULK_MOVE:
-				art->move(artSet, srcPos, *gs->getHero(dstArtHolder), slot.dstPos);
+				art->move(artSet, srcPos, *gs->getArtSet(ArtifactLocation(dstArtHolder, dstCreature)), slot.dstPos);
 				break;
 			case EBulkArtsOp::BULK_REMOVE:
 				art->removeFrom(artSet, srcPos);
 				break;
 			case EBulkArtsOp::BULK_PUT:
-				art->putAt(*gs->getHero(srcArtHolder), slot.dstPos);
+				art->putAt(*gs->getArtSet(ArtifactLocation(srcArtHolder, srcCreature)), slot.dstPos);
 				break;
 			default:
 				break;
@@ -1856,11 +1856,11 @@ void BulkMoveArtifacts::applyGs(CGameState * gs)
 		}
 	};
 	
-	auto * leftSet = gs->getArtSet(ArtifactLocation(srcArtHolder));
+	auto * leftSet = gs->getArtSet(ArtifactLocation(srcArtHolder, srcCreature));
 	if(swap)
 	{
 		// Swap
-		auto * rightSet = gs->getArtSet(ArtifactLocation(dstArtHolder));
+		auto * rightSet = gs->getArtSet(ArtifactLocation(dstArtHolder, dstCreature));
 		CArtifactFittingSet artFittingSet(leftSet->bearerType());
 
 		artFittingSet.artifactsWorn = rightSet->artifactsWorn;

+ 12 - 0
lib/networkPacks/PacksForClient.h

@@ -1064,17 +1064,25 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
 
 	ObjectInstanceID srcArtHolder;
 	ObjectInstanceID dstArtHolder;
+	std::optional<SlotID> srcCreature;
+	std::optional<SlotID> dstCreature;
 
 	BulkMoveArtifacts()
 		: srcArtHolder(ObjectInstanceID::NONE)
 		, dstArtHolder(ObjectInstanceID::NONE)
 		, swap(false)
+		, askAssemble(false)
+		, srcCreature(std::nullopt)
+		, dstCreature(std::nullopt)
 	{
 	}
 	BulkMoveArtifacts(const ObjectInstanceID srcArtHolder, const ObjectInstanceID dstArtHolder, bool swap)
 		: srcArtHolder(std::move(srcArtHolder))
 		, dstArtHolder(std::move(dstArtHolder))
 		, swap(swap)
+		, askAssemble(false)
+		, srcCreature(std::nullopt)
+		, dstCreature(std::nullopt)
 	{
 	}
 
@@ -1083,6 +1091,7 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
 	std::vector<LinkedSlots> artsPack0;
 	std::vector<LinkedSlots> artsPack1;
 	bool swap;
+	bool askAssemble;
 
 	void visitTyped(ICPackVisitor & visitor) override;
 
@@ -1092,7 +1101,10 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
 		h & artsPack1;
 		h & srcArtHolder;
 		h & dstArtHolder;
+		h & srcCreature;
+		h & dstCreature;
 		h & swap;
+		h & askAssemble;
 	}
 };
 

+ 39 - 41
server/CGameHandler.cpp

@@ -2667,19 +2667,18 @@ bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
 // Function moves artifact from src to dst. If dst is not a backpack and is already occupied, old dst art goes to backpack and is replaced.
 bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst)
 {
-	ArtifactLocation srcLoc = src, dstLoc = dst;
-	const auto srcArtSet = getArtSet(srcLoc);
-	const auto dstArtSet = getArtSet(dstLoc);
+	const auto srcArtSet = getArtSet(src);
+	const auto dstArtSet = getArtSet(dst);
 	assert(srcArtSet);
 	assert(dstArtSet);
 
 	// Make sure exchange is even possible between the two heroes.
-	if(!isAllowedExchange(srcLoc.artHolder, dstLoc.artHolder))
+	if(!isAllowedExchange(src.artHolder, dst.artHolder))
 		COMPLAIN_RET("That heroes cannot make any exchange!");
 
-	const auto srcArtifact = srcArtSet->getArt(srcLoc.slot);
-	const auto dstArtifact = dstArtSet->getArt(dstLoc.slot);
-	const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dstLoc.slot) : false;
+	const auto srcArtifact = srcArtSet->getArt(src.slot);
+	const auto dstArtifact = dstArtSet->getArt(dst.slot);
+	const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dst.slot) : false;
 
 	if(srcArtifact == nullptr)
 		COMPLAIN_RET("No artifact to move!");
@@ -2688,55 +2687,54 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca
 
 	// Check if src/dest slots are appropriate for the artifacts exchanged.
 	// Moving to the backpack is always allowed.
-	if((!srcArtifact || !isDstSlotBackpack) && srcArtifact && !srcArtifact->canBePutAt(dstArtSet, dstLoc.slot, true))
+	if((!srcArtifact || !isDstSlotBackpack) && srcArtifact && !srcArtifact->canBePutAt(dstArtSet, dst.slot, true))
 		COMPLAIN_RET("Cannot move artifact!");
 
-	auto srcSlotInfo = srcArtSet->getSlot(srcLoc.slot);
-	auto dstSlotInfo = dstArtSet->getSlot(dstLoc.slot);
+	auto srcSlotInfo = srcArtSet->getSlot(src.slot);
+	auto dstSlotInfo = dstArtSet->getSlot(dst.slot);
 
 	if((srcSlotInfo && srcSlotInfo->locked) || (dstSlotInfo && dstSlotInfo->locked))
 		COMPLAIN_RET("Cannot move artifact locks.");
 
 	if(isDstSlotBackpack && srcArtifact->artType->isBig())
 		COMPLAIN_RET("Cannot put big artifacts in backpack!");
-	if(srcLoc.slot == ArtifactPosition::MACH4 || dstLoc.slot == ArtifactPosition::MACH4)
+	if(src.slot == ArtifactPosition::MACH4 || dst.slot == ArtifactPosition::MACH4)
 		COMPLAIN_RET("Cannot move catapult!");
+	if(isDstSlotBackpack && !ArtifactUtils::isBackpackFreeSlots(dstArtSet))
+		COMPLAIN_RET("Backpack is full!");
 
-	if(isDstSlotBackpack)
+	auto dstSlot = std::min(dst.slot, ArtifactPosition(ArtifactPosition::BACKPACK_START + dstArtSet->artifactsInBackpack.size()));
+
+	if(src.slot == dstSlot && src.artHolder == dst.artHolder)
+		COMPLAIN_RET("Won't move artifact: Dest same as source!");
+	
+	BulkMoveArtifacts ma(src.artHolder, dst.artHolder, false);
+	ma.srcCreature = src.creature;
+	ma.dstCreature = dst.creature;
+	
+	// Check if dst slot is occupied
+	if(!isDstSlotBackpack && dstArtifact)
 	{
-		if(!ArtifactUtils::isBackpackFreeSlots(dstArtSet))
-			COMPLAIN_RET("Backpack is full!");
-		vstd::amin(dstLoc.slot, ArtifactPosition::BACKPACK_START + dstArtSet->artifactsInBackpack.size());
+		// Previous artifact must be removed
+		ma.artsPack1.push_back(BulkMoveArtifacts::LinkedSlots(dstSlot, src.slot));
+		ma.swap = true;
 	}
 
-	if(!(srcLoc.slot == ArtifactPosition::TRANSITION_POS && dstLoc.slot == ArtifactPosition::TRANSITION_POS))
+	try
 	{
-		if(srcLoc.slot == dstLoc.slot && srcLoc.artHolder == dstLoc.artHolder)
-			COMPLAIN_RET("Won't move artifact: Dest same as source!");
-
-		// Check if dst slot is occupied
-		if(!isDstSlotBackpack && dstArtifact)
-		{
-			// Previous artifact must be removed first
-			moveArtifact(dstLoc, ArtifactLocation(dstLoc.artHolder, ArtifactPosition::TRANSITION_POS));
-		}
-
-		try
-		{
-			auto hero = getHero(dst.artHolder);
-			if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dstLoc.slot))
-				giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
-		}
-		catch(const std::bad_variant_access &)
-		{
-			// object other than hero received an art - ignore
-		}
-
-		MoveArtifact ma(&srcLoc, &dstLoc);
-		if(srcLoc.artHolder == dstLoc.artHolder)
-			ma.askAssemble = false;
-		sendAndApply(&ma);
+		auto hero = getHero(dst.artHolder);
+		if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dstSlot))
+			giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
 	}
+	catch(const std::bad_variant_access &)
+	{
+		// object other than hero received an art - ignore
+	}
+
+	ma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(src.slot, dstSlot));
+	if(src.artHolder != dst.artHolder)
+		ma.askAssemble = true;
+	sendAndApply(&ma);
 	return true;
 }