Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/1.19.2' into 1.19.3
Browse files Browse the repository at this point in the history
# Conflicts:
#	gradle.properties
  • Loading branch information
modmuss50 committed Nov 7, 2022
2 parents f75bcd1 + 3e1ba48 commit 28cc6cc
Show file tree
Hide file tree
Showing 29 changed files with 726 additions and 28 deletions.
2 changes: 2 additions & 0 deletions fabric-block-api-v1/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
archivesBaseName = "fabric-block-api-v1"
version = getSubprojectVersion(project)
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.block.v1;

import org.jetbrains.annotations.Nullable;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import net.minecraft.world.World;

/**
* General-purpose Fabric-provided extensions for {@link Block} subclasses.
*
* <p>Note: This interface is automatically implemented on all blocks via Mixin and interface injection.
*/
// Note to maintainers: Functions should only be added to this interface if they are general-purpose enough,
// to be evaluated on a case-by-case basis. Otherwise, they are better suited for more specialized APIs.
public interface FabricBlock {
/**
* Return the current appearance of the block, i.e. which block state this block reports to look like on a given side.
*
* <p>Common implementors are covers and facades, or any other mimic blocks that proxy another block's model.
* These will want to override this method. In that case, make sure to carefully read the implementation guidelines below.
*
* <p>Common consumers are models with connected textures that wish to seamlessly connect to mimic blocks.
* These will want to check the apparent block state using {@link FabricBlockState#getAppearance}.
*
* <p>Generally, the appearance will be queried from a nearby block,
* identified by the optional {@code sourcePos} and {@code sourceState} parameters.
*
* <p>When a block changes appearance, it should trigger a chunk remesh for itself and the adjacent blocks,
* for example by calling {@link World#updateListeners}.
*
* <p>Note: Overriding this method for a block does <strong>not</strong> change how it renders.
* It's up to modded models to check for the appearance of nearby blocks and adjust accordingly.
*
* <h3>Implementation guidelines</h3>
*
* <p>This can be called on the server, where block entity data can be safely accessed,
* and on the client, possibly in a meshing thread, where block entity data is not safe to access!
* Here is an example of how data from a block entity can be handled safely.
* The block entity needs to implement {@code RenderAttachmentBlockEntity} for this to work.
* <pre>{@code @Override
* public BlockState getAppearance(BlockState state, BlockRenderView renderView, BlockPos pos, Direction side, @Nullable BlockState sourceState, @Nullable BlockPos sourcePos) {
* if (renderView instanceof ServerWorld serverWorld) {
* // Server side, ok to use block entity directly!
* BlockEntity blockEntity = serverWorld.getBlockEntity(pos);
*
* if (blockEntity instanceof ...) {
* // Get data from block entity
* return ...;
* }
* } else {
* // Client side, need to use the render attachment!
* RenderAttachedBlockView attachmentView = (RenderAttachedBlockView) renderView;
* Object data = attachmentView.getBlockEntityRenderAttachment(pos);
*
* // Check if data is not null and of the correct type, and use that to determine the appearance
* if (data instanceof ...) {
* // get appearance for side ...
* return ...;
* }
* }
*
* // Example of varying the appearance based on the source pos
* if (sourcePos != null) {
* // get appearance for side ...
* return ...;
* }
*
* // If there is no other appearance, just return the original block state
* return state;
* });
* }</pre>
*
* @param state state of this block, whose appearance is being queried
* @param renderView the world this block is in
* @param pos position of this block, whose appearance is being queried
* @param side the side for which the appearance is being queried
* @param sourceState (optional) state of the block that is querying the appearance, or null if unknown
* @param sourcePos (optional) position of the block that is querying the appearance, or null if unknown
* @return the appearance of the block on the given side; the original {@code state} can be returned if there is no better option
*/
default BlockState getAppearance(BlockState state, BlockRenderView renderView, BlockPos pos, Direction side, @Nullable BlockState sourceState, @Nullable BlockPos sourcePos) {
return state;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.block.v1;

import org.jetbrains.annotations.Nullable;

import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;

/**
* General-purpose Fabric-provided extensions for {@link BlockState}, matching the functionality provided in {@link FabricBlock}.
*
* <p>Note: This interface is automatically implemented on all block states via Mixin and interface injection.
*/
public interface FabricBlockState {
/**
* Return the current appearance of the block, i.e. which block state this block reports to look like on a given side.
*
* @param renderView the world this block is in
* @param pos position of this block, whose appearance is being queried
* @param side the side for which the appearance is being queried
* @param sourceState (optional) state of the block that is querying the appearance, or null if unknown
* @param sourcePos (optional) position of the block that is querying the appearance, or null if unknown
* @return the appearance of the block on the given side; the original {@code state} can be returned if there is no better option
* @see FabricBlock#getAppearance
*/
default BlockState getAppearance(BlockRenderView renderView, BlockPos pos, Direction side, @Nullable BlockState sourceState, @Nullable BlockPos sourcePos) {
BlockState self = (BlockState) this;
return self.getBlock().getAppearance(self, renderView, pos, side, sourceState, sourcePos);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.mixin.block;

import org.spongepowered.asm.mixin.Mixin;

import net.minecraft.block.Block;

import net.fabricmc.fabric.api.block.v1.FabricBlock;

@Mixin(Block.class)
public class BlockMixin implements FabricBlock { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.mixin.block;

import org.spongepowered.asm.mixin.Mixin;

import net.minecraft.block.BlockState;

import net.fabricmc.fabric.api.block.v1.FabricBlockState;

@Mixin(BlockState.class)
public class BlockStateMixin implements FabricBlockState { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"required": true,
"package": "net.fabricmc.fabric.mixin.block",
"compatibilityLevel": "JAVA_17",
"mixins": [
"BlockMixin",
"BlockStateMixin"
],
"injectors": {
"defaultRequire": 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions fabric-block-api-v1/src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"schemaVersion": 1,
"id": "fabric-block-api-v1",
"name": "Fabric Block API (v1)",
"version": "${version}",
"environment": "*",
"license": "Apache-2.0",
"icon": "assets/fabric-block-api-v1/icon.png",
"contact": {
"homepage": "https://fabricmc.net",
"irc": "irc://irc.esper.net:6667/fabric",
"issues": "https://github.com/FabricMC/fabric/issues",
"sources": "https://github.com/FabricMC/fabric"
},
"authors": [
"FabricMC"
],
"depends": {
"fabricloader": ">=0.14.9"
},
"entrypoints": {
},
"description": "Hooks for blocks",
"mixins": [
"fabric-block-api-v1.mixins.json"
],
"custom": {
"fabric-api:module-lifecycle": "stable",
"loom:injected_interfaces": {
"net/minecraft/class_2248": ["net/fabricmc/fabric/api/block/v1/FabricBlock"],
"net/minecraft/class_2680": ["net/fabricmc/fabric/api/block/v1/FabricBlockState"]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.entity.event.v1;

import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;

import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;

/**
* Various server-side only events related to living entities.
*/
public final class ServerLivingEntityEvents {
/**
* An event that is called when a living entity is going to take damage.
* This is fired from {@link LivingEntity#damage}, before armor or any other mitigation are applied.
* Mods can cancel this to prevent the damage entirely.
*/
public static final Event<AllowDamage> ALLOW_DAMAGE = EventFactory.createArrayBacked(AllowDamage.class, callbacks -> (entity, source, amount) -> {
for (AllowDamage callback : callbacks) {
if (!callback.allowDamage(entity, source, amount)) {
return false;
}
}

return true;
});

/**
* An event that is called when an entity takes fatal damage.
*
* <p>Mods can cancel this to keep the entity alive.
*
* <p>Vanilla checks for entity health {@code <= 0} each tick (with {@link LivingEntity#isDead()}), and kills if true -
* so the entity will still die next tick if this event is cancelled.
* It's assumed that the listener will do something to prevent this, for example, if the entity is a player:
* <ul>
* <li>a minigame mod teleporting the player into a 'respawn room' and setting their health to 20.0</li>
* <li>a mod that changes death mechanics switching the player over to the mod's play-mode, where death doesn't apply</li>
* </ul>
*/
public static final Event<AllowDeath> ALLOW_DEATH = EventFactory.createArrayBacked(AllowDeath.class, callbacks -> (entity, damageSource, damageAmount) -> {
for (AllowDeath callback : callbacks) {
if (!callback.allowDeath(entity, damageSource, damageAmount)) {
return false;
}
}

return true;
});

/**
* An event that is called when a living entity dies.
*/
public static final Event<AfterDeath> AFTER_DEATH = EventFactory.createArrayBacked(AfterDeath.class, callbacks -> (entity, damageSource) -> {
for (AfterDeath callback : callbacks) {
callback.afterDeath(entity, damageSource);
}
});

@FunctionalInterface
public interface AllowDamage {
/**
* Called when a living entity is going to take damage. Can be used to cancel the damage entirely.
*
* <p>The amount corresponds to the "incoming" damage amount, before armor and other mitigations have been applied.
*
* @param entity the entity
* @param source the source of the damage
* @param amount the amount of damage that the entity will take (before mitigations)
* @return true if the damage should go ahead, false to cancel the damage.
*/
boolean allowDamage(LivingEntity entity, DamageSource source, float amount);
}

@FunctionalInterface
public interface AllowDeath {
/**
* Called when a living entity takes fatal damage (before totems of undying can take effect).
*
* @param entity the entity
* @param damageSource the source of the fatal damage
* @param damageAmount the amount of damage that has killed the entity
* @return true if the death should go ahead, false to cancel the death.
*/
boolean allowDeath(LivingEntity entity, DamageSource damageSource, float damageAmount);
}

@FunctionalInterface
public interface AfterDeath {
/**
* Called when a living entity dies. The death cannot be canceled at this point.
*
* @param entity the entity
* @param damageSource the source of the fatal damage
*/
void afterDeath(LivingEntity entity, DamageSource damageSource);
}

private ServerLivingEntityEvents() {
}
}
Loading

0 comments on commit 28cc6cc

Please sign in to comment.