Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 00743c841f | |||
| bdb9c9dec4 |
+1
-1
@@ -4,7 +4,7 @@ mcVersion=1.21.8
|
||||
release=2
|
||||
# 0 for skip release, 1 for pre-release, 2 for release
|
||||
|
||||
luminolRef=a3c596e26bfdf197a1c0c7a536c8a2bf7f97c09d
|
||||
luminolRef=48368770092c9bd039406fc058ad4aa516e3692b
|
||||
|
||||
org.gradle.configuration-cache=true
|
||||
org.gradle.caching=true
|
||||
|
||||
@@ -5,7 +5,7 @@ Subject: [PATCH] Rebrand to Lophine
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
index d8066afd5f3f2ea9a5dff87d853562e22268785c..f8b2364fa162a41304a99a4993354e33528ab801 100644
|
||||
index a5208f5426ea2e5d8f50c51fe17718ea1d63eef5..c80c578f1a3786bd7413c9a7af8ae125fe7975bb 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
@@ -21,6 +21,7 @@ public class ConfigManager {
|
||||
|
||||
@@ -8,180 +8,69 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/d93e9766d3797d130
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||
index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981c4e34aed 100644
|
||||
index 112dc08eb62c4c50fb4859f51a366cedf027ca00..b5f661fd20b382725ad117c56ce2c94ded32b1b7 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||
@@ -17,12 +17,173 @@
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package org.leavesmc.leaves.util;
|
||||
|
||||
+import fun.bm.lophine.config.modules.function.ContainerExpansionConfig;
|
||||
+import net.minecraft.core.component.DataComponents;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.world.entity.item.ItemEntity;
|
||||
+import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
+import net.minecraft.world.item.component.CustomData;
|
||||
+import net.minecraft.world.item.component.ItemContainerContents;
|
||||
+import net.minecraft.world.level.block.ShulkerBoxBlock;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.util.List;
|
||||
+import java.util.Objects;
|
||||
+import java.util.Optional;
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import io.papermc.paper.datacomponent.item.ItemEnchantments;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
@@ -135,9 +136,9 @@ public class ItemOverstackUtils {
|
||||
|
||||
// Only the used part is retained
|
||||
public class ItemOverstackUtils {
|
||||
+ private static final List<ItemUtil> overstackUtils = List.of(
|
||||
+ new ShulkerBox()
|
||||
+ );
|
||||
+
|
||||
+ public static int getItemStackMaxCount(ItemStack stack) {
|
||||
+ int size;
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if ((size = util.getMaxServerStackCount(stack)) != -1) {
|
||||
+ return size;
|
||||
+ }
|
||||
+ }
|
||||
+ return stack.getMaxStackSize();
|
||||
+ }
|
||||
+
|
||||
+ public static int getNetworkMaxCount(ItemStack stack) {
|
||||
+ int size;
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if ((size = util.getMaxClientStackCount(stack)) != -1) {
|
||||
+ return size;
|
||||
+ }
|
||||
+ }
|
||||
+ return stack.getMaxStackSize();
|
||||
+ }
|
||||
+
|
||||
+ public static boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.tryStackItems(self, other)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public static boolean hasOverstackingItem() {
|
||||
+ return overstackUtils.stream().anyMatch(ItemUtil::isEnabled);
|
||||
+ }
|
||||
+
|
||||
+ public static int getItemStackMaxCountReal(ItemStack stack) {
|
||||
+ CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag();
|
||||
+ return nbt.getInt("Leaves.RealStackSize").orElse(stack.getMaxStackSize());
|
||||
+ }
|
||||
+
|
||||
+ public static ItemStack encodeMaxStackSize(ItemStack itemStack) {
|
||||
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
|
||||
+ int modifiedMaxStackSize = getNetworkMaxCount(itemStack);
|
||||
+ if (itemStack.getMaxStackSize() != modifiedMaxStackSize) {
|
||||
+ itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize);
|
||||
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
+ nbt.putInt("Leaves.RealStackSize", realMaxStackSize);
|
||||
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
|
||||
+ }
|
||||
+ return itemStack;
|
||||
+ }
|
||||
+
|
||||
+ public static ItemStack decodeMaxStackSize(ItemStack itemStack) {
|
||||
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
|
||||
+ if (itemStack.getMaxStackSize() != realMaxStackSize) {
|
||||
+ itemStack.set(DataComponents.MAX_STACK_SIZE, realMaxStackSize);
|
||||
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
+ nbt.remove("Leaves.RealStackSize");
|
||||
+ if (nbt.isEmpty()) {
|
||||
+ itemStack.remove(DataComponents.CUSTOM_DATA);
|
||||
+ } else {
|
||||
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
|
||||
+ }
|
||||
+ }
|
||||
+ return itemStack;
|
||||
+ }
|
||||
+
|
||||
public static float getItemStackSignalStrength(int maxStackSize, ItemStack itemStack) {
|
||||
float result = (float) itemStack.getCount() / Math.min(maxStackSize, itemStack.getMaxStackSize());
|
||||
return Math.clamp(result, 0f, 1f);
|
||||
}
|
||||
+
|
||||
+ public static boolean isStackable(ItemStack itemStack) {
|
||||
+ return getItemStackMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged());
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ private interface ItemUtil {
|
||||
+ boolean isEnabled();
|
||||
+
|
||||
+ boolean tryStackItems(ItemEntity self, ItemEntity other);
|
||||
+
|
||||
+ // number -> modified count, -1 -> I don't care
|
||||
+ int getMaxServerStackCount(ItemStack stack);
|
||||
+
|
||||
+ // number -> modified count, -1 -> I don't care
|
||||
+ default int getMaxClientStackCount(ItemStack stack) {
|
||||
+ return getMaxServerStackCount(stack);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static class ShulkerBox implements ItemUtil {
|
||||
+ public static boolean shulkerBoxCheck(@NotNull ItemStack stack1, @NotNull ItemStack stack2) {
|
||||
private static class ShulkerBox implements ItemUtil {
|
||||
public static boolean shulkerBoxCheck(@NotNull ItemStack stack1, @NotNull ItemStack stack2) {
|
||||
- /*if (LeavesConfig.modify.shulkerBox.sameNbtStackable) {
|
||||
+ if (ContainerExpansionConfig.nbtShulkerStackable) {
|
||||
+ return Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||
return Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||
- }*/ // Luminol
|
||||
+ }
|
||||
+ return shulkerBoxNoItem(stack1) && shulkerBoxNoItem(stack2) && Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||
+ }
|
||||
+
|
||||
+ public static boolean shulkerBoxNoItem(@NotNull ItemStack stack) {
|
||||
+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).stream().findAny().isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isEnabled() {
|
||||
return shulkerBoxNoItem(stack1) && shulkerBoxNoItem(stack2) && Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||
}
|
||||
|
||||
@@ -147,16 +148,15 @@ public class ItemOverstackUtils {
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
- // return LeavesConfig.modify.shulkerBox.stackableShulkerBoxes > 1; // Luminol
|
||||
- return false; // Luminol
|
||||
+ return ContainerExpansionConfig.shulkerCount > 1;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||
+ ItemStack selfStack = self.getItem();
|
||||
+ if (!isEnabled() ||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||
ItemStack selfStack = self.getItem();
|
||||
if (!isEnabled() ||
|
||||
- !(selfStack.getItem() instanceof net.minecraft.world.item.BlockItem blockItem) ||
|
||||
- !(blockItem.getBlock() instanceof net.minecraft.world.level.block.ShulkerBoxBlock)
|
||||
+ !(selfStack.getItem() instanceof BlockItem blockItem) ||
|
||||
+ !(blockItem.getBlock() instanceof ShulkerBoxBlock)
|
||||
+ ) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ ItemStack otherStack = other.getItem();
|
||||
+ if (selfStack.getItem() == otherStack.getItem()
|
||||
+ && shulkerBoxCheck(selfStack, otherStack)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -164,8 +164,8 @@ public class ItemOverstackUtils {
|
||||
ItemStack otherStack = other.getItem();
|
||||
if (selfStack.getItem() == otherStack.getItem()
|
||||
&& shulkerBoxCheck(selfStack, otherStack)
|
||||
- && selfStack.getCount() != /*org.leavesmc.leaves.LeavesConfig.modify.shulkerBox.stackableShulkerBoxes*/ 1) { // Luminol
|
||||
- int amount = Math.min(otherStack.getCount(), /*org.leavesmc.leaves.LeavesConfig.modify.shulkerBox.stackableShulkerBoxes*/1 - selfStack.getCount()); // Luminol
|
||||
+ && selfStack.getCount() != ContainerExpansionConfig.shulkerCount) {
|
||||
+ int amount = Math.min(otherStack.getCount(), ContainerExpansionConfig.shulkerCount - selfStack.getCount());
|
||||
+
|
||||
+ selfStack.grow(amount);
|
||||
+ self.setItem(selfStack);
|
||||
+
|
||||
+ self.pickupDelay = Math.max(other.pickupDelay, self.pickupDelay);
|
||||
+ self.age = Math.min(other.getAge(), self.age);
|
||||
+
|
||||
+ otherStack.shrink(amount);
|
||||
+ if (otherStack.isEmpty()) {
|
||||
+ other.discard();
|
||||
+ } else {
|
||||
+ other.setItem(otherStack);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxServerStackCount(ItemStack stack) {
|
||||
+ if (isEnabled() && stack.getItem() instanceof BlockItem bi &&
|
||||
|
||||
selfStack.grow(amount);
|
||||
self.setItem(selfStack);
|
||||
@@ -187,9 +187,8 @@ public class ItemOverstackUtils {
|
||||
@Override
|
||||
public int getMaxServerStackCount(ItemStack stack) {
|
||||
if (isEnabled() && stack.getItem() instanceof BlockItem bi &&
|
||||
- bi.getBlock() instanceof ShulkerBoxBlock && (/*LeavesConfig.modify.shulkerBox.sameNbtStackable ||*/ shulkerBoxNoItem(stack))) { // Luminol
|
||||
- // return LeavesConfig.modify.shulkerBox.stackableShulkerBoxes; // Luminol
|
||||
- return 1; // Luminol
|
||||
+ bi.getBlock() instanceof ShulkerBoxBlock && (ContainerExpansionConfig.nbtShulkerStackable || shulkerBoxNoItem(stack))) {
|
||||
+ return ContainerExpansionConfig.shulkerCount;
|
||||
+ }
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
+3
-3
@@ -18,10 +18,10 @@ index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd1
|
||||
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
|
||||
if (rangeY != -1) {
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index f5539ca5964abb18124522a8aa7ce940517b2011..1258591aae1b926ee8085b1984d553b8d3a1df7e 100644
|
||||
index ea177b8ad7ebb25e3e2967c8ff3d36dc3dda6a1d..861684a36e3277c31842f30c82ffd9d85e2fe3f8 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
|
||||
@@ -146,7 +146,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -30,7 +30,7 @@ index f5539ca5964abb18124522a8aa7ce940517b2011..1258591aae1b926ee8085b1984d553b8
|
||||
// CraftBukkit start
|
||||
private static final int CURRENT_LEVEL = 2;
|
||||
public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first snapTo
|
||||
@@ -6482,4 +6482,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -6462,4 +6462,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
// Paper end - Expose entity id counter
|
||||
|
||||
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
|
||||
|
||||
@@ -446,10 +446,10 @@ index 10b2cc20bbf3b70e4e09dbbe14b90506e6366158..1535bb8cec8692e8d26eaff090288f1b
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index 699bb3cc2b680a4ee438a88c05854e5ab05ea910..d4fe03fd766caca1d7693a5317460ca1a9b9fa4f 100644
|
||||
index 3fd172f82216fa35c36e5f563819a6f01ffd4ea4..419bc939e19a306b33d4d387007c6acbae73fba3 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -148,7 +148,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -144,7 +144,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
public void setItem(int index, ItemStack stack) {
|
||||
this.unpackLootTable(null);
|
||||
this.getItems().set(index, stack);
|
||||
@@ -458,7 +458,7 @@ index 699bb3cc2b680a4ee438a88c05854e5ab05ea910..d4fe03fd766caca1d7693a5317460ca1
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -743,9 +743,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -740,9 +740,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (item.isEmpty()) {
|
||||
// Spigot start - SPIGOT-6693, SimpleContainer#setItem
|
||||
ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
|
||||
@@ -469,4 +469,4 @@ index 699bb3cc2b680a4ee438a88c05854e5ab05ea910..d4fe03fd766caca1d7693a5317460ca1
|
||||
+ stack = stack.split(Math.min(destination.getMaxStackSize(), stack.getMaxStackSize())); // Leaves - item over-stack util
|
||||
}
|
||||
// Spigot end
|
||||
//IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading // Luminol - Use vanilla hopper logic
|
||||
//IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading // Luminol - vanilla hopper
|
||||
|
||||
@@ -23,7 +23,7 @@ index d0d90a25a10bbecfffceee1992af88c60d14fd87..187e48e78e69c80b25710f193813335e
|
||||
+ // Leaves end - servux
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index eb3aef1f5198592eda5dafe84b91271e861b4135..576dde41a4b48aac9079cca902f4371a31470af3 100644
|
||||
index 9796c449f924b8fd9c0dd6bb02cf196641e495ed..4f1976c47a087bf4f36687124ef29ca7b664f682 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2368,6 +2368,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18
|
||||
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 593dbcda4b497291eb1ecdc64b947a8d279f8be6..cb863a36fc67e993956ec3be655e6e4b9764c051 100644
|
||||
index 6c1f4f943a5be5f2e43a82cca52ca76a98226915..8e2775e873c92beed6a0e4e8ce1304ab8ca6e8d1 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1087,6 +1087,10 @@ public abstract class PlayerList {
|
||||
|
||||
@@ -39,7 +39,7 @@ index cf72cb8b418239b56c755486b03a321672e16bc3..b69c06607ca900beeebf4892a978442d
|
||||
String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck();
|
||||
if (awtException != null) {
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index c93feb64b6088a4878fcdb6e7c733a5f37e9385b..79c911003c7b1c3d94e7e9d3974eeadcc16bde3a 100644
|
||||
index 392d75548f7eb271a6320ac30eb301a61071d465..0e278f7b9ed85ce8c3cedd9154f817b30ff1e48a 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -172,6 +172,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
|
||||
@@ -266,7 +266,7 @@ index 70740381c6501c1a518c52b24381edd16792507f..5e31b499a894113b4be1982a1071348f
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 4f1976c47a087bf4f36687124ef29ca7b664f682..96aafe4d63446b3d212f21f14091858f72bb081f 100644
|
||||
index d1a799199a68771ae3130a30a59625587c11b0b0..edf29b1a8a6cbadff6a65f0483e28ec72a78594d 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -207,6 +207,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -548,10 +548,10 @@ index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd1
|
||||
|
||||
for (WaypointTransmitter waypointTransmitter : this.waypoints) {
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 1258591aae1b926ee8085b1984d553b8d3a1df7e..365cb2aed3d0f428ba33d4debdf3c3a3c494882d 100644
|
||||
index 861684a36e3277c31842f30c82ffd9d85e2fe3f8..da1b004c1f66437534f3180b6d3f3a054b7c6945 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -1225,7 +1225,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -1224,7 +1224,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
|
||||
BlockPos onPosLegacy = this.getOnPosLegacy();
|
||||
BlockState blockState = this.level().getBlockState(onPosLegacy);
|
||||
@@ -560,7 +560,7 @@ index 1258591aae1b926ee8085b1984d553b8d3a1df7e..365cb2aed3d0f428ba33d4debdf3c3a3
|
||||
this.checkFallDamage(vec3.y, this.onGround(), blockState, onPosLegacy);
|
||||
}
|
||||
|
||||
@@ -1539,7 +1539,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
@@ -1538,7 +1538,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
// Paper start - optimise collisions
|
||||
|
||||
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 908ec29a6e285122d1a8a43dc547b74af2697442..1bf1731e43278b71423fee5d92401c48d6dabaca 100644
|
||||
index 580f114fd99b017403c61e994d0c947d00e5115d..11c1eb6995ec3aa896815efa59477096c39089d1 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1247,6 +1247,7 @@ public abstract class PlayerList {
|
||||
|
||||
@@ -10,10 +10,10 @@ Licensed under: MIT
|
||||
This patch is Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet)
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index d4fe03fd766caca1d7693a5317460ca1a9b9fa4f..a821deaa5c076151336762d17a8da45abb4c43cd 100644
|
||||
index 419bc939e19a306b33d4d387007c6acbae73fba3..96445438c5b4202e3fc93bece778ad0d7312d41c 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -232,8 +232,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -228,8 +228,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
flag |= validator.getAsBoolean(); // Paper - note: this is not a validator, it's what adds/sucks in items
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ index d4fe03fd766caca1d7693a5317460ca1a9b9fa4f..a821deaa5c076151336762d17a8da45a
|
||||
setChanged(level, pos, state);
|
||||
// Leaves start - Lithium Sleeping Block Entity
|
||||
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled
|
||||
@@ -465,6 +487,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -461,6 +483,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
// Paper end - Perf: Optimize Hoppers
|
||||
|
||||
private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
|
||||
@@ -58,7 +58,7 @@ index d4fe03fd766caca1d7693a5317460ca1a9b9fa4f..a821deaa5c076151336762d17a8da45a
|
||||
Container attachedContainer = me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? blockEntity.getInsertInventory(level) : getAttachedContainer(level, pos, blockEntity); // Leaves - Lithium Sleeping Block Entity
|
||||
if (attachedContainer == null) {
|
||||
return false;
|
||||
@@ -541,6 +570,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -536,6 +565,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ index d4fe03fd766caca1d7693a5317460ca1a9b9fa4f..a821deaa5c076151336762d17a8da45a
|
||||
private static int[] getSlots(Container container, Direction direction) {
|
||||
if (container instanceof WorldlyContainer worldlyContainer) {
|
||||
return worldlyContainer.getSlotsForFace(direction);
|
||||
@@ -683,6 +732,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -680,6 +729,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
}
|
||||
|
||||
public static boolean addItem(Container container, ItemEntity item) {
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
Date: Mon, 3 Feb 2025 13:51:26 +0800
|
||||
Subject: [PATCH] Leaves: Alternative block placement Protocol
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||
Licensed under: MIT
|
||||
|
||||
This patch is Powered by
|
||||
carpet-extra(https://github.com/gnembon/carpet-extra)
|
||||
MasaGadget(https://github.com/plusls/MasaGadget)
|
||||
litematica(https://github.com/maruohon/litematica)
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 9be4bc9e78c22c12ba594b16dac6901023f0fd47..3d9c26bc8cc14e98310f557f351871b082e5023e 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2087,7 +2087,7 @@ public class ServerGamePacketListenerImpl
|
||||
if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.player.level(), blockPos.getX() >> 4, blockPos.getZ() >> 4, 8) && this.player.canInteractWithBlock(blockPos, 1.0)) { // Folia - do not allow players to interact with blocks outside the current region
|
||||
Vec3 vec3 = location.subtract(Vec3.atCenterOf(blockPos));
|
||||
double d = 1.0000001;
|
||||
- if (Math.abs(vec3.x()) < 1.0000001 && Math.abs(vec3.y()) < 1.0000001 && Math.abs(vec3.z()) < 1.0000001) {
|
||||
+ if (fun.bm.lophine.config.modules.function.protocol.AlternativeBlockPlacementProtocolConfig.needIgnoreDistance() ||Math.abs(vec3.x()) < 1.0000001 && Math.abs(vec3.y()) < 1.0000001 && Math.abs(vec3.z()) < 1.0000001) { // Leaves - disableDistanceCheckForUseItem
|
||||
Direction direction = hitResult.getDirection();
|
||||
this.player.resetLastActionTime();
|
||||
int maxY = this.player.level().getMaxY();
|
||||
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
|
||||
index 6db566adf2d0df1d26221eda04aa01738df6d3d2..8f112f382190d606a87f38da8bcdf8dd5f31d1c5 100644
|
||||
--- a/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/net/minecraft/world/item/BlockItem.java
|
||||
@@ -149,7 +149,7 @@ public class BlockItem extends Item {
|
||||
|
||||
@Nullable
|
||||
protected BlockState getPlacementState(BlockPlaceContext context) {
|
||||
- BlockState stateForPlacement = this.getBlock().getStateForPlacement(context);
|
||||
+ BlockState stateForPlacement = this.getBlock().getRealStateForPlacement(context); // Leaves - alternativeBlockPlacement
|
||||
return stateForPlacement != null && this.canPlace(context, stateForPlacement) ? stateForPlacement : null;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/item/StandingAndWallBlockItem.java b/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
index 12c6c8aeec89a0a55633c62fe98f5a3aa75fd476..1f0e7c391d02b18e2c89700025713ec3d759f2ea 100644
|
||||
--- a/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
+++ b/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
@@ -27,14 +27,14 @@ public class StandingAndWallBlockItem extends BlockItem {
|
||||
@Nullable
|
||||
@Override
|
||||
protected BlockState getPlacementState(BlockPlaceContext context) {
|
||||
- BlockState stateForPlacement = this.wallBlock.getStateForPlacement(context);
|
||||
+ BlockState stateForPlacement = this.wallBlock.getRealStateForPlacement(context); // Leaves - alternativeBlockPlacement
|
||||
BlockState blockState = null;
|
||||
LevelReader level = context.getLevel();
|
||||
BlockPos clickedPos = context.getClickedPos();
|
||||
|
||||
for (Direction direction : context.getNearestLookingDirections()) {
|
||||
if (direction != this.attachmentDirection.getOpposite()) {
|
||||
- BlockState blockState1 = direction == this.attachmentDirection ? this.getBlock().getStateForPlacement(context) : stateForPlacement;
|
||||
+ BlockState blockState1 = direction == this.attachmentDirection ? this.getBlock().getRealStateForPlacement(context) : stateForPlacement; // Leaves - alternativeBlockPlacement
|
||||
if (blockState1 != null && this.canPlace(level, blockState1, clickedPos)) {
|
||||
blockState = blockState1;
|
||||
break;
|
||||
diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java
|
||||
index 644b9fab1d6729bf3964ebee0d6e9c46f89b8c46..634bdb554dfe757c3c9f13a79c3f644d8be4e3ea 100644
|
||||
--- a/net/minecraft/world/level/block/Block.java
|
||||
+++ b/net/minecraft/world/level/block/Block.java
|
||||
@@ -439,6 +439,33 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) {
|
||||
}
|
||||
|
||||
+ // Leaves start - alternativeBlockPlacement
|
||||
+ @Nullable
|
||||
+ public BlockState getRealStateForPlacement(BlockPlaceContext ctx) {
|
||||
+ BlockState vanillaState = this.getStateForPlacement(ctx);
|
||||
+ switch (fun.bm.lophine.config.modules.function.protocol.AlternativeBlockPlacementProtocolConfig.alternativeBlockPlacement) {
|
||||
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.CARPET -> {
|
||||
+ BlockState tryState = org.leavesmc.leaves.protocol.CarpetAlternativeBlockPlacement.alternativeBlockPlacement(this, ctx);
|
||||
+ if (tryState != null) {
|
||||
+ return tryState;
|
||||
+ }
|
||||
+ }
|
||||
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.CARPET_FIX -> {
|
||||
+ BlockState tryState = org.leavesmc.leaves.protocol.CarpetAlternativeBlockPlacement.alternativeBlockPlacementFix(this, ctx);
|
||||
+ if (tryState != null) {
|
||||
+ return tryState;
|
||||
+ }
|
||||
+ }
|
||||
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.LITEMATICA -> {
|
||||
+ if (vanillaState != null) {
|
||||
+ return org.leavesmc.leaves.protocol.LitematicaEasyPlaceProtocol.applyPlacementProtocol(vanillaState, ctx);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return vanillaState;
|
||||
+ }
|
||||
+ // Leaves end - alternativeBlockPlacement
|
||||
+
|
||||
@Nullable
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
return this.defaultBlockState();
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package fun.bm.lophine.config.modules.function.protocol;
|
||||
|
||||
import fun.bm.lophine.enums.EnumAlternativePlaceType;
|
||||
import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
|
||||
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "alternative_block_placement", directory = {"protocol"})
|
||||
public class AlternativeBlockPlacementProtocolConfig implements IConfigModule {
|
||||
@ConfigInfo(name = "enabled", comments = """
|
||||
Specify the precise placement protocol type
|
||||
NONE Disable precise placement protocol
|
||||
CARPET Precise placement protocol version 2
|
||||
CARPET_FIX Enhanced precise placement protocol version 2 (requires MasaGadget installed on client)
|
||||
LITEMATICA Precise placement protocol version 3""")
|
||||
public static EnumAlternativePlaceType alternativeBlockPlacement = EnumAlternativePlaceType.NONE;
|
||||
|
||||
public static boolean needIgnoreDistance() {
|
||||
return alternativeBlockPlacement != EnumAlternativePlaceType.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package fun.bm.lophine.enums;
|
||||
|
||||
public enum EnumAlternativePlaceType {
|
||||
NONE,
|
||||
CARPET,
|
||||
CARPET_FIX,
|
||||
LITEMATICA
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.protocol;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.piston.PistonBaseBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.*;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
|
||||
public class CarpetAlternativeBlockPlacement {
|
||||
|
||||
@Nullable
|
||||
public static BlockState alternativeBlockPlacement(@NotNull Block block, @NotNull BlockPlaceContext context) {
|
||||
Vec3 hitPos = context.getClickLocation();
|
||||
BlockPos blockPos = context.getClickedPos();
|
||||
double relativeHitX = hitPos.x - blockPos.getX();
|
||||
BlockState state = block.getStateForPlacement(context);
|
||||
Player player = context.getPlayer();
|
||||
|
||||
if (relativeHitX < 2 || state == null || player == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
EnumProperty<Direction> directionProp = getFirstDirectionProperty(state);
|
||||
int protocolValue = ((int) relativeHitX - 2) / 2;
|
||||
|
||||
if (directionProp != null) {
|
||||
Direction origFacing = state.getValue(directionProp);
|
||||
Direction facing = origFacing;
|
||||
int facingIndex = protocolValue & 0xF;
|
||||
|
||||
if (facingIndex == 6) {
|
||||
facing = facing.getOpposite();
|
||||
} else if (facingIndex <= 5) {
|
||||
facing = Direction.from3DDataValue(facingIndex);
|
||||
}
|
||||
|
||||
if (!directionProp.getPossibleValues().contains(facing)) {
|
||||
facing = player.getDirection().getOpposite();
|
||||
}
|
||||
|
||||
if (facing != origFacing && directionProp.getPossibleValues().contains(facing)) {
|
||||
if (state.getBlock() instanceof BedBlock) {
|
||||
BlockPos headPos = blockPos.relative(facing);
|
||||
|
||||
if (!context.getLevel().getBlockState(headPos).canBeReplaced(context)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
state = state.setValue(directionProp, facing);
|
||||
}
|
||||
} else if (state.hasProperty(BlockStateProperties.AXIS)) {
|
||||
Direction.Axis axis = Direction.Axis.VALUES[protocolValue % 3];
|
||||
state = state.setValue(BlockStateProperties.AXIS, axis);
|
||||
}
|
||||
|
||||
protocolValue &= 0xFFFFFFF0;
|
||||
|
||||
if (protocolValue >= 16) {
|
||||
if (block instanceof RepeaterBlock) {
|
||||
Integer delay = (protocolValue / 16);
|
||||
|
||||
if (RepeaterBlock.DELAY.getPossibleValues().contains(delay)) {
|
||||
state = state.setValue(RepeaterBlock.DELAY, delay);
|
||||
}
|
||||
} else if (protocolValue == 16) {
|
||||
if (block instanceof ComparatorBlock) {
|
||||
state = state.setValue(ComparatorBlock.MODE, ComparatorMode.SUBTRACT);
|
||||
} else if (state.hasProperty(BlockStateProperties.HALF) && state.getValue(BlockStateProperties.HALF) == Half.BOTTOM) {
|
||||
state = state.setValue(BlockStateProperties.HALF, Half.TOP);
|
||||
} else if (state.hasProperty(BlockStateProperties.SLAB_TYPE) && state.getValue(BlockStateProperties.SLAB_TYPE) == SlabType.BOTTOM) {
|
||||
state = state.setValue(BlockStateProperties.SLAB_TYPE, SlabType.TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BlockState alternativeBlockPlacementFix(Block block, @NotNull BlockPlaceContext context) {
|
||||
Direction facing;
|
||||
Vec3 vec3d = context.getClickLocation();
|
||||
BlockPos pos = context.getClickedPos();
|
||||
double hitX = vec3d.x - pos.getX();
|
||||
if (hitX < 2) {
|
||||
return null;
|
||||
}
|
||||
int code = (int) (hitX - 2) / 2;
|
||||
Player placer = Objects.requireNonNull(context.getPlayer());
|
||||
Level world = context.getLevel();
|
||||
|
||||
if (block instanceof GlazedTerracottaBlock) {
|
||||
facing = Direction.from3DDataValue(code);
|
||||
if (facing == Direction.UP || facing == Direction.DOWN) {
|
||||
facing = placer.getDirection().getOpposite();
|
||||
}
|
||||
return block.defaultBlockState().setValue(GlazedTerracottaBlock.FACING, facing);
|
||||
} else if (block instanceof ObserverBlock) {
|
||||
return block.defaultBlockState().setValue(ObserverBlock.FACING, Direction.from3DDataValue(code)).setValue(ObserverBlock.POWERED, true);
|
||||
} else if (block instanceof RepeaterBlock) {
|
||||
facing = Direction.from3DDataValue(code % 16);
|
||||
if (facing == Direction.UP || facing == Direction.DOWN) {
|
||||
facing = placer.getDirection().getOpposite();
|
||||
}
|
||||
return block.defaultBlockState().setValue(RepeaterBlock.FACING, facing).setValue(RepeaterBlock.DELAY, Mth.clamp(code / 16, 1, 4)).setValue(RepeaterBlock.LOCKED, Boolean.FALSE);
|
||||
} else if (block instanceof TrapDoorBlock) {
|
||||
facing = Direction.from3DDataValue(code % 16);
|
||||
if (facing == Direction.UP || facing == Direction.DOWN) {
|
||||
facing = placer.getDirection().getOpposite();
|
||||
}
|
||||
return block.defaultBlockState().setValue(TrapDoorBlock.FACING, facing).setValue(TrapDoorBlock.OPEN, Boolean.FALSE).setValue(TrapDoorBlock.HALF, (code >= 16) ? Half.TOP : Half.BOTTOM).setValue(TrapDoorBlock.OPEN, world.hasNeighborSignal(pos));
|
||||
} else if (block instanceof ComparatorBlock) {
|
||||
facing = Direction.from3DDataValue(code % 16);
|
||||
if ((facing == Direction.UP) || (facing == Direction.DOWN)) {
|
||||
facing = placer.getDirection().getOpposite();
|
||||
}
|
||||
ComparatorMode m = (hitX >= 16) ? ComparatorMode.SUBTRACT : ComparatorMode.COMPARE;
|
||||
return block.defaultBlockState().setValue(ComparatorBlock.FACING, facing).setValue(ComparatorBlock.POWERED, Boolean.FALSE).setValue(ComparatorBlock.MODE, m);
|
||||
} else if (block instanceof DispenserBlock) {
|
||||
return block.defaultBlockState().setValue(DispenserBlock.FACING, Direction.from3DDataValue(code)).setValue(DispenserBlock.TRIGGERED, Boolean.FALSE);
|
||||
} else if (block instanceof PistonBaseBlock) {
|
||||
return block.defaultBlockState().setValue(DirectionalBlock.FACING, Direction.from3DDataValue(code)).setValue(PistonBaseBlock.EXTENDED, Boolean.FALSE);
|
||||
} else if (block instanceof StairBlock) {
|
||||
return Objects.requireNonNull(block.getStateForPlacement(context)).setValue(StairBlock.FACING, Direction.from3DDataValue(code % 16)).setValue(StairBlock.HALF, (hitX >= 16) ? Half.TOP : Half.BOTTOM);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public static EnumProperty<Direction> getFirstDirectionProperty(@NotNull BlockState state) {
|
||||
for (Property<?> prop : state.getProperties()) {
|
||||
if (prop instanceof EnumProperty<?> enumProperty) {
|
||||
if (enumProperty.getValueClass().equals(Direction.class)) {
|
||||
return (EnumProperty<Direction>) enumProperty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.protocol;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BedBlock;
|
||||
import net.minecraft.world.level.block.RepeaterBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import net.minecraft.world.level.block.state.properties.SlabType;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class LitematicaEasyPlaceProtocol {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getClassLogger();
|
||||
|
||||
public static final ImmutableSet<Property<?>> WHITELISTED_PROPERTIES = ImmutableSet.of(
|
||||
BlockStateProperties.INVERTED,
|
||||
BlockStateProperties.OPEN,
|
||||
BlockStateProperties.BELL_ATTACHMENT,
|
||||
BlockStateProperties.AXIS,
|
||||
BlockStateProperties.HALF,
|
||||
BlockStateProperties.ATTACH_FACE,
|
||||
BlockStateProperties.CHEST_TYPE,
|
||||
BlockStateProperties.MODE_COMPARATOR,
|
||||
BlockStateProperties.DOOR_HINGE,
|
||||
BlockStateProperties.FACING,
|
||||
BlockStateProperties.FACING_HOPPER,
|
||||
BlockStateProperties.HORIZONTAL_FACING,
|
||||
BlockStateProperties.ORIENTATION,
|
||||
BlockStateProperties.RAIL_SHAPE,
|
||||
BlockStateProperties.RAIL_SHAPE_STRAIGHT,
|
||||
BlockStateProperties.SLAB_TYPE,
|
||||
BlockStateProperties.STAIRS_SHAPE,
|
||||
BlockStateProperties.BITES,
|
||||
BlockStateProperties.DELAY,
|
||||
BlockStateProperties.NOTE,
|
||||
BlockStateProperties.ROTATION_16
|
||||
);
|
||||
|
||||
public static BlockState applyPlacementProtocol(BlockState state, BlockPlaceContext context) {
|
||||
return applyPlacementProtocolV3(state, UseContext.from(context, context.getHand()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private static <T extends Comparable<T>> BlockState applyPlacementProtocolV3(BlockState state, @NotNull UseContext context) {
|
||||
int protocolValue = (int) (context.getHitVec().x - (double) context.getPos().getX()) - 2;
|
||||
BlockState oldState = state;
|
||||
if (protocolValue < 0) {
|
||||
return oldState;
|
||||
}
|
||||
|
||||
EnumProperty<Direction> property = CarpetAlternativeBlockPlacement.getFirstDirectionProperty(state);
|
||||
if (property != null && property != BlockStateProperties.VERTICAL_DIRECTION) {
|
||||
state = applyDirectionProperty(state, context, property, protocolValue);
|
||||
|
||||
if (state == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (state.canSurvive(context.getWorld(), context.getPos())) {
|
||||
oldState = state;
|
||||
} else {
|
||||
state = oldState;
|
||||
}
|
||||
|
||||
protocolValue >>>= 3;
|
||||
}
|
||||
|
||||
protocolValue >>>= 1;
|
||||
|
||||
List<Property<?>> propList = new ArrayList<>(state.getBlock().getStateDefinition().getProperties());
|
||||
propList.sort(Comparator.comparing(Property::getName));
|
||||
|
||||
try {
|
||||
for (Property<?> p : propList) {
|
||||
if (property != null && property.equals(p)) {
|
||||
continue;
|
||||
}
|
||||
if (!WHITELISTED_PROPERTIES.contains(p)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Property<T> prop = (Property<T>) p;
|
||||
List<T> list = new ArrayList<>(prop.getPossibleValues());
|
||||
list.sort(Comparable::compareTo);
|
||||
|
||||
int requiredBits = Mth.log2(Mth.smallestEncompassingPowerOfTwo(list.size()));
|
||||
int bitMask = ~(0xFFFFFFFF << requiredBits);
|
||||
int valueIndex = protocolValue & bitMask;
|
||||
|
||||
if (valueIndex < list.size()) {
|
||||
T value = list.get(valueIndex);
|
||||
|
||||
if (!state.getValue(prop).equals(value) && value != SlabType.DOUBLE) {
|
||||
state = state.setValue(prop, value);
|
||||
|
||||
if (state.canSurvive(context.getWorld(), context.getPos())) {
|
||||
oldState = state;
|
||||
} else {
|
||||
state = oldState;
|
||||
}
|
||||
}
|
||||
|
||||
protocolValue >>>= requiredBits;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Exception trying to apply placement protocol value", e);
|
||||
}
|
||||
|
||||
if (state.getBlock() instanceof RepeaterBlock repeaterBlock) {
|
||||
state = state.setValue(RepeaterBlock.LOCKED, repeaterBlock.isLocked(context.getWorld(), context.getPos(), state));
|
||||
}
|
||||
|
||||
if (state.canSurvive(context.getWorld(), context.getPos())) {
|
||||
return state;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static BlockState applyDirectionProperty(BlockState state, UseContext context, EnumProperty<Direction> property, int protocolValue) {
|
||||
Direction facingOrig = state.getValue(property);
|
||||
Direction facing = facingOrig;
|
||||
int decodedFacingIndex = (protocolValue & 0xF) >> 1;
|
||||
|
||||
if (decodedFacingIndex == 6) {
|
||||
facing = facing.getOpposite();
|
||||
} else if (decodedFacingIndex <= 5) {
|
||||
facing = Direction.from3DDataValue(decodedFacingIndex);
|
||||
|
||||
if (!property.getPossibleValues().contains(facing)) {
|
||||
facing = context.getEntity().getDirection().getOpposite();
|
||||
}
|
||||
}
|
||||
|
||||
if (facing != facingOrig && property.getPossibleValues().contains(facing)) {
|
||||
if (state.getBlock() instanceof BedBlock) {
|
||||
BlockPos headPos = context.pos.relative(facing);
|
||||
BlockPlaceContext ctx = context.getItemPlacementContext();
|
||||
|
||||
if (ctx == null || !context.getWorld().getBlockState(headPos).canBeReplaced(ctx)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
state = state.setValue(property, facing);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public static class UseContext {
|
||||
|
||||
private final Level world;
|
||||
private final BlockPos pos;
|
||||
private final Direction side;
|
||||
private final Vec3 hitVec;
|
||||
private final LivingEntity entity;
|
||||
private final InteractionHand hand;
|
||||
@Nullable
|
||||
private final BlockPlaceContext itemPlacementContext;
|
||||
|
||||
private UseContext(Level world, BlockPos pos, Direction side, Vec3 hitVec, LivingEntity entity, InteractionHand hand, @Nullable BlockPlaceContext itemPlacementContext) {
|
||||
this.world = world;
|
||||
this.pos = pos;
|
||||
this.side = side;
|
||||
this.hitVec = hitVec;
|
||||
this.entity = entity;
|
||||
this.hand = hand;
|
||||
this.itemPlacementContext = itemPlacementContext;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static UseContext from(@NotNull BlockPlaceContext ctx, InteractionHand hand) {
|
||||
Vec3 pos = ctx.getClickLocation();
|
||||
return new UseContext(ctx.getLevel(), ctx.getClickedPos(), ctx.getClickedFace(), new Vec3(pos.x, pos.y, pos.z), ctx.getPlayer(), hand, ctx);
|
||||
}
|
||||
|
||||
public Level getWorld() {
|
||||
return this.world;
|
||||
}
|
||||
|
||||
public BlockPos getPos() {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
public Direction getSide() {
|
||||
return this.side;
|
||||
}
|
||||
|
||||
public Vec3 getHitVec() {
|
||||
return this.hitVec;
|
||||
}
|
||||
|
||||
public LivingEntity getEntity() {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
public InteractionHand getHand() {
|
||||
return this.hand;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockPlaceContext getItemPlacementContext() {
|
||||
return this.itemPlacementContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user