Add block break and block place events

This commit is contained in:
shedaniel
2020-11-18 00:28:15 +08:00
parent e23ca38572
commit f78c88a0eb
13 changed files with 245 additions and 4 deletions

19
README.md Normal file
View File

@@ -0,0 +1,19 @@
# Architectury
A intermediary api aimed to ease developing multiplatform mods.
### What is Architectury
Architectury is an api to abstract calls to fabric api and forge api as both loader has different implementations of what can be perceived as the same thing.
Architectury updates regularly, with new hooks and features. Currently contains over **60** events hooks, networking abstraction, loader calls abstraction, game registry abstraction and an easy to use @ExpectPlatform annotation.
### Advantages of Architectury
- Open sourced
- Less boilerplate for your multiplatform mod
### Getting started with making multiplatform mods
Gradle Plugin: https://github.com/architectury/architect-plugin
Example Mod: https://github.com/architectury/architect-example-mod
### Credits
This library bundles typetools, which you can find its license [here](https://github.com/jhalterman/typetools/blob/master/LICENSE.txt "")

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2020 shedaniel
*
* 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 me.shedaniel.architectury;
import java.lang.annotation.ElementType;

View File

@@ -18,11 +18,14 @@ package me.shedaniel.architectury.event.events;
import me.shedaniel.architectury.event.Event;
import me.shedaniel.architectury.event.EventFactory;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
public interface EntityEvent {
/**
@@ -37,6 +40,7 @@ public interface EntityEvent {
* Invoked before entity is added to a world, equivalent to forge's {@code EntityJoinWorldEvent}.
*/
Event<Add> ADD = EventFactory.createInteractionResult(Add.class);
Event<PlaceBlock> PLACE_BLOCK = EventFactory.createInteractionResult(PlaceBlock.class);
interface LivingDeath {
InteractionResult die(LivingEntity entity, DamageSource source);
@@ -49,4 +53,8 @@ public interface EntityEvent {
interface Add {
InteractionResult add(Entity entity, Level world);
}
interface PlaceBlock {
InteractionResult placeBlock(Level world, BlockPos pos, BlockState state, @Nullable Entity placer);
}
}

View File

@@ -22,6 +22,7 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.advancements.Advancement;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Container;
import net.minecraft.world.InteractionResult;
@@ -29,6 +30,8 @@ import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
public interface PlayerEvent {
Event<PlayerJoin> PLAYER_JOIN = EventFactory.createLoop(PlayerJoin.class);
@@ -46,6 +49,7 @@ public interface PlayerEvent {
Event<DropItem> DROP_ITEM = EventFactory.createLoop(DropItem.class);
Event<OpenMenu> OPEN_MENU = EventFactory.createLoop(OpenMenu.class);
Event<CloseMenu> CLOSE_MENU = EventFactory.createLoop(CloseMenu.class);
Event<BreakBlock> BREAK_BLOCK = EventFactory.createInteractionResult(BreakBlock.class);
interface PlayerJoin {
void join(ServerPlayer player);
@@ -87,6 +91,10 @@ public interface PlayerEvent {
InteractionResult drop(Player player, ItemEntity entity);
}
interface BreakBlock {
InteractionResult breakBlock(Level world, BlockPos pos, BlockState state, ServerPlayer player);
}
interface OpenMenu {
void open(Player player, AbstractContainerMenu menu);
}

View File

@@ -21,7 +21,7 @@ dependencies {
implementation "net.jodah:typetools:0.6.2"
shadow "net.jodah:typetools:0.6.2"
compileOnly(project(path: ":common", configuration: "transformed")) {
compileOnly(project(path: ":common")) {
transitive = false
}
runtimeOnly(project(path: ":common", configuration: "transformed")) {

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2020 shedaniel
*
* 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 me.shedaniel.architectury.event.fabric;
import me.shedaniel.architectury.event.Event;

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2020 shedaniel
*
* 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 me.shedaniel.architectury.mixin.fabric;
import me.shedaniel.architectury.event.events.EntityEvent;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.context.BlockPlaceContext;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(BlockItem.class)
public abstract class MixinBlockItem {
@Inject(method = "place",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/item/context/BlockPlaceContext;getClickedPos()Lnet/minecraft/core/BlockPos;"),
cancellable = true)
private void place(BlockPlaceContext context, CallbackInfoReturnable<InteractionResult> cir) {
InteractionResult result = EntityEvent.PLACE_BLOCK.invoker().placeBlock(context.getLevel(), context.getClickedPos(), context.getLevel().getBlockState(context.getClickedPos()), context.getPlayer());
if (result != InteractionResult.PASS) {
cir.setReturnValue(result);
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2020 shedaniel
*
* 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 me.shedaniel.architectury.mixin.fabric;
import me.shedaniel.architectury.event.events.PlayerEvent;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.ServerPlayerGameMode;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(ServerPlayerGameMode.class)
public class MixinServerPlayerGameMode {
@Shadow public ServerLevel level;
@Shadow public ServerPlayer player;
@Inject(method = "destroyBlock", at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/level/block/state/BlockState;getBlock()Lnet/minecraft/world/level/block/Block;",
ordinal = 0),
locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
private void onBreak(BlockPos blockPos, CallbackInfoReturnable<Boolean> cir, BlockState state) {
if (PlayerEvent.BREAK_BLOCK.invoker().breakBlock(this.level, blockPos, state, this.player) == InteractionResult.FAIL) {
cir.setReturnValue(false);
}
}
}

View File

@@ -14,9 +14,9 @@
"client.MixinTextureAtlas"
],
"mixins": [
"ExplosionPreInvoker", "LivingDeathInvoker", "MixinCommands", "MixinExplosion", "MixinFurnaceResultSlot", "MixinItemEntity", "MixinLivingEntity",
"MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList", "MixinResultSlot", "MixinServerGamePacketListenerImpl", "MixinServerLevel",
"MixinServerPlayer", "PlayerAttackInvoker"
"ExplosionPreInvoker", "LivingDeathInvoker", "MixinBlockItem", "MixinCommands", "MixinExplosion", "MixinFurnaceResultSlot", "MixinItemEntity",
"MixinLivingEntity", "MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList", "MixinResultSlot", "MixinServerGamePacketListenerImpl",
"MixinServerLevel", "MixinServerPlayer", "MixinServerPlayerGameMode", "PlayerAttackInvoker"
],
"injectors": {
"defaultRequire": 1

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2020 shedaniel
*
* 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 me.shedaniel.architectury.event.forge;
import me.shedaniel.architectury.event.Event;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2020 shedaniel
*
* 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 me.shedaniel.architectury.event.forge;
import me.shedaniel.architectury.event.events.TextureStitchEvent;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2020 shedaniel
*
* 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 me.shedaniel.architectury.event.forge;
import me.shedaniel.architectury.event.events.*;
@@ -6,6 +22,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.event.CommandEvent;
import net.minecraftforge.event.RegisterCommandsEvent;
@@ -23,6 +40,7 @@ import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
import net.minecraftforge.event.entity.player.PlayerContainerEvent;
import net.minecraftforge.event.entity.player.PlayerEvent.*;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.ExplosionEvent.Detonate;
import net.minecraftforge.event.world.ExplosionEvent.Start;
import net.minecraftforge.event.world.WorldEvent;
@@ -268,6 +286,26 @@ public class EventHandlerImplCommon {
}
}
@SubscribeEvent
public static void event(BlockEvent.BreakEvent event) {
if (event.getPlayer() instanceof ServerPlayerEntity && event.getWorld() instanceof World) {
ActionResultType result = PlayerEvent.BREAK_BLOCK.invoker().breakBlock((World) event.getWorld(), event.getPos(), event.getState(), (ServerPlayerEntity) event.getPlayer());
if (result != ActionResultType.PASS) {
event.setCanceled(true);
}
}
}
@SubscribeEvent
public static void event(BlockEvent.EntityPlaceEvent event) {
if (event.getWorld() instanceof World) {
ActionResultType result = EntityEvent.PLACE_BLOCK.invoker().placeBlock((World) event.getWorld(), event.getPos(), event.getState(), event.getEntity());
if (result != ActionResultType.PASS) {
event.setCanceled(true);
}
}
}
public static class ModBasedEventHandler {
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2020 shedaniel
*
* 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 me.shedaniel.architectury.event.forge;
import net.minecraftforge.api.distmarker.Dist;