Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Soulwar ebb and flow changing map bug #3293

Closed
4 of 5 tasks
Kadeosek opened this issue Jan 28, 2025 · 2 comments
Closed
4 of 5 tasks

Soulwar ebb and flow changing map bug #3293

Kadeosek opened this issue Jan 28, 2025 · 2 comments
Labels
Priority: Critical Represents a risk to live servers Status: Pending Test This PR or Issue requires more testing Type: Bug Inconsistencies or issues which will cause an issue or problem for users or implementors.

Comments

@Kadeosek
Copy link

Priority

Critical

Area

  • Datapack
  • Source
  • Map
  • Other

What happened?

When executing soulwar if we are on ebb_and_flow at the time of map change, if anyone is there it freezes the entire server for 30 seconds and causes kicks

Image

What OS are you seeing the problem on?

Linux

Code of Conduct

  • I agree to follow this project's Code of Conduct
@Kadeosek Kadeosek added the Type: Bug Inconsistencies or issues which will cause an issue or problem for users or implementors. label Jan 28, 2025
@github-actions github-actions bot added Priority: Critical Represents a risk to live servers Status: Pending Test This PR or Issue requires more testing labels Jan 28, 2025
@XmasGame
Copy link

Image
on config.lua try to change maxpacketspersecond to 100

@Kadeosek
Copy link
Author

Kadeosek commented Jan 29, 2025

local function updateWaterPoolsSize()
	for _, pos in ipairs(SoulWarQuest.ebbAndFlow.poolPositions) do
		local tile = Tile(pos)
		if tile then
			local item = tile:getItemById(SoulWarQuest.ebbAndFlow.smallPoolId)
			if item then
				item:transform(SoulWarQuest.ebbAndFlow.MediumPoolId)
				-- Starts another timer for filling after an additional 40 seconds
				addEvent(function()
					local item = tile:getItemById(SoulWarQuest.ebbAndFlow.MediumPoolId)
					if item then
						item:transform(SoulWarQuest.ebbAndFlow.smallPoolId)
					end
				end, 40000) -- 40 seconds
			end
		end
	end
end

local function loadMapEmpty()
	local playersInZone = SoulWarQuest.ebbAndFlow.getZone():countPlayers()
	local monstersInZone = SoulWarQuest.ebbAndFlow.getZone():countMonsters()
	if playersInZone > 0 or monstersInZone > 0 then
		local creatures = SoulWarQuest.ebbAndFlow.getZone():getCreatures()
		for _, creature in ipairs(creatures) do
			local creatureMaster = creature:getMaster()
			local player = creature:getPlayer()
			if creature:isPlayer() or (creature:isMonster() and creatureMaster and creatureMaster:getPlayer()) then
				if creature:getPosition().z == 8 then
					if creature:isInBoatSpot() then
						local teleportPosition = creature:getPosition()
						teleportPosition.z = 9
						creature:teleportTo(teleportPosition)
						logger.trace("Teleporting player to down.")
					end
					if player then
						player:sendCreatureAppear()
					end
				end
			end
		end
	end

	Game.loadMap(SoulWarQuest.ebbAndFlow.mapsPath.empty)
	SoulWarQuest.ebbAndFlow.setLoadedEmptyMap(true)
	SoulWarQuest.ebbAndFlow.setActive(false)

	local updatePlayers = EventCallback("UpdatePlayersEmptyEbbFlowMap", true)
	function updatePlayers.mapOnLoad(mapPath)
		if mapPath ~= SoulWarQuest.ebbAndFlow.mapsPath.empty then
			return
		end

		SoulWarQuest.ebbAndFlow.updateZonePlayers()
	end

	updatePlayers:register()

	addEvent(function()
		-- Change the appearance of puddles to indicate the next filling
		updateWaterPoolsSize()
	end, 80000) -- 80 seconds
end

