βŒ›Events System

The events system allow for a user to add custom logic to a BB block.

Event Inputs

Callback functions can be added to objects using the NetEventDispatcher class. The function is called by the engine when a specific type of event occurs in-game. Events can either be server-sided or client-sided. The β€œside” of an event determines who runs the callback function: either the client who triggered the event, or the server when any client triggers an event. Prefer to use server-sided events when possible, because the server host is able to automatically synchronise information between all players. Client-sided events are usually only needed when split-second timing is required, for example jump blocks in a platform game or firing a weapon.

NetEventDispatcher.prototype.addEventListener(NET_SERVER or NET_CLIENT, "eventname", function(e)
{
	//callback
	console.log(e);
});

Block event listeners - dispatches in this order

NetEventListener scene.globalBlockDispatcher - apply an event to all blocks

NetEventListener BlockType.dispatcher - apply an event to all blocks of a specific type

scene.setBlockEvent(ax, ay, az, side, type, code, isNet) - apply an event to an individual block

Event
Description
Parameters

playerfootenter

Triggered when a player steps on top of a block. On the client side, this only dispatches for the entity owner.

container: either ChunkScene or RBChunk,

player,

x, y, z

playerfootleave

Triggered when a player stops standing on a block. On the client side, this only dispatches for the entity owner.

container: either ChunkScene or RBChunk,

player,

x, y, z

allplayerfeetenter

Triggered when all players enter a block group. Server-side only. Only dispatches on the group level dispatcher.

container: either ChunkScene or RBChunk,

group

build

build/break/sculpt events are triggered by (RB)Chunk.setBlock when triggerEvents is set to true. If you change a block's type, break and build will both trigger in that order. When sculpt triggers, it will never also have a break/build event. Inversion and side rotation change can also trigger sculpt. On the client side, this only dispatches for the peer who modified the block.

container: either ChunkScene or RBChunk,

x, y, z

break

See build event description

container: either ChunkScene or RBChunk,

x, y, z

sculpt

See build event description

container: either ChunkScene or RBChunk,

x, y, z

interact

Block was interacted with using the "interact" key binding or button. Client-side only. Interact labels do not appear if the event is added on the global level dispatcher (unless you set every block type to have interactLabel: true I guess??)

container: either ChunkScene or RBChunk,

x, y, z

impact

Triggered when an impulse is applied to this block, either by a rigid body, projectile, or explosion

container: either ChunkScene or RBChunk, x, y, z, impact: Vector3, isExplosion

metadata

Triggered by setting or deleting a block's metadata

container: either ChunkScene or RBChunk, x, y, z, key, value, prvValue, mapLoad: true if triggered by loading a map

spawn

Useful for making spawner blocks. Server-side only and incompatible with the global block dispatcher. Can be triggered multiple ways: - When a map loads - At the same time "build" triggers - Immediately after adding a new spawn listener during runtime - Manually triggering the spawn event using the Rete node or scene.respawnBlock() Does not work on the global level dispatcher.

container: either ChunkScene or RBChunk, x, y, z, mapLoad: true if triggered by loading a map

eventadd

Triggered when an event listener is added to a block group. Server-side only. Only dispatches on the global level dispatcher.

container: either ChunkScene or RBChunk, group, side: either NET_SERVER or NET_CLIENT, eventType: the type of event ("build", "spawn", etc.), mapLoad: true if triggered by loading a map, callback: if side is NET_SERVER this will be the function added to the dispatcher

eventremove

Triggered when BlockGroup.removeEvents is called. Server-side only. Only dispatches on the global level dispatcher.

container: either ChunkScene or RBChunk, group

movespawn

Triggered when a block group's spawn position changes. Server-side only. Only dispatches on the global level dispatcher. Any build/break/sculpt events will trigger AFTER movespawn.

container: either ChunkScene or RBChunk,

prvSize,

prvX, prvY, prvZ,

newX, newY, newZ, group

movecenter

Triggered when a block group's center position changes. Server-side only. Only dispatches on the global level dispatcher. Any build/break/sculpt events will trigger AFTER movecenter.

container: either ChunkScene or RBChunk,

prvSize,

prvX, prvY, prvZ,

newX, newY, newZ, group

World extends NetEventDispatcher

Event
Description
Parameters

frame

Fires at the end of each frame. Only use this as a last case resort if you can’t find a better solution. Client-side only.

none ha

itemchange

Fires when the value of world.getEquippedItem() changes

prvItem: the old item item: the new item

createentity

It does what you think it does

entity

VFXManager extends NetEventDispatcher

Event
Description
Parameters

add

Client-side only

vfx

remove

Client-side only

vfx

NetEventDispatcher entity.dispatcher

Subclass
Event
Description
Parameters

Entity

death

Triggers when entity's health is set to 0.

entity

Entity

dispose

Triggers when entity is disposed. The entity is now removed from the world and can't be used again.

entity

Player

kill

Triggers when AI kills someone.

entity

target: Entity that was killed

Player

approach

Triggers when AI completes the approach behavior

entity

target: Entity that was approached

Item

use

Triggers when mouse is pressed while holding an item. Client-side only.

entity

