Skip to content

Commit

Permalink
Create StandOnBlockEventEntry
Browse files Browse the repository at this point in the history
  • Loading branch information
gabber235 committed Dec 23, 2024
1 parent 95ef488 commit ee2537f
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ class InteractionContextBuilder {
put(this, value)
}

operator fun <T : Any> Ref<out Entry>.set(key: EntryContextKey, value: T) {
put(EntryInteractionContextKey<T>(this, key), value)
}

operator fun <T : Any> Entry.set(key: EntryContextKey, value: T) = ref().set(key, value)

fun build(): InteractionContext {
return InteractionContext(data)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.typewritermc.basic.entries.event

import com.typewritermc.core.books.pages.Colors
import com.typewritermc.core.entries.Query
import com.typewritermc.core.entries.Ref
import com.typewritermc.core.extension.annotations.*
import com.typewritermc.core.interaction.EntryContextKey
import com.typewritermc.core.interaction.context
import com.typewritermc.core.utils.point.Position
import com.typewritermc.core.utils.point.toBlockPosition
import com.typewritermc.engine.paper.entry.TriggerableEntry
import com.typewritermc.engine.paper.entry.entries.ConstVar
import com.typewritermc.engine.paper.entry.entries.EventEntry
import com.typewritermc.engine.paper.entry.entries.Var
import com.typewritermc.engine.paper.entry.triggerAllFor
import com.typewritermc.engine.paper.utils.toPosition
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.event.player.PlayerMoveEvent
import java.util.*
import kotlin.jvm.optionals.getOrNull
import kotlin.reflect.KClass

@Entry(
"stand_on_block_event",
"Triggered when a player stands on a block",
Colors.YELLOW,
"material-symbols:lightning-stand"
)
@ContextKeys(StandOnBlockContextKeys::class)
/**
* The `Stand On Block Event` is triggered when a player stands on a block.
*
* ## How could this be used?
* This could be used to send a player flying when the stand on a netherite block.
*/
class StandOnBlockEventEntry(
override val id: String = "",
override val name: String = "",
override val triggers: List<Ref<TriggerableEntry>> = emptyList(),
val block: Optional<Var<Material>> = Optional.empty(),
val position: Optional<Var<Position>> = Optional.empty(),
@Help(
"""
Cancel the event when triggered.
It will only cancel the event if all the criteria are met.
If set to false, it will not modify the event.
"""
)
val cancel: Var<Boolean> = ConstVar(false),
) : EventEntry

enum class StandOnBlockContextKeys(override val klass: KClass<*>) : EntryContextKey {
@KeyType(Position::class)
PLAYER_POSITION(Position::class),

@KeyType(Position::class)
BLOCK_POSITION(Position::class),

@KeyType(Material::class)
BLOCK_MATERIAL(Material::class),
}

fun hasBlock(location: Location, block: Material): Boolean {
return blockLocation(location, block) != null
}

fun blockLocation(location: Location, block: Material): Location? {
val loc = location.clone()
if (loc.block.type == block) return location
loc.add(0.0, 1.0, 0.0)
if (loc.block.type == block) return loc
loc.add(0.0, -1.0, 0.0)
if (loc.block.type == block) return loc
return null
}

@EntryListener(StandOnBlockEventEntry::class)
fun onStandOnBlock(event: PlayerMoveEvent, query: Query<StandOnBlockEventEntry>) {
if (!event.hasChangedBlock()) return
val player = event.player
val from = event.from
val to = event.to
val entries = query.findWhere {
if (it.block.isPresent) {
val block = it.block.get().get(player, context())
if (!(!hasBlock(from, block) && hasBlock(to, block))) return@findWhere false
}
if (it.position.isPresent) {
val position = it.position.get().get(player, context())
if (!(!position.sameBlock(from.toPosition()) && position.sameBlock(to.toPosition()))) return@findWhere false
}
true
}.toList()

entries.triggerAllFor(event.player, context {
entries.forEach { entry ->
entry[StandOnBlockContextKeys.PLAYER_POSITION] = to.toPosition()

val blockType = entry.block.getOrNull()?.get(player, context())
if (blockType != null) {
entry[StandOnBlockContextKeys.BLOCK_MATERIAL] = blockType
entry[StandOnBlockContextKeys.BLOCK_POSITION] = blockLocation(
to,
blockType
)?.toPosition()?.toBlockPosition() ?: to.toPosition().toBlockPosition()
} else if (to.block.type != Material.AIR) {
entry[StandOnBlockContextKeys.BLOCK_MATERIAL] = to.block.type
entry[StandOnBlockContextKeys.BLOCK_POSITION] = to.toPosition().toBlockPosition()
} else {
val blockBelow = to.clone().add(0.0, -1.0, 0.0)
entry[StandOnBlockContextKeys.BLOCK_MATERIAL] = blockBelow.block.type
entry[StandOnBlockContextKeys.BLOCK_POSITION] = blockBelow.toPosition().toBlockPosition()
}
}
})

if (entries.any { it.cancel.get(player) }) event.isCancelled = true
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ fun onEvent(event: SomeBukkitEvent, query: Query<ExampleEventEntry>) {
//<code-block:event_entry_with_context_keys>
@Entry("example_event_with_context_keys", "An example event entry with context keys.", Colors.YELLOW, "material-symbols:bigtop-updates")
// This tells Typewriter that this entry exposes some context
// highlight-next-line
@ContextKeys(ExampleContextKeys::class)
class ExampleEventEntryWithContextKeys(
override val id: String = "",
override val name: String = "",
override val triggers: List<Ref<TriggerableEntry>> = emptyList(),
) : EventEntry

// highlight-start
enum class ExampleContextKeys(override val klass: KClass<*>) : EntryContextKey {
// The two `String::class` have to be the same.
// The @KeyType is for the panel to know
Expand All @@ -61,17 +63,20 @@ enum class ExampleContextKeys(override val klass: KClass<*>) : EntryContextKey {
@KeyType(Position::class)
POSITION(Position::class)
}
// highlight-end

@EntryListener(ExampleEventEntryWithContextKeys::class)
fun onEventAddContext(event: SomeBukkitEvent, query: Query<ExampleEventEntryWithContextKeys>) {
val entries = query.find()
// highlight-start
entries.triggerAllFor(event.player) {
// Make sure these values are drawn from the event.
// You MUST supply all the context keys.
ExampleContextKeys.TEXT withValue "Hello World"
ExampleContextKeys.NUMBER withValue 42
ExampleContextKeys.POSITION withValue Position.ORIGIN
}
// highlight-end
}
//</code-block:event_entry_with_context_keys>

Expand Down

0 comments on commit ee2537f

Please sign in to comment.