local function getDistance(pos1, pos2)
	return math.sqrt((pos1.x - pos2.x) ^ 2 + (pos1.y - pos2.y) ^ 2 + (pos1.z - pos2.z) ^ 2)
end

local function findNearestRoomPosition(playerPosition)
	local nearestPosition = nil
	local smallestDistance = nil
	for _, room in ipairs(SoulWarQuest.ebbAndFlow.centerRoomPositions) do
		local distance = getDistance(playerPosition, room.conor)
		if not smallestDistance or distance < smallestDistance then
			smallestDistance = distance
			nearestPosition = room.teleportPosition
		end
	end
	return nearestPosition
end

local function loadMapInundate()
	local playersInZone = SoulWarQuest.ebbAndFlow.getZone():countPlayers()
	local monstersInZone = SoulWarQuest.ebbAndFlow.getZone():countMonsters()
	if playersInZone > 0 or monstersInZone > 0 then
		local creatures = SoulWarQuest.ebbAndFlow.getZone():getCreatures()
		for _, creature in ipairs(creatures) do
			local creatureMaster = creature:getMaster()
			local player = creature:getPlayer()
			if creature:isPlayer() or (creature:isMonster() and creatureMaster and creatureMaster:getPlayer()) then
				local creaturePosition = creature:getPosition()
				if creaturePosition.z == 9 then
					if creature:isInBoatSpot() then
						local nearestCenterPosition = findNearestRoomPosition(creaturePosition)
						creature:teleportTo(nearestCenterPosition)
						logger.trace("Teleporting player to the near center position room and updating tile.")
					else
						creature:teleportTo(SoulWarQuest.ebbAndFlow.waitPosition)
						logger.trace("Teleporting player to wait position and updating tile.")
					end
					creaturePosition:sendMagicEffect(CONST_ME_TELEPORT)
				end
				if player then
					player:sendCreatureAppear()
				end
			end
		end
	end

	Game.loadMap(SoulWarQuest.ebbAndFlow.mapsPath.inundate)
	SoulWarQuest.ebbAndFlow.setLoadedEmptyMap(false)
	SoulWarQuest.ebbAndFlow.setActive(true)

	local updatePlayers = EventCallback("UpdatePlayersInundateEbbFlowMap", true)
	function updatePlayers.mapOnLoad(mapPath)
		if mapPath ~= SoulWarQuest.ebbAndFlow.mapsPath.inundate then
			return
		end

		SoulWarQuest.ebbAndFlow.updateZonePlayers()
	end

	updatePlayers:register()
end

local loadEmptyMap = GlobalEvent("SoulWarQuest.ebbAndFlow")

function loadEmptyMap.onStartup()
	Game.loadMap(SoulWarQuest.ebbAndFlow.mapsPath.ebbFlow)
	loadMapEmpty()
	SoulWarQuest.ebbAndFlow.updateZonePlayers()
end

loadEmptyMap:register()

local eddAndFlowInundate = GlobalEvent("eddAndFlowInundate")

function eddAndFlowInundate.onThink(interval, lastExecution)
	if SoulWarQuest.ebbAndFlow.isLoadedEmptyMap() then
		logger.trace("Map change to empty in {} minutes.", SoulWarQuest.ebbAndFlow.intervalChangeMap)
		loadMapInundate()
	elseif SoulWarQuest.ebbAndFlow.isActive() then
		logger.trace("Map change to inundate in {} minutes.", SoulWarQuest.ebbAndFlow.intervalChangeMap)
		loadMapEmpty()
	end

	return true
end

eddAndFlowInundate:interval(SoulWarQuest.ebbAndFlow.intervalChangeMap * 60 * 1000)
eddAndFlowInundate:register()

This script fixed freeze lag on players, but you make better i think ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Priority: Critical Represents a risk to live servers Status: Pending Test This PR or Issue requires more testing Type: Bug Inconsistencies or issues which will cause an issue or problem for users or implementors.
Projects
None yet
Development

No branches or pull requests

2 participants