left: true on left click, right: true on right click (it's possible for both to be true, but never both false)

Item

fire

Triggers when item fires a projectile. Client-side only.

entity

projectile: Entity that was shot out

Item

equip

Triggers when a player equips or unequips an item.

entity

player, toggle: true for equip, false for unequip

Adding an event to a block

NET_SERVER = Run event only on server side. Benefit of synchronization (and anti-cheat) for all players in server. Slower response time for player and gives host advantage NET_CLIENT = Run event only on client. Faster response time for player. For events that triggered by planet, use the following syntax

planet.addEventListener(NET_SERVER, "frame", function(){})

For events that are triggered by blockType, use the following syntax.

getBlock("bb.block.platformer.trapdoor").addEventListener(NET_SERVER, "playerfootenter", async function({ player, x, y, z }){});

Code Example

Here is an example of an event that kills the player on touch.

client: function()
	getBlock("bb.block.platformer.death").addEventListener(DEBUG.NET_CLIENT, "playerfootenter", function({ player })
	{
		player.addHealth(-player.maxHealth);
	});
}	

Event Outputs

Event
Description

player.addHealth(amount)

Add or subtract health from player.

player.serverSetSpeedSprint(speedSprint)

Set sprint speed of player.

player.serverSetJumpVelocity(jumpVelocity)

Set jump velocity of player. Sets how high a player can jump.

player.serverJump(velocity, force)

Makes a player jump. If force is true then player can jump while not on the ground.

player.serverSetCoyoteTime(coyoteTime)

Sets coyote time for player.

player.serverSetFallDamage(fallDamage)

Sets fall damage for player.

player.serverSetCanFly(bool)

Sets whether a player can fly or not.

planet.createEntity(def, nameplate, x, y, z, angle, id, except)

Creates entity and adds to scene.

planet.serverSetMessage(peer, msg, duration)

Sets message at top of screen for given peer.

Entity: setPosition(x, y, z, angle, resetCamera)

Set position of entity.

Entity: serverSetPosition(x, y, z, angle, resetCamera)

Set position of entity.

Entity: serverRespawn()

Respawn method for entities like vehicles and players.

Entity: mount(ownershipCheck, child, toggle, index)

Mounts/dismount an entity to another entities mount point. For example, a player sits in mount point of a vehicle.

scene.setBlock(ax, ay, az, shape, type, triggerEvents, isNet)

Places a block of a certain block type at a given coordinate.

BlockPhysics.unsnapSingle(container, x, y, z, isExplosion, type)

Breaks a single block & turns into a physics block.

BlockPhysics.unsnapChain(container, x, y, z, split)

Breaks a block as well as attached blocks & turns into a single physics chunk. Split should be set to false for this effect.

BlockPhysics.explosion(container, pos, centerBlock, radius, impact)

Causes an explosion by applying an impulse of magnitude "impact" at a given position and radius.

Event Examples

BlockPhysics.unsnapSingle & scene.setBlock

unsnapSingle is used to turn a block into a physics block. When the player touches the block, the block will be converted to a physics block and will fall to the ground. After 3 seconds, as long as the initial position of the trapdoor block is still unoccupied, a new trapdoor block will be placed in the original position using scene.setBlock.

//must be server sided, at least for now until we can create an RBChunk on the client side
getBlock("bb.block.platformer.trapdoor").addEventListener(NET_SERVER, "playerfootenter", async function({ player, x, y, z })
{
	var scene = player.world.scene;
	var prvShape = scene.getShape(x, y, z);
	
	//"this" refers to the engine's BlockType class instance for trapdoors
	//block's unsnapAnimation must be set to ragdoll in order to get RBChunk
	var rbchunk = BlockPhysics.unsnapSingle(scene, x, y, z, false, this);
	
	//make block spin randomly. clients will not see this!
	rbchunk.phys.setAngularVelocity((Math.random() - 0.5) * 10, (Math.random() - 0.5) * 10, (Math.random() - 0.5) * 10);
	
	await wait(3);
	
	//only build a new trapdoor if the spot is still empty
	if(scene.getShape(x, y, z) === BLOCK_AIR)
	{
		if(!rbchunk.disposed)
			rbchunk.dispose();
		
		scene.setBlock(x, y, z, prvShape, this.name, true);
	}
});

BlockPhysics.unsnapChain

Will convert all attached physics enabled blocks to physics objects that will fall with gravity.

//must be server sided, at least for now until we can create an RBChunk on the client side
getBlock("bb.block.platformer.chaintrapdoor").addEventListener(NET_SERVER, "playerfootenter", async function({ player, x, y, z })
{
	var scene = player.world.scene;
	var prvShape = scene.getShape(x, y, z);
	
	var rbchunk = BlockPhysics.unsnapChain(scene, x, y, z, false);
				
	await wait(3);
	
	//only build a new trapdoor if the spot is still empty
	if(scene.getShape(x, y, z) === BLOCK_AIR)
	{
		if(!rbchunk.disposed)
			rbchunk.dispose();
		
		scene.setBlock(x, y, z, prvShape, this.name, true);
	}
});

BlockPhyics.explosion

getBlock("bb.block.platformer.landmine").addEventListener(NET_SERVER, "playerfootenter", async function({ player, x, y, z })
{
	var radius = 5; // radius of explosion
	var impact = 100000; // each block has a maxImpact property, the explosion must be greater in order to destroy the block
	var explosionPos = new Vector3(x,y,z); // position of explosion

	var scene = player.world.scene;			
	
	player.world.hudPopup.set(null, 'BOOM!', 2);
	player.addHealth(-(player.health/2)); // do damage to player

	BlockPhysics.explosion(scene, explosionPos, explosionPos, 5, impact);
	// second explosion makes blocks go flying
	BlockPhysics.explosion(scene, explosionPos, explosionPos, 5, impact);
});

planet.createEntity

example found in src/mods/defs/BlocksSpawners.js

getBlock("bb.block.spawner.ketchupkar").addEventListener(NET_SERVER, "build", async function({ container, x, y, z })
{
	container.world.createEntity("VehicleBroncoRed", null, x + 0.5, y + 6, z + 0.5);
});

Last updated