Skip to content

Commit

Permalink
Add event supports: 'SERVER_TICK_TAIL', 'ENTITY_TICK', 'ENTITY_TICKED…
Browse files Browse the repository at this point in the history
…', 'ITEM_USED_ON_BLOCK'.

Make event arise before the source action.
  • Loading branch information
cao-awa committed Nov 18, 2024
1 parent 7a6fb8f commit 94f6355
Show file tree
Hide file tree
Showing 16 changed files with 329 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.github.cao.awa.conium.entity.event.tick

import com.github.cao.awa.conium.event.ConiumEvent
import com.github.cao.awa.conium.event.context.ConiumEventContext
import com.github.cao.awa.conium.event.context.ConiumEventContextBuilder.requires
import com.github.cao.awa.conium.event.type.ConiumEventArgTypes
import com.github.cao.awa.conium.event.type.ConiumEventType
import com.github.cao.awa.conium.parameter.ParameterSelective
import com.github.cao.awa.conium.parameter.ParameterSelective1
import com.github.cao.awa.conium.parameter.ParameterSelective4
import net.minecraft.entity.Entity
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.damage.DamageSource
import net.minecraft.world.World

class ConiumEntityTickEvent : ConiumEvent<ParameterSelective1<Boolean, Entity>>() {
override fun requirement(): ConiumEventContext<out ParameterSelective> {
return requires(
ConiumEventArgTypes.ENTITY
).attach(
forever(ConiumEventType.ENTITY_TICK)
).arise { identity, entity ->
noFailure(identity) {
it.arise(entity)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.github.cao.awa.conium.entity.event.tick

import com.github.cao.awa.conium.event.ConiumEvent
import com.github.cao.awa.conium.event.context.ConiumEventContext
import com.github.cao.awa.conium.event.context.ConiumEventContextBuilder.requires
import com.github.cao.awa.conium.event.type.ConiumEventArgTypes
import com.github.cao.awa.conium.event.type.ConiumEventType
import com.github.cao.awa.conium.parameter.ParameterSelective
import com.github.cao.awa.conium.parameter.ParameterSelective1
import net.minecraft.entity.Entity

class ConiumEntityTickedEvent : ConiumEvent<ParameterSelective1<Boolean, Entity>>() {
override fun requirement(): ConiumEventContext<out ParameterSelective> {
return requires(
ConiumEventArgTypes.ENTITY
).attach(
forever(ConiumEventType.ENTITY_TICKED)
).arise { identity, entity ->
noFailure(identity) {
it.arise(entity)
}
}
}
}
20 changes: 20 additions & 0 deletions src/main/java/com/github/cao/awa/conium/event/ConiumEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@ import com.github.cao.awa.conium.entity.event.damage.ConiumEntityDamageEvent
import com.github.cao.awa.conium.entity.event.damage.ConiumEntityDamagedEvent
import com.github.cao.awa.conium.entity.event.die.ConiumEntityDeadEvent
import com.github.cao.awa.conium.entity.event.die.ConiumEntityDieEvent
import com.github.cao.awa.conium.entity.event.tick.ConiumEntityTickEvent
import com.github.cao.awa.conium.entity.event.tick.ConiumEntityTickedEvent
import com.github.cao.awa.conium.event.context.ConiumEventContext
import com.github.cao.awa.conium.event.server.tick.ConiumServerTickEvent
import com.github.cao.awa.conium.event.server.tick.ConiumServerTickTailEvent
import com.github.cao.awa.conium.event.trigger.ListTriggerable
import com.github.cao.awa.conium.event.type.ConiumEventType
import com.github.cao.awa.conium.item.event.use.ConiumItemUseOnBlockEvent
import com.github.cao.awa.conium.item.event.use.ConiumItemUsedOnBlockEvent
import com.github.cao.awa.conium.parameter.ParameterSelective
import com.github.cao.awa.sinuatum.util.collection.CollectionFactor
import java.util.*
Expand All @@ -28,9 +32,15 @@ abstract class ConiumEvent<P : ParameterSelective> : ListTriggerable<P>() {
@JvmField
val itemUseOnBlockEvent = ConiumItemUseOnBlockEvent()

@JvmField
val itemUsedOnBlockEvent = ConiumItemUsedOnBlockEvent()

@JvmField
val serverTick = ConiumServerTickEvent()

@JvmField
val serverTickTail = ConiumServerTickTailEvent()

@JvmField
val breakingBlock = ConiumBreakingBlockEvent()

Expand All @@ -52,6 +62,12 @@ abstract class ConiumEvent<P : ParameterSelective> : ListTriggerable<P>() {
@JvmField
val usedBlock = ConiumUsedBlockEvent()

@JvmField
val entityTick = ConiumEntityTickEvent()

@JvmField
val entityTicked = ConiumEntityTickedEvent()

@JvmField
val entityDamage = ConiumEntityDamageEvent()

Expand Down Expand Up @@ -92,7 +108,9 @@ abstract class ConiumEvent<P : ParameterSelective> : ListTriggerable<P>() {
@JvmStatic
fun init() {
this.events[ConiumEventType.ITEM_USE_ON_BLOCK] = this.itemUseOnBlockEvent
this.events[ConiumEventType.ITEM_USED_ON_BLOCK] = this.itemUsedOnBlockEvent
this.events[ConiumEventType.SERVER_TICK] = this.serverTick
this.events[ConiumEventType.SERVER_TICK_TAIL] = this.serverTickTail

this.events[ConiumEventType.BREAKING_BLOCK] = this.breakingBlock
this.events[ConiumEventType.BREAK_BLOCK] = this.breakBlock
Expand All @@ -102,6 +120,8 @@ abstract class ConiumEvent<P : ParameterSelective> : ListTriggerable<P>() {
this.events[ConiumEventType.USE_BLOCK] = this.useBlock
this.events[ConiumEventType.USED_BLOCK] = this.usedBlock

this.events[ConiumEventType.ENTITY_TICK] = this.entityTick
this.events[ConiumEventType.ENTITY_TICKED] = this.entityTicked
this.events[ConiumEventType.ENTITY_DAMAGE] = this.entityDamage
this.events[ConiumEventType.ENTITY_DAMAGED] = this.entityDamaged
this.events[ConiumEventType.ENTITY_DIE] = this.entityDie
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ class ConiumEventContext<P : ParameterSelective?>(
return this
}

fun <X> put(arg: DynamicArgType<X>, value: X) {
fun <X> put(arg: DynamicArgType<X>, value: X): ConiumEventContext<P> {
this.args[arg] = value
return this
}

fun <X> dynamic(arg: DynamicArgType<X>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.github.cao.awa.conium.event.server.tick

import com.github.cao.awa.conium.event.ConiumEvent
import com.github.cao.awa.conium.event.context.ConiumEventContext
import com.github.cao.awa.conium.event.context.ConiumEventContextBuilder.requires
import com.github.cao.awa.conium.event.type.ConiumEventArgTypes
import com.github.cao.awa.conium.event.type.ConiumEventType
import com.github.cao.awa.conium.parameter.ParameterSelective
import com.github.cao.awa.conium.parameter.ParameterSelective1
import net.minecraft.server.MinecraftServer

class ConiumServerTickTailEvent : ConiumEvent<ParameterSelective1<Boolean, MinecraftServer>>() {
override fun requirement(): ConiumEventContext<out ParameterSelective> {
return requires(
ConiumEventArgTypes.SERVER,
).attach(
forever(ConiumEventType.SERVER_TICK_TAIL)
).arise { identity, server ->
noFailure(identity) {
it.arise(server)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ class ConiumEventType<I> {
@JvmField
val SERVER_TICK: ConiumEventType<MinecraftServer> = ConiumEventType()

@JvmField
val SERVER_TICK_TAIL: ConiumEventType<MinecraftServer> = ConiumEventType()

@JvmField
val ITEM_USE_ON_BLOCK: ConiumEventType<Item> = ConiumEventType()

@JvmField
val ITEM_USED_ON_BLOCK: ConiumEventType<Item> = ConiumEventType()

// Block.
/**
* The event where that block is be mining.
Expand Down Expand Up @@ -74,6 +80,12 @@ class ConiumEventType<I> {
@JvmField
val USED_BLOCK: ConiumEventType<Block> = ConiumEventType()

@JvmField
val ENTITY_TICK: ConiumEventType<EntityType<*>> = ConiumEventType()

@JvmField
val ENTITY_TICKED: ConiumEventType<EntityType<*>> = ConiumEventType()

// Entity.
@JvmField
val ENTITY_DAMAGE: ConiumEventType<EntityType<*>> = ConiumEventType()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.github.cao.awa.conium.item.event.use

import com.github.cao.awa.conium.event.context.ConiumEventContext
import com.github.cao.awa.conium.event.context.ConiumEventContextBuilder.requires
import com.github.cao.awa.conium.event.type.ConiumEventArgTypes
import com.github.cao.awa.conium.event.type.ConiumEventType
import com.github.cao.awa.conium.item.event.ConiumItemEvent
import com.github.cao.awa.conium.parameter.ParameterSelective
import com.github.cao.awa.conium.parameter.ParameterSelective3
import net.minecraft.item.ItemUsageContext
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.ActionResult

class ConiumItemUsedOnBlockEvent : ConiumItemEvent<ParameterSelective3<Boolean, ServerWorld, ItemUsageContext, ActionResult>>() {
override fun requirement(): ConiumEventContext<out ParameterSelective> {
return requires(
ConiumEventArgTypes.SERVER_WORLD,
ConiumEventArgTypes.ITEM_USAGE_CONTEXT,
ConiumEventArgTypes.ACTION_RESULT
).attach(
forever(ConiumEventType.ITEM_USED_ON_BLOCK)
).arise { identity, world, context, result ->
noFailure(identity) {
it.arise(
world,
context,
result
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.github.cao.awa.conium.block.event.use.ConiumUseBlockEvent;
import com.github.cao.awa.conium.block.event.use.ConiumUsedBlockEvent;

@Mixin(AbstractBlock.AbstractBlockState.class)
public abstract class BlockStateMixin {
Expand All @@ -27,28 +29,53 @@ public abstract class BlockStateMixin {
cancellable = true
)
public void breakingBlock(World world, BlockPos pos, PlayerEntity player, CallbackInfo ci) {
ConiumEventContext<?> eventContext = ConiumEvent.request(ConiumEventType.BREAKING_BLOCK);
// Request the breaking block context.
ConiumEventContext<?> breakingContext = ConiumEvent.request(ConiumEventType.BREAKING_BLOCK);

AbstractBlock.AbstractBlockState self = cast();

Block block = self.getBlock();

// Fill the context args.
eventContext.put(ConiumEventArgTypes.WORLD, world);
breakingContext.put(ConiumEventArgTypes.WORLD, world);

eventContext.put(ConiumEventArgTypes.PLAYER, player);
breakingContext.put(ConiumEventArgTypes.PLAYER, player);

eventContext.put(ConiumEventArgTypes.BLOCK_POS, pos);
eventContext.put(ConiumEventArgTypes.BLOCK_STATE, self);
breakingContext.put(ConiumEventArgTypes.BLOCK_POS, pos);
breakingContext.put(ConiumEventArgTypes.BLOCK_STATE, self);

if (eventContext.presaging(block)) {
eventContext.arising(block);
if (breakingContext.presaging(block)) {
breakingContext.arising(block);
} else {
// Cancel this event when presaging was rejected the event.
ci.cancel();
}
}

/**
* Redirect the 'onUse' calling of block using, make event context and trigger the event.
*
* @param instance the block instance
* @param blockState the block state of current context
* @param world the world of the block
* @param blockPos the position of the block
* @param playerEntity the user
* @param blockHitResult the hit result of the user using to block
*
* @see ConiumEventType#USE_BLOCK
* @see ConiumEventType#USED_BLOCK
* @see ConiumUseBlockEvent
* @see ConiumUsedBlockEvent
* @see Block
* @see BlockState
* @see ActionResult
*
* @author cao_awa
*
* @return the action result
*
* @since 1.0.0
*/
@Redirect(
method = "onUse",
at = @At(
Expand All @@ -57,27 +84,29 @@ public void breakingBlock(World world, BlockPos pos, PlayerEntity player, Callba
)
)
public ActionResult useBlock(Block instance, BlockState blockState, World world, BlockPos blockPos, PlayerEntity playerEntity, BlockHitResult blockHitResult) {
// Create using block context.
ConiumEventContext<?> usingContext = ConiumEvent.request(ConiumEventType.USE_BLOCK);
ConiumEventContext<?> usedContext = ConiumEvent.request(ConiumEventType.USED_BLOCK);

Block block = blockState.getBlock();

// Fill the context args.
usingContext.put(ConiumEventArgTypes.WORLD, world);

usingContext.put(ConiumEventArgTypes.PLAYER, playerEntity);

usingContext.put(ConiumEventArgTypes.BLOCK_POS, blockPos);
usingContext.put(ConiumEventArgTypes.BLOCK_STATE, blockState);
usingContext.put(ConiumEventArgTypes.BLOCK_HIT_RESULT, blockHitResult);

usedContext.inherit(usingContext);
usingContext.put(ConiumEventArgTypes.WORLD, world)
.put(ConiumEventArgTypes.PLAYER, playerEntity)
.put(ConiumEventArgTypes.BLOCK_POS, blockPos)
.put(ConiumEventArgTypes.BLOCK_STATE, blockState)
.put(ConiumEventArgTypes.BLOCK_HIT_RESULT, blockHitResult);

if (usingContext.presaging(block)) {
usingContext.arising(block);

// Invoke the 'onUse' method.
ActionResult result = ((AbstractBlockMixin) instance).invokeOnUse(blockState, world, blockPos, playerEntity, blockHitResult);

// Create used block context.
ConiumEventContext<?> usedContext = ConiumEvent.request(ConiumEventType.USED_BLOCK);
usedContext.inherit(usingContext);

// Used context has action result to acquire the result, this result not cancel or modifiable.
usedContext.put(ConiumEventArgTypes.ACTION_RESULT, result);

if (usedContext.presaging(block)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ public class ClientPlayerInteractionManagerMixin {
)
)
public void breakBlock(Block instance, WorldAccess world, BlockPos pos, BlockState state) {
ConiumEventContext<?> eventContext = ConiumEvent.request(ConiumEventType.BROKEN_BLOCK);
// Request the broken block event.
ConiumEventContext<?> brokenContext = ConiumEvent.request(ConiumEventType.BROKEN_BLOCK);

// Fill the context args.
eventContext.put(ConiumEventArgTypes.WORLD, (World) world);
brokenContext.put(ConiumEventArgTypes.WORLD, (World) world)
.put(ConiumEventArgTypes.BLOCK_POS, pos)
.put(ConiumEventArgTypes.BLOCK_STATE, state);

eventContext.put(ConiumEventArgTypes.BLOCK_POS, pos);
eventContext.put(ConiumEventArgTypes.BLOCK_STATE, state);

if (eventContext.presaging(instance)) {
if (brokenContext.presaging(instance)) {
// Only presaging state is true can be continues.
instance.onBroken(world, pos, state);
brokenContext.arising(instance);

eventContext.arising(instance);
instance.onBroken(world, pos, state);
}
}
}
Loading

0 comments on commit 94f6355

Please sign in to comment.