Переглянути джерело

Add block break and block place events

shedaniel 4 роки тому
батько
коміт
f78c88a0eb

+ 19 - 0
README.md

@@ -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 "")

+ 16 - 0
common/src/main/java/me/shedaniel/architectury/ForgeEvent.java

@@ -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;

+ 8 - 0
common/src/main/java/me/shedaniel/architectury/event/events/EntityEvent.java

@@ -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);
+    }
 }

+ 8 - 0
common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java

@@ -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);
     }

+ 1 - 1
fabric/build.gradle

@@ -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")) {

+ 16 - 0
fabric/src/main/java/me/shedaniel/architectury/event/fabric/EventFactoryImpl.java

@@ -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;

+ 40 - 0
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinBlockItem.java

@@ -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);
+        }
+    }
+}

+ 48 - 0
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerPlayerGameMode.java

@@ -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);
+        }
+    }
+}

+ 3 - 3
fabric/src/main/resources/architectury.mixins.json

@@ -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

+ 16 - 0
forge/src/main/java/me/shedaniel/architectury/event/forge/EventFactoryImpl.java

@@ -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;

+ 16 - 0
forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplClient.java

@@ -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;

+ 38 - 0
forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplCommon.java

@@ -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 {
         
     }

+ 16 - 0
forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplServer.java

@@ -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;