@ -1,4 +1,4 @@
package net.deliciousreya.minecraftportal
package net.deliciousreya.minecraftportal.model
import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import com.google.common.collect.ImmutableMap
@ -7,8 +7,11 @@ import org.bukkit.Location
import org.bukkit.block.Block
import org.bukkit.block.Block
import org.bukkit.util.Vector
import org.bukkit.util.Vector
import net.deliciousreya.minecraftportal.extensions.*
import net.deliciousreya.minecraftportal.extensions.*
import net.deliciousreya.minecraftportal.proto.PortalSaveDataProtos
import org.bukkit.Material
import org.bukkit.Material
import org.bukkit.Material.*
import org.bukkit.Material.*
import org.bukkit.Particle
import org.bukkit.Sound
import org.bukkit.block.BlockFace
import org.bukkit.block.BlockFace
import org.bukkit.material.Directional
import org.bukkit.material.Directional
@ -25,11 +28,15 @@ val MINERAL_TYPES: ImmutableMap<Material, Material> = ImmutableMap.Builder<Mater
val DOOR _TYPES : ImmutableSet < Material > = ImmutableSet . of ( ACACIA _DOOR , BIRCH _DOOR , DARK _OAK _DOOR , IRON _DOOR , JUNGLE _DOOR , OAK _DOOR , SPRUCE _DOOR )
val DOOR _TYPES : ImmutableSet < Material > = ImmutableSet . of ( ACACIA _DOOR , BIRCH _DOOR , DARK _OAK _DOOR , IRON _DOOR , JUNGLE _DOOR , OAK _DOOR , SPRUCE _DOOR )
fun findPortalFrameConnectedTo ( block : Block , state : PortalFrame . State ) : PortalFrame ? {
fun findPortalFrameConnectedTo ( block : Block , state : PortalFrame . State ) : PortalFrame ? {
when {
when {
block . type in state . glassBlocks -> for ( direction in PortalFrame . EntranceDirection . values ( ) ) {
block . type in state . glassBlocks -> for ( direction in PortalFrame . EntranceDirection . values ( ) ) {
for ( vector in direction . glassOffsets ) {
for ( vector in direction . glassOffsets ) {
val scanResult = checkPortalFrameAt ( block . location . subtract ( vector ) , direction , state )
val scanResult = checkPortalFrameAt (
block . location . subtract ( vector ) ,
direction ,
state
)
if ( scanResult != null ) {
if ( scanResult != null ) {
return scanResult
return scanResult
}
}
@ -37,14 +44,22 @@ fun findPortalFrameConnectedTo(block:Block, state:PortalFrame.State): PortalFram
}
}
block . type in state . doorBlocks -> for ( direction in PortalFrame . EntranceDirection . values ( ) ) {
block . type in state . doorBlocks -> for ( direction in PortalFrame . EntranceDirection . values ( ) ) {
for ( vector in direction . doorOffsets ) {
for ( vector in direction . doorOffsets ) {
val scanResult = checkPortalFrameAt ( block . location . subtract ( vector ) , direction , state )
val scanResult = checkPortalFrameAt (
block . location . subtract ( vector ) ,
direction ,
state
)
if ( scanResult != null ) {
if ( scanResult != null ) {
return scanResult
return scanResult
}
}
}
}
}
}
block . type in state . mineralBlocks -> for ( direction in PortalFrame . EntranceDirection . values ( ) ) {
block . type in state . mineralBlocks -> for ( direction in PortalFrame . EntranceDirection . values ( ) ) {
val scanResult = checkPortalFrameAt ( block . location . subtract ( direction . mineralOffset ) , direction , state )
val scanResult = checkPortalFrameAt (
block . location . subtract ( direction . mineralOffset ) ,
direction ,
state
)
if ( scanResult != null ) {
if ( scanResult != null ) {
return scanResult
return scanResult
}
}
@ -54,7 +69,7 @@ fun findPortalFrameConnectedTo(block:Block, state:PortalFrame.State): PortalFram
}
}
/** Detects whether there is a portal frame in the given state at the given location, extending in the given direction. */
/** Detects whether there is a portal frame in the given state at the given location, extending in the given direction. */
fun checkPortalFrameAt ( location : Location , direction : PortalFrame . EntranceDirection , state : PortalFrame . State ) : PortalFrame ? {
fun checkPortalFrameAt ( location : Location , direction : PortalFrame . EntranceDirection , state : PortalFrame . State ) : PortalFrame ? {
val mineral = ( location + direction . mineralOffset ) . block
val mineral = ( location + direction . mineralOffset ) . block
if ( mineral . type !in state . mineralBlocks ) {
if ( mineral . type !in state . mineralBlocks ) {
return null
return null
@ -74,20 +89,31 @@ fun checkPortalFrameAt(location:Location, direction:PortalFrame.EntranceDirectio
return PortalFrame ( location , direction )
return PortalFrame ( location , direction )
}
}
fun PortalSaveDataProtos . Portal . Direction . toDirection ( ) : PortalFrame . EntranceDirection {
for ( direction in PortalFrame . EntranceDirection . values ( ) ) {
if ( direction . protoEnum == this ) {
return direction
}
}
throw IllegalStateException ( " Bad enum value: $this " )
}
/** Information about a portal frame. */
/** Information about a portal frame. */
data class PortalFrame ( val lowerLeftFrontCorner : Location , val direction : EntranceDirection ) {
data class PortalFrame ( val lowerLeftFrontCorner : Location , val direction : EntranceDirection ) {
enum class State ( val glassBlocks : ImmutableSet < Material > , val doorBlocks : ImmutableSet < Material > , val mineralBlocks : ImmutableSet < Material > ) {
enum class State ( val glassBlocks : ImmutableSet < Material > , val doorBlocks : ImmutableSet < Material > , val mineralBlocks : ImmutableSet < Material > ) {
ACTIVE ( ImmutableSet . copyOf ( MINERAL _TYPES . values ) , DOOR _TYPES , ImmutableSet . copyOf ( MINERAL _TYPES . keys ) ) ,
ACTIVE ( ImmutableSet . copyOf ( MINERAL _TYPES . values ) ,
INACTIVE ( ImmutableSet . of ( GLASS ) , DOOR _TYPES , ImmutableSet . copyOf ( MINERAL _TYPES . keys ) ) ;
DOOR _TYPES , ImmutableSet . copyOf ( MINERAL _TYPES . keys ) ) ,
INACTIVE ( ImmutableSet . of ( GLASS ) ,
DOOR _TYPES , ImmutableSet . copyOf ( MINERAL _TYPES . keys ) ) ;
val allValidBlocks = ImmutableSet . Builder < Material > ( ) . addAll ( glassBlocks ) . addAll ( doorBlocks ) . addAll ( mineralBlocks ) . build ( )
val allValidBlocks : ImmutableSet < Material > = ImmutableSet . Builder < Material > ( ) . addAll ( glassBlocks ) . addAll ( doorBlocks ) . addAll ( mineralBlocks ) . build ( )
}
}
/** The direction along which a portal frame extends. */
/** The direction along which a portal frame extends. */
enum class EntranceDirection ( toRight : Vector , toBack : Vector , val doorDirection : BlockFace ) {
enum class EntranceDirection ( toRight : Vector , toBack : Vector , val doorDirection : BlockFace , val protoEnum : PortalSaveDataProtos . Portal . Direction ) {
NORTH ( Vector ( 1 , 0 , 0 ) , Vector ( 0 , 0 , 1 ) , BlockFace . NORTH ) ,
NORTH ( Vector ( 1 , 0 , 0 ) , Vector ( 0 , 0 , 1 ) , BlockFace . NORTH , PortalSaveDataProtos . Portal . Direction . NORTH ) ,
SOUTH ( Vector ( 1 , 0 , 0 ) , Vector ( 0 , 0 , - 1 ) , BlockFace . SOUTH ) ,
SOUTH ( Vector ( 1 , 0 , 0 ) , Vector ( 0 , 0 , - 1 ) , BlockFace . SOUTH , PortalSaveDataProtos . Portal . Direction . SOUTH ) ,
EAST ( Vector ( 0 , 0 , 1 ) , Vector ( - 1 , 0 , 0 ) , BlockFace . EAST ) ,
EAST ( Vector ( 0 , 0 , 1 ) , Vector ( - 1 , 0 , 0 ) , BlockFace . EAST , PortalSaveDataProtos . Portal . Direction . EAST ) ,
WEST ( Vector ( 0 , 0 , 1 ) , Vector ( 1 , 0 , 0 ) , BlockFace . WEST ) ;
WEST ( Vector ( 0 , 0 , 1 ) , Vector ( 1 , 0 , 0 ) , BlockFace . WEST , PortalSaveDataProtos . Portal . Direction . WEST ) ;
val glassOffsets : ImmutableList < Vector > = ImmutableList . of (
val glassOffsets : ImmutableList < Vector > = ImmutableList . of (
// check corners first:
// check corners first:
@ -138,6 +164,10 @@ data class PortalFrame(val lowerLeftFrontCorner: Location, val direction: Entran
Vector ( 0 , 1 , 0 ) + toRight ,
Vector ( 0 , 1 , 0 ) + toRight ,
Vector ( 0 , 2 , 0 ) + toRight
Vector ( 0 , 2 , 0 ) + toRight
)
)
fun toProto ( ) : PortalSaveDataProtos . Portal . Direction {
return this . protoEnum
}
}
}
val portalCenter = lowerLeftFrontCorner + direction . doorOffsets [ 0 ]
val portalCenter = lowerLeftFrontCorner + direction . doorOffsets [ 0 ]
@ -146,16 +176,22 @@ data class PortalFrame(val lowerLeftFrontCorner: Location, val direction: Entran
return direction . doorOffsets . any { offset -> location . block . location - offset == lowerLeftFrontCorner }
return direction . doorOffsets . any { offset -> location . block . location - offset == lowerLeftFrontCorner }
}
}
fun color ( ) {
val mineral = ( lowerLeftFrontCorner + direction . mineralOffset ) . block . type
fun activate ( ) {
val mineral = ( lowerLeftFrontCorner + direction . mineralOffset ) . block
val mineral = ( lowerLeftFrontCorner + direction . mineralOffset ) . block
for ( offset in direction . glassOffsets ) {
for ( offset in direction . glassOffsets ) {
( lowerLeftFrontCorner + offset ) . block . type = MINERAL _TYPES . getOrDefault ( mineral . type , BROWN _STAINED _GLASS )
( lowerLeftFrontCorner + offset ) . block . type = MINERAL _TYPES . getOrDefault ( mineral . type , BROWN _STAINED _GLASS )
}
}
portalCenter . world ?. playSound ( portalCenter , Sound . BLOCK _BEACON _ACTIVATE , 20f , 1f )
portalCenter . world ?. spawnParticle ( Particle . SPELL , portalCenter , 40 )
}
}
fun uncolor ( ) {
fun deactivate ( ) {
for ( offset in direction . glassOffsets ) {
for ( offset in direction . glassOffsets ) {
( lowerLeftFrontCorner + offset ) . block . type = GLASS
( lowerLeftFrontCorner + offset ) . block . type = GLASS
}
}
portalCenter . world ?. playSound ( portalCenter , Sound . BLOCK _BEACON _DEACTIVATE , 20f , 1f )
portalCenter . world ?. spawnParticle ( Particle . SMOKE _NORMAL , portalCenter , 40 )
}
}
}
}