1
0
Fork 0
The portal creating plugin for Minecraft.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
8.1 KiB

package net.deliciousreya.minecraftportal
import com.destroystokyo.paper.event.block.BlockDestroyEvent
import net.deliciousreya.minecraftportal.extensions.COLOR_NAME_MAPPING
import net.deliciousreya.minecraftportal.extensions.MID_BLOCK
import net.deliciousreya.minecraftportal.extensions.plus
import net.deliciousreya.minecraftportal.model.DOOR_TYPES
import net.deliciousreya.minecraftportal.model.PortalDataStore
import net.deliciousreya.minecraftportal.model.PortalFrame
import net.deliciousreya.minecraftportal.model.findPortalFrameConnectedTo
import org.bukkit.Material
import org.bukkit.Sound
import org.bukkit.block.Block
import org.bukkit.block.data.type.Door
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
import org.bukkit.entity.Entity
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.block.*
import org.bukkit.event.entity.EntityChangeBlockEvent
import org.bukkit.event.entity.EntityExplodeEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.potion.PotionEffectType
import java.lang.IllegalStateException
class MinecraftPortalPlugin() : JavaPlugin(), Listener
{
val portals: PortalDataStore = PortalDataStore()
override fun onEnable() {
super.onEnable()
if (!dataFolder.isDirectory) {
if (dataFolder.exists()) {
throw IllegalStateException("Data folder already exists but not as a directory")
} else {
logger.info("Setting up in newly created data directory $dataFolder")
dataFolder.mkdirs()
}
} else {
logger.info("Setting up in data directory $dataFolder")
}
portals.loadFromAndAutoSaveTo(server, dataFolder.resolve("portal_data.binproto"), dataFolder.resolve("portal_data.binproto.bak"))
portals.validateWorldOnStartup(logger)
portals.launchEffectsOnStartup(this)
val setColorCommand = getCommand("portalcolor") ?: throw IllegalStateException("portalcolor command was missing")
setColorCommand.setExecutor { sender, _, _, args -> onPortalColor(sender, args) }
server.pluginManager.registerEvents(this, this)
}
override fun onDisable() {
super.onDisable()
portals.unload()
}
fun onPortalColor(sender: CommandSender, args: Array<String>): Boolean {
val argsList = if (args.isEmpty() && sender is Player) {
listOf("show")
} else {
args.asList()
}
if (argsList.isEmpty() || args.size > 2) {
sender.sendMessage("You must specify one or two arguments.")
return false
}
val colorString = if (argsList.size == 1) {
argsList[0]
} else {
argsList[1]
}
val playerString = when {
argsList.size == 2 -> {
argsList[0]
}
sender is Player -> {
sender.name
}
else -> {
null
}
}
if (playerString == null) {
sender.sendMessage("Only players can set their own color with the one-arg form.")
return false
}
if (colorString == "show") {
if (sender is Player && playerString == sender.name) {
sender.sendMessage("Portals you create are marked with ${portals.getColorFor(playerString).name}.")
} else {
sender.sendMessage("Portals created by $playerString are marked with ${portals.getColorFor(playerString).name}.")
}
return true
}
if (playerString != sender.name && !sender.isOp) {
sender.sendMessage("Only ops can set other players' colors with the two-arg form.")
return false
}
val color = COLOR_NAME_MAPPING[colorString]
if (color == null) {
sender.sendMessage("I don't know that color. Are you sure it's one of the dye colors?")
return false
}
portals.setColorFor(playerString, color)
if (sender is Player && playerString == sender.name) {
sender.sendMessage("Your portals will now be marked with ${portals.getColorFor(playerString).name}.")
} else {
sender.sendMessage("Portals created by $playerString will now be marked with ${portals.getColorFor(playerString).name}")
}
return true
}
@EventHandler
fun onBlockPlaced(e: BlockPlaceEvent) {
e.player.name
if (e.block.type in PortalFrame.State.INACTIVE.allValidBlocks) {
val newPortal = findPortalFrameConnectedTo(
e.block,
PortalFrame.State.INACTIVE
)
if (newPortal != null) {
if (newPortal.color == Material.GLASS) {
newPortal.color = portals.getColorFor(e.player.name)
}
val replacedPortal = portals.activateAndReplacePortal(newPortal)
val otherPortal = portals.getOtherPortal(newPortal)
newPortal.activate()
replacedPortal?.deactivate()
if (otherPortal != null) {
newPortal.open()
otherPortal.open()
portals.startEffectsFor(newPortal, this)
} else {
newPortal.ejectEntities()
newPortal.close()
}
}
}
}
@EventHandler
fun onBlockDestroy(e:BlockDestroyEvent) {
onDestroyedBlock(e.block)
}
@EventHandler
fun onEntityExplosion(e:EntityExplodeEvent) {
e.blockList().forEach(::onDestroyedBlock)
}
@EventHandler
fun onBlockExplosion(e:BlockExplodeEvent) {
onDestroyedBlock(e.block)
e.blockList().forEach(::onDestroyedBlock)
}
@EventHandler
fun onBlockBurn(e: BlockBurnEvent) {
onDestroyedBlock(e.block)
}
@EventHandler
fun onBlockFade(e: BlockFadeEvent) {
onDestroyedBlock(e.block)
}
@EventHandler
fun onBlockBreak(e:BlockBreakEvent) {
onDestroyedBlock(e.block)
}
@EventHandler
fun onEntityChangeBlock(e: EntityChangeBlockEvent) {
onDestroyedBlock(e.block)
}
@EventHandler
fun onPlayerInteract(e: PlayerInteractEvent) {
if (e.clickedBlock == null || e.action != Action.RIGHT_CLICK_BLOCK) {
return
}
val block = e.clickedBlock!!
if(block.type !in DOOR_TYPES) {
return
}
val door = block.blockData as Door
val location = e.player.location
// i.e., is the door part of a portal and are we standing in that portal?
val portal = portals.isLocationInPortalChamber(block.location + MID_BLOCK) ?: return
if (location.toVector() !in portal.portalInsideBoundingBox) {
e.isCancelled = true
return
}
if (!door.isOpen) {
portals.stopTeleporting(portal)
} else {
portals.startTeleporting(portal, this)
}
}
//fun onPlayerMove(e: PlayerMoveEvent) {
//val player = e.player
//val oldLocation = e.from
//val portal = portals.isLocationInPortalChamber(oldLocation) ?: return
//val newLocation = e.to ?: return
//if (oldLocation.world != newLocation.world || oldLocation.toVector() !in portal.portalInsideBoundingBox) {
// TODO: cancelTeleportFor(player)
//}
//}
fun onDestroyedBlock(block: Block) {
if (block.type !in PortalFrame.State.ACTIVE.allValidBlocks) {
return
}
val oldPortal = findPortalFrameConnectedTo(
block,
PortalFrame.State.ACTIVE
)
if (oldPortal != null) {
val otherPortal = portals.getOtherPortal(oldPortal)
portals.deactivatePortal(oldPortal)
oldPortal.deactivate()
if (otherPortal != null) {
otherPortal.ejectEntities()
otherPortal.close()
}
}
}
}