All Downloads are FREE. Search and download functionalities are using the official Maven repository.

walkmc.event.RegionEvent.kt Maven / Gradle / Ivy

The newest version!
package walkmc.event

import com.sk89q.worldguard.protection.regions.*
import org.bukkit.*
import org.bukkit.entity.*
import org.bukkit.event.player.*
import walkmc.*
import walkmc.annotation.*
import walkmc.extensions.*
import java.util.*

enum class Movement {
	MOVE, TELEPORT, CONNECT, DISCONNECT, SPAWN;
	
	val isMove get() = this == MOVE
	val isTeleport get() = this == TELEPORT
	val isConnect get() = this == CONNECT
	val isDisconnect get() = this == DISCONNECT
	val isSpawn get() = this == SPAWN
	val isByMovement get() = isMove || isTeleport
	val isByConnection get() = isConnect || isDisconnect
}


class RegionEnterEvent(
	val player: Player,
	val region: ProtectedRegion,
	val movement: Movement,
) : CancellableEvent() {
	val world: World = player.world
	val location: Location = player.location
}


class RegionLeaveEvent(
	val player: Player,
	val region: ProtectedRegion,
	val movement: Movement,
) : CancellableEvent() {
	val world: World = player.world
	val location: Location = player.location
}


@ResourceMarker
object RegionResource : Resource(Service) {
	val regionCache = cacheOf>()
	
	@Component
	fun start() {
		subscribe {
			updateRegion(player, player.location, Movement.CONNECT)
		}
		
		subscribe {
			updateRegion(player, respawnLocation, Movement.SPAWN)
		}
		
		subscribe {
			isCancelled = updateRegion(player, to, Movement.TELEPORT)
		}
		
		subscribe {
			isCancelled = updateRegion(player, to, Movement.MOVE)
		}
		
		subscribe {
			runCatching {
				regionCache -= player.uuid
				for (region in player.location.regions())
					RegionLeaveEvent(player, region, Movement.DISCONNECT).call()
			}
		}
		
		subscribe {
			runCatching {
				regionCache -= player.uuid
				for (region in player.location.regions())
					RegionLeaveEvent(player, region, Movement.DISCONNECT).call()
			}
		}
	}
	
	
	private fun updateRegion(player: Player, location: Location, movement: Movement): Boolean {
		return runCatching {
			val manager = location.world.regionManager()
			val cachedRegions = regionCache[player.uuid] ?: hashSetOf()
			val applicableRegions = manager.getApplicableRegions(location)
			val oldRegions = HashSet(cachedRegions)
			
			// enter
			for (region in applicableRegions) {
				if (region !in cachedRegions) {
					val event = RegionEnterEvent(player, region, movement)
					event.call()
					if (event.isCancelled) {
						cachedRegions.clear()
						cachedRegions += oldRegions
						return true
					}
					cachedRegions += region
				}
			}
			
			// leave
			for (region in cachedRegions) {
				if (region !in applicableRegions) {
					if (manager.getRegion(region.id) != region) {
						cachedRegions -= region
						continue
					}
					
					val event = RegionLeaveEvent(player, region, movement)
					event.call()
					if (event.isCancelled) {
						cachedRegions.clear()
						cachedRegions += oldRegions
						return true
					}
					
					cachedRegions -= region
				}
			}
			
			regionCache[player.uuid] = cachedRegions
			false
		}.getOrDefault(false)
